Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
89d8985
Documents: Use single-transaction create/update-and-publish endpoints…
iOvergaard Jun 1, 2026
c25740b
Merge remote-tracking branch 'origin/v17/improvement/save-and-publish…
iOvergaard Jun 1, 2026
3fb8ac4
Documents: Address review feedback on save-and-publish FE
iOvergaard Jun 1, 2026
149d77f
Documents: Drop redundant document re-read on save-and-publish
iOvergaard Jun 1, 2026
2eeb9d4
Documents: Fix spurious discard dialog after create-and-publish
iOvergaard Jun 3, 2026
368da35
Documents: Move create/update-and-publish into the publishing domain
iOvergaard Jun 3, 2026
3fa459b
Documents: Drop redundant context guard in save-and-publish orchestrator
iOvergaard Jun 3, 2026
9cbd92b
Documents: Reconcile current as well as persisted in finalizeCreate
iOvergaard Jun 3, 2026
ad059a0
Documents: Align finalizeUpdate with finalizeCreate and tighten metho…
iOvergaard Jun 5, 2026
95f7f16
Merge branch 'v17/improvement/save-and-publish-take-three' into v17/f…
iOvergaard Jun 5, 2026
1defc81
initial correction
nielslyngsoe Jun 17, 2026
ce26103
second round of refactor
nielslyngsoe Jun 18, 2026
119fe09
url-pattern-to-string tests
nielslyngsoe Jun 18, 2026
bfc51e7
url-pattern-to-string jsdocs
nielslyngsoe Jun 18, 2026
96c34ab
avoid discard changes dialog when navigating between create and edit
nielslyngsoe Jun 18, 2026
2f5ab7f
keep track of the absolute route as well
nielslyngsoe Jun 18, 2026
0342d33
check absolute path as part of dirty check
nielslyngsoe Jun 18, 2026
20b313e
check navigation util
nielslyngsoe Jun 18, 2026
0e82e21
added TODOs
nielslyngsoe Jun 18, 2026
f21b71b
clean up
nielslyngsoe Jun 19, 2026
60d7350
error handling
nielslyngsoe Jun 19, 2026
6fd51e5
error handling for schedule
nielslyngsoe Jun 19, 2026
10d6127
remove unused import
nielslyngsoe Jun 19, 2026
f3a5dac
rename to performDefault...
nielslyngsoe Jun 19, 2026
9a9b55a
rename
nielslyngsoe Jun 19, 2026
f2dbcde
rename and export interface
nielslyngsoe Jun 19, 2026
21f09df
simplify #applyPersistedData
nielslyngsoe Jun 19, 2026
0a86e25
fix(documents): avoid double notification on publish/schedule validat…
iOvergaard Jun 19, 2026
bba87c7
fix(documents): don't report publish failure when only the read-back …
iOvergaard Jun 19, 2026
0951f36
simplify comment
nielslyngsoe Jun 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions src/Umbraco.Web.UI.Client/mocks/db/document-publishing.manager.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { UmbMockDocumentModel } from '../data/mock-data-set.types.js';

Check warning on line 1 in src/Umbraco.Web.UI.Client/mocks/db/document-publishing.manager.ts

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (v17/improvement/save-and-publish-take-three)

❌ New issue: String Heavy Function Arguments

In this module, 46.7% of all arguments to its 9 functions are strings. The threshold for string arguments is 39.0% The functions in this file have a high ratio of strings as arguments. Avoid adding more.
import type { UmbDocumentMockDB } from './document.db.js';
import type {
CreateAndPublishDocumentRequestModel,
PublishDocumentRequestModel,
PublishDocumentWithDescendantsRequestModel,
UnpublishDocumentRequestModel,
UpdateAndPublishDocumentRequestModel,
} from '@umbraco-cms/backoffice/external/backend-api';
import { UmbId } from '@umbraco-cms/backoffice/id';
import type { DocumentVariantResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
Expand Down Expand Up @@ -55,6 +57,34 @@
this.#documentDb.detail.update(id, document);
}

createAndPublish(data: CreateAndPublishDocumentRequestModel) {
const id = this.#documentDb.detail.create(data);
this.#publishCultures(id, data.culturesToPublish);
return id;
}

updateAndPublish(id: string, data: UpdateAndPublishDocumentRequestModel) {
this.#documentDb.detail.update(id, data);
this.#publishCultures(id, data.culturesToPublish);
}

#publishCultures(id: string, culturesToPublish: Array<string>) {
const document: UmbMockDocumentModel = this.#documentDb.detail.read(id);

// Invariant content types publish with an empty cultures array; publish the invariant variant in that case.
const cultures: Array<string | null> = culturesToPublish.length > 0 ? culturesToPublish : [null];

cultures.forEach((culture) => {
const variant = document.variants.find((x) => x.culture === culture);
if (variant) {
variant.state = 'Published' as UmbDocumentVariantState;
variant.updateDate = new Date().toISOString();
}
});

this.#documentDb.detail.update(id, document);
}

publishWithDescendants(id: string, data: PublishDocumentWithDescendantsRequestModel) {
const document: UmbMockDocumentModel = this.#documentDb.detail.read(id);
const documents = this.getDescendants(id, []);
Expand All @@ -64,10 +94,7 @@
for (const culture of data.cultures) {
for (const d of documents) {
const variant = document.variants.find((x) => x.culture === culture);
if (
variant &&
(data.includeUnpublishedDescendants || variant.state !== 'Published')
) {
if (variant && (data.includeUnpublishedDescendants || variant.state !== 'Published')) {
variant.state = 'Published' as UmbDocumentVariantState;
variant.updateDate = new Date().toISOString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import { umbMockManager } from '../../mock-manager.js';
import { umbDocumentMockDb } from '../../db/document.db.js';
import { UMB_SLUG } from './slug.js';
import type {
CreateAndPublishDocumentRequestModel,
CreateDocumentRequestModel,
DefaultReferenceResponseModel,
GetDocumentByIdAvailableSegmentOptionsResponse,
GetDocumentByIdReferencedDescendantsResponse,
PagedIReferenceResponseModel,
UpdateAndPublishDocumentRequestModel,
UpdateDocumentRequestModel,
} from '@umbraco-cms/backoffice/external/backend-api';
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
Expand Down Expand Up @@ -38,6 +40,21 @@ export const detailHandlers = [
});
}),

http.post(umbracoPath(`${UMB_SLUG}/create-and-publish`), async ({ request }) => {
const requestBody = (await request.json()) as CreateAndPublishDocumentRequestModel;
if (!requestBody) return new HttpResponse(null, { status: 400, statusText: 'no body found' });

const id = umbDocumentMockDb.publishing.createAndPublish(requestBody);

return HttpResponse.json(null, {
status: 201,
headers: {
Location: request.url + '/' + id,
'Umb-Generated-Resource': id,
},
});
}),

http.get(umbracoPath(`${UMB_SLUG}/configuration`), () => {
return HttpResponse.json(umbDocumentMockDb.getConfiguration());
}),
Expand Down Expand Up @@ -155,6 +172,19 @@ export const detailHandlers = [
}
}),

http.put(umbracoPath(`${UMB_SLUG}/:id/update-and-publish`), async ({ request, params }) => {
const id = params.id as string;
if (!id) return new HttpResponse(null, { status: 400 });
if (id === 'forbidden') {
// Simulate a forbidden response
return new HttpResponse(null, { status: 403 });
}
const requestBody = (await request.json()) as UpdateAndPublishDocumentRequestModel;
if (!requestBody) return new HttpResponse(null, { status: 400, statusText: 'no body found' });
umbDocumentMockDb.publishing.updateAndPublish(id, requestBody);
return new HttpResponse(null, { status: 200 });
}),

http.put(umbracoPath(`${UMB_SLUG}/:id`), async ({ request, params }) => {
const id = params.id as string;
if (!id) return new HttpResponse(null, { status: 400 });
Expand Down
4 changes: 3 additions & 1 deletion src/Umbraco.Web.UI.Client/src/assets/lang/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1542,9 +1542,11 @@ export default {
cssSavedText: 'Stylesheet saved without any errors',
dataTypeSaved: 'Datatype saved',
dictionaryItemSaved: 'Dictionary item saved',
editContentPublishedFailed: 'Document could not be published or saved',
editContentPublishedFailedByValidation: 'Document could not be published, but we saved it for you',
editContentPublishedFailedByParent: 'Document could not be published, because a parent page is not published',
editContentPublishedHeader: 'Document published',
editContentPublishedReloadFailed: 'Document published, but the editor could not be refreshed',
editContentPublishedText: 'and is visible on the website',
editContentUnpublishedHeader: 'Document unpublished',
editContentUnpublishedText: 'and is no longer visible on the website',
Expand Down Expand Up @@ -2192,7 +2194,7 @@ export default {
updateDate: 'User last updated',
userCreated: 'has been created',
userCreatedSuccessHelp: 'The new user has successfully been created. To log in to Umbraco use the password below.',
userCreatedApiSuccessHelp: 'Set client credentials for the account via the user\'s profile.',
userCreatedApiSuccessHelp: "Set client credentials for the account via the user's profile.",
userHasPassword: 'The user already has a password set',
userHasGroup: "The user is already in group '%0%'",
userLockoutNotEnabled: 'Lockout is not enabled for this user',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { UmbBlockDataModel, UmbBlockDataValueModel, UmbBlockLayoutBaseModel } from '../types.js';

Check notice on line 1 in src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (v17/improvement/save-and-publish-take-three)

✅ Getting better: Overall Code Complexity

The mean cyclomatic complexity decreases from 5.04 to 5.00, threshold = 4 This file has many conditional statements (e.g. if, for, while) across its implementation, leading to lower code health. Avoid adding more conditionals.
import { UMB_BLOCK_ENTRIES_CONTEXT, UMB_BLOCK_MANAGER_CONTEXT } from '../context/index.js';
import { UmbBlockWorkspaceEditorElement } from './block-workspace-editor.element.js';
import { UmbBlockElementManager } from './block-element-manager.js';
Expand All @@ -12,6 +12,7 @@
UmbWorkspaceIsNewRedirectController,
type ManifestWorkspace,
UmbWorkspaceIsNewRedirectControllerAlias,
umbWorkspaceWillNavigateAway,
} from '@umbraco-cms/backoffice/workspace';
import {
UmbBooleanState,
Expand Down Expand Up @@ -362,10 +363,7 @@
* @memberof UmbEntityWorkspaceContextBase
*/
protected _checkWillNavigateAway(newUrl: string | URL): boolean {
if (newUrl instanceof URL) {
newUrl = newUrl.href;
}
return !newUrl.includes(this.routes.getActiveLocalPath());
return umbWorkspaceWillNavigateAway(this.routes, this.getUnique(), newUrl);
}

setEditorSize(editorSize: UUIModalSidebarSize) {
Expand Down
Loading