From 8161d4ebd4a6e4bd137783c8d05ac75a9ab1b325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 22 Nov 2023 20:09:09 +0100 Subject: [PATCH 1/3] regenerate models --- src/external/backend-api/src/index.ts | 4 + .../CreateDictionaryItemRequestModel.ts | 1 + .../src/models/DataTypeItemResponseModel.ts | 2 +- .../models/DataTypeTreeItemResponseModel.ts | 2 +- .../src/models/PublishDocumentRequestModel.ts | 9 + ...lishDocumentWithDescendantsRequestModel.ts | 11 + .../models/ResendInviteUserRequestModel.ts | 10 + .../models/UnpublishDocumentRequestModel.ts | 9 + .../src/services/DocumentResource.ts | 279 ++++++++++++++++++ .../backend-api/src/services/UserResource.ts | 57 ++++ 10 files changed, 382 insertions(+), 2 deletions(-) create mode 100644 src/external/backend-api/src/models/PublishDocumentRequestModel.ts create mode 100644 src/external/backend-api/src/models/PublishDocumentWithDescendantsRequestModel.ts create mode 100644 src/external/backend-api/src/models/ResendInviteUserRequestModel.ts create mode 100644 src/external/backend-api/src/models/UnpublishDocumentRequestModel.ts diff --git a/src/external/backend-api/src/index.ts b/src/external/backend-api/src/index.ts index 972ec2bb32..961956c2ce 100644 --- a/src/external/backend-api/src/index.ts +++ b/src/external/backend-api/src/index.ts @@ -213,6 +213,8 @@ export type { PropertyTypeValidationModel } from './models/PropertyTypeValidatio export type { PublicAccessBaseModel } from './models/PublicAccessBaseModel'; export type { PublicAccessRequestModel } from './models/PublicAccessRequestModel'; export type { PublicAccessResponseModel } from './models/PublicAccessResponseModel'; +export type { PublishDocumentRequestModel } from './models/PublishDocumentRequestModel'; +export type { PublishDocumentWithDescendantsRequestModel } from './models/PublishDocumentWithDescendantsRequestModel'; export { PublishedStateModel } from './models/PublishedStateModel'; export type { RecycleBinItemResponseModel } from './models/RecycleBinItemResponseModel'; export { RedirectStatusModel } from './models/RedirectStatusModel'; @@ -223,6 +225,7 @@ export type { RelationResponseModel } from './models/RelationResponseModel'; export type { RelationTypeBaseModel } from './models/RelationTypeBaseModel'; export type { RelationTypeItemResponseModel } from './models/RelationTypeItemResponseModel'; export type { RelationTypeResponseModel } from './models/RelationTypeResponseModel'; +export type { ResendInviteUserRequestModel } from './models/ResendInviteUserRequestModel'; export type { ResetPasswordRequestModel } from './models/ResetPasswordRequestModel'; export type { ResetPasswordTokenRequestModel } from './models/ResetPasswordTokenRequestModel'; export type { RichTextRuleModel } from './models/RichTextRuleModel'; @@ -273,6 +276,7 @@ export type { TextFileViewModelBaseModel } from './models/TextFileViewModelBaseM export type { TourStatusModel } from './models/TourStatusModel'; export type { TreeItemPresentationModel } from './models/TreeItemPresentationModel'; export type { UnlockUsersRequestModel } from './models/UnlockUsersRequestModel'; +export type { UnpublishDocumentRequestModel } from './models/UnpublishDocumentRequestModel'; export type { UpdateContentForDocumentRequestModel } from './models/UpdateContentForDocumentRequestModel'; export type { UpdateContentForMediaRequestModel } from './models/UpdateContentForMediaRequestModel'; export type { UpdateContentTypeForDocumentTypeRequestModel } from './models/UpdateContentTypeForDocumentTypeRequestModel'; diff --git a/src/external/backend-api/src/models/CreateDictionaryItemRequestModel.ts b/src/external/backend-api/src/models/CreateDictionaryItemRequestModel.ts index 7227e1f230..ee60863e59 100644 --- a/src/external/backend-api/src/models/CreateDictionaryItemRequestModel.ts +++ b/src/external/backend-api/src/models/CreateDictionaryItemRequestModel.ts @@ -6,6 +6,7 @@ import type { DictionaryItemModelBaseModel } from './DictionaryItemModelBaseModel'; export type CreateDictionaryItemRequestModel = (DictionaryItemModelBaseModel & { + id?: string | null; parentId?: string | null; }); diff --git a/src/external/backend-api/src/models/DataTypeItemResponseModel.ts b/src/external/backend-api/src/models/DataTypeItemResponseModel.ts index 38c20ee12f..22f5a6e493 100644 --- a/src/external/backend-api/src/models/DataTypeItemResponseModel.ts +++ b/src/external/backend-api/src/models/DataTypeItemResponseModel.ts @@ -6,6 +6,6 @@ import type { ItemResponseModelBaseModel } from './ItemResponseModelBaseModel'; export type DataTypeItemResponseModel = (ItemResponseModelBaseModel & { - icon?: string | null; + editorUiAlias?: string | null; }); diff --git a/src/external/backend-api/src/models/DataTypeTreeItemResponseModel.ts b/src/external/backend-api/src/models/DataTypeTreeItemResponseModel.ts index 6d26e11b22..a24567b4f4 100644 --- a/src/external/backend-api/src/models/DataTypeTreeItemResponseModel.ts +++ b/src/external/backend-api/src/models/DataTypeTreeItemResponseModel.ts @@ -6,6 +6,6 @@ import type { FolderTreeItemResponseModel } from './FolderTreeItemResponseModel'; export type DataTypeTreeItemResponseModel = (FolderTreeItemResponseModel & { - icon?: string | null; + editorUiAlias?: string | null; }); diff --git a/src/external/backend-api/src/models/PublishDocumentRequestModel.ts b/src/external/backend-api/src/models/PublishDocumentRequestModel.ts new file mode 100644 index 0000000000..2cd7e31527 --- /dev/null +++ b/src/external/backend-api/src/models/PublishDocumentRequestModel.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type PublishDocumentRequestModel = { + cultures?: Array; +}; + diff --git a/src/external/backend-api/src/models/PublishDocumentWithDescendantsRequestModel.ts b/src/external/backend-api/src/models/PublishDocumentWithDescendantsRequestModel.ts new file mode 100644 index 0000000000..374b487d59 --- /dev/null +++ b/src/external/backend-api/src/models/PublishDocumentWithDescendantsRequestModel.ts @@ -0,0 +1,11 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +import type { PublishDocumentRequestModel } from './PublishDocumentRequestModel'; + +export type PublishDocumentWithDescendantsRequestModel = (PublishDocumentRequestModel & { + includeUnpublishedDescendants?: boolean; +}); + diff --git a/src/external/backend-api/src/models/ResendInviteUserRequestModel.ts b/src/external/backend-api/src/models/ResendInviteUserRequestModel.ts new file mode 100644 index 0000000000..a129e7bdcf --- /dev/null +++ b/src/external/backend-api/src/models/ResendInviteUserRequestModel.ts @@ -0,0 +1,10 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type ResendInviteUserRequestModel = { + userId?: string; + message?: string | null; +}; + diff --git a/src/external/backend-api/src/models/UnpublishDocumentRequestModel.ts b/src/external/backend-api/src/models/UnpublishDocumentRequestModel.ts new file mode 100644 index 0000000000..9d603f6694 --- /dev/null +++ b/src/external/backend-api/src/models/UnpublishDocumentRequestModel.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +export type UnpublishDocumentRequestModel = { + culture?: string | null; +}; + diff --git a/src/external/backend-api/src/services/DocumentResource.ts b/src/external/backend-api/src/services/DocumentResource.ts index a5eb2ae5a3..0f3789bcab 100644 --- a/src/external/backend-api/src/services/DocumentResource.ts +++ b/src/external/backend-api/src/services/DocumentResource.ts @@ -13,7 +13,10 @@ import type { PagedDocumentTreeItemResponseModel } from '../models/PagedDocument import type { PagedDocumentTypeResponseModel } from '../models/PagedDocumentTypeResponseModel'; import type { PagedRecycleBinItemResponseModel } from '../models/PagedRecycleBinItemResponseModel'; import type { PublicAccessRequestModel } from '../models/PublicAccessRequestModel'; +import type { PublishDocumentRequestModel } from '../models/PublishDocumentRequestModel'; +import type { PublishDocumentWithDescendantsRequestModel } from '../models/PublishDocumentWithDescendantsRequestModel'; import type { SortingRequestModel } from '../models/SortingRequestModel'; +import type { UnpublishDocumentRequestModel } from '../models/UnpublishDocumentRequestModel'; import type { UpdateDocumentNotificationsRequestModel } from '../models/UpdateDocumentNotificationsRequestModel'; import type { UpdateDocumentRequestModel } from '../models/UpdateDocumentRequestModel'; import type { UpdateDomainsRequestModel } from '../models/UpdateDomainsRequestModel'; @@ -346,6 +349,255 @@ export class DocumentResource { }); } + /** + * @returns string Created + * @throws ApiError + */ + public static postDocumentByIdPublicAccess1({ + id, + requestBody, + }: { + id: string, + requestBody?: PublicAccessRequestModel, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/umbraco/management/api/v2/document/{id}/public-access', + path: { + 'id': id, + }, + body: requestBody, + mediaType: 'application/json', + responseHeader: 'Location', + errors: { + 404: `Not Found`, + }, + }); + } + + /** + * @returns any Success + * @throws ApiError + */ + public static deleteDocumentByIdPublicAccess1({ + id, + }: { + id: string, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'DELETE', + url: '/umbraco/management/api/v2/document/{id}/public-access', + path: { + 'id': id, + }, + errors: { + 404: `Not Found`, + }, + }); + } + + /** + * @returns void + * @throws ApiError + */ + public static getDocumentByIdPublicAccess1({ + id, + }: { + id: string, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/umbraco/management/api/v2/document/{id}/public-access', + path: { + 'id': id, + }, + errors: { + 404: `Not Found`, + }, + }); + } + + /** + * @returns any Success + * @throws ApiError + */ + public static putDocumentByIdPublicAccess1({ + id, + requestBody, + }: { + id: string, + requestBody?: PublicAccessRequestModel, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'PUT', + url: '/umbraco/management/api/v2/document/{id}/public-access', + path: { + 'id': id, + }, + body: requestBody, + mediaType: 'application/json', + errors: { + 404: `Not Found`, + }, + }); + } + + /** + * @returns any Success + * @throws ApiError + */ + public static putDocumentByIdPublish({ + id, + requestBody, + }: { + id: string, + requestBody?: (PublishDocumentRequestModel | PublishDocumentWithDescendantsRequestModel), + }): CancelablePromise { + return __request(OpenAPI, { + method: 'PUT', + url: '/umbraco/management/api/v1/document/{id}/publish', + path: { + 'id': id, + }, + body: requestBody, + mediaType: 'application/json', + errors: { + 400: `Bad Request`, + 404: `Not Found`, + }, + }); + } + + /** + * @returns any Success + * @throws ApiError + */ + public static putDocumentByIdPublish1({ + id, + requestBody, + }: { + id: string, + requestBody?: (PublishDocumentRequestModel | PublishDocumentWithDescendantsRequestModel), + }): CancelablePromise { + return __request(OpenAPI, { + method: 'PUT', + url: '/umbraco/management/api/v2/document/{id}/publish', + path: { + 'id': id, + }, + body: requestBody, + mediaType: 'application/json', + errors: { + 400: `Bad Request`, + 404: `Not Found`, + }, + }); + } + + /** + * @returns any Success + * @throws ApiError + */ + public static putDocumentByIdPublishWithDescendants({ + id, + requestBody, + }: { + id: string, + requestBody?: PublishDocumentWithDescendantsRequestModel, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'PUT', + url: '/umbraco/management/api/v1/document/{id}/publish-with-descendants', + path: { + 'id': id, + }, + body: requestBody, + mediaType: 'application/json', + errors: { + 400: `Bad Request`, + 404: `Not Found`, + }, + }); + } + + /** + * @returns any Success + * @throws ApiError + */ + public static putDocumentByIdPublishWithDescendants1({ + id, + requestBody, + }: { + id: string, + requestBody?: PublishDocumentWithDescendantsRequestModel, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'PUT', + url: '/umbraco/management/api/v2/document/{id}/publish-with-descendants', + path: { + 'id': id, + }, + body: requestBody, + mediaType: 'application/json', + errors: { + 400: `Bad Request`, + 404: `Not Found`, + }, + }); + } + + /** + * @returns any Success + * @throws ApiError + */ + public static putDocumentByIdUnpublish({ + id, + requestBody, + }: { + id: string, + requestBody?: UnpublishDocumentRequestModel, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'PUT', + url: '/umbraco/management/api/v1/document/{id}/unpublish', + path: { + 'id': id, + }, + body: requestBody, + mediaType: 'application/json', + errors: { + 400: `Bad Request`, + 404: `Not Found`, + }, + }); + } + + /** + * @returns any Success + * @throws ApiError + */ + public static putDocumentByIdUnpublish1({ + id, + requestBody, + }: { + id: string, + requestBody?: UnpublishDocumentRequestModel, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'PUT', + url: '/umbraco/management/api/v2/document/{id}/unpublish', + path: { + 'id': id, + }, + body: requestBody, + mediaType: 'application/json', + errors: { + 400: `Bad Request`, + 404: `Not Found`, + }, + }); + } + /** * @returns PagedDocumentTypeResponseModel Success * @throws ApiError @@ -373,6 +625,33 @@ export class DocumentResource { }); } + /** + * @returns PagedDocumentTypeResponseModel Success + * @throws ApiError + */ + public static getDocumentAllowedDocumentTypes1({ + parentId, + skip, + take = 100, + }: { + parentId?: string, + skip?: number, + take?: number, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/umbraco/management/api/v2/document/allowed-document-types', + query: { + 'parentId': parentId, + 'skip': skip, + 'take': take, + }, + errors: { + 404: `Not Found`, + }, + }); + } + /** * @returns any Success * @throws ApiError diff --git a/src/external/backend-api/src/services/UserResource.ts b/src/external/backend-api/src/services/UserResource.ts index 66d93084ac..86fcfe8eba 100644 --- a/src/external/backend-api/src/services/UserResource.ts +++ b/src/external/backend-api/src/services/UserResource.ts @@ -14,6 +14,7 @@ import type { EnableUserRequestModel } from '../models/EnableUserRequestModel'; import type { InviteUserRequestModel } from '../models/InviteUserRequestModel'; import type { LinkedLoginsRequestModel } from '../models/LinkedLoginsRequestModel'; import type { PagedUserResponseModel } from '../models/PagedUserResponseModel'; +import type { ResendInviteUserRequestModel } from '../models/ResendInviteUserRequestModel'; import type { SetAvatarRequestModel } from '../models/SetAvatarRequestModel'; import type { UnlockUsersRequestModel } from '../models/UnlockUsersRequestModel'; import type { UpdateUserGroupsOnUserRequestModel } from '../models/UpdateUserGroupsOnUserRequestModel'; @@ -322,6 +323,24 @@ export class UserResource { }); } + /** + * @returns any Success + * @throws ApiError + */ + public static getUserCurrentPermissionsDocument1({ + id, + }: { + id?: Array, + }): CancelablePromise> { + return __request(OpenAPI, { + method: 'GET', + url: '/umbraco/management/api/v2/user/current/permissions/document', + query: { + 'id': id, + }, + }); + } + /** * @returns any Success * @throws ApiError @@ -340,6 +359,24 @@ export class UserResource { }); } + /** + * @returns any Success + * @throws ApiError + */ + public static getUserCurrentPermissionsMedia1({ + id, + }: { + id?: Array, + }): CancelablePromise> { + return __request(OpenAPI, { + method: 'GET', + url: '/umbraco/management/api/v2/user/current/permissions/media', + query: { + 'id': id, + }, + }); + } + /** * @returns any Success * @throws ApiError @@ -454,6 +491,26 @@ export class UserResource { }); } + /** + * @returns any Success + * @throws ApiError + */ + public static postUserInviteResend({ + requestBody, + }: { + requestBody?: ResendInviteUserRequestModel, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/umbraco/management/api/v1/user/invite/resend', + body: requestBody, + mediaType: 'application/json', + errors: { + 400: `Bad Request`, + }, + }); + } + /** * @returns any Success * @throws ApiError From bdcb9e0b7dac0dfaf590296b485cc5a62c0702c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 22 Nov 2023 21:12:01 +0100 Subject: [PATCH 2/3] simple publish and unpublish impl --- src/mocks/data/document.data.ts | 50 +++++++++++++++++++ .../handlers/document/document.handlers.ts | 18 +++++++ ...publishable-workspace-context.interface.ts | 1 + .../entity-actions/publish.action.ts | 5 +- .../entity-actions/unpublish.action.ts | 5 +- .../repository/document.repository.ts | 46 ++++++++++++----- .../sources/document.server.data.ts | 40 +++++++++++++++ .../actions/save-and-publish.action.ts | 7 +-- .../workspace/document-workspace.context.ts | 37 +++++++++++--- .../documents/workspace/manifests.ts | 4 +- 10 files changed, 184 insertions(+), 29 deletions(-) diff --git a/src/mocks/data/document.data.ts b/src/mocks/data/document.data.ts index 5e0446c3e4..a2eaab07bf 100644 --- a/src/mocks/data/document.data.ts +++ b/src/mocks/data/document.data.ts @@ -10,6 +10,7 @@ import { PagedDocumentTreeItemResponseModel, PagedDocumentTypeResponseModel, PagedRecycleBinItemResponseModel, + PublishDocumentRequestModel, } from '@umbraco-cms/backoffice/backend-api'; import { UMB_DOCUMENT_ENTITY_TYPE } from '@umbraco-cms/backoffice/document'; @@ -693,6 +694,55 @@ class UmbDocumentData extends UmbEntityData { return result; } + publish(id: string, data: PublishDocumentRequestModel) { + + // Update detail data: + const foundIndex = this.data.findIndex((item) => item.id === id); + if (foundIndex !== -1) { + // update + this.data[foundIndex].variants?.forEach((variant) => { + if (data.cultures?.includes(variant.culture ?? '')) { + variant.state = ContentStateModel.PUBLISHED; + } + }); + } + + // TODO: Tree data is not aware about variants and status of variants: so this is not good enough: + this.treeData = this.treeData.map((x) => { + if (x.id && x.id === id) { + return { ...x, isPublished: true }; + } else { + return x; + } + }); + return true; + } + + unpublish(id: string, data: PublishDocumentRequestModel) { + + // Update detail data: + const foundIndex = this.data.findIndex((item) => item.id === id); + if (foundIndex !== -1) { + // update + this.data[foundIndex].variants?.forEach((variant) => { + if (data.cultures?.includes(variant.culture ?? '')) { + variant.state = ContentStateModel.DRAFT; + } + }); + } + + // TODO: Tree data is not aware about variants and status of variants: so this is not good enough: + this.treeData = this.treeData.map((x) => { + if (x.id && x.id === id) { + return { ...x, isPublished: false }; + } else { + return x; + } + }); + + return true; + } + trash(ids: string[]): DocumentResponseModel[] { const result = super.trash(ids); this.treeData = this.treeData.map((x) => { diff --git a/src/mocks/handlers/document/document.handlers.ts b/src/mocks/handlers/document/document.handlers.ts index 88cf9e3791..a26f1edb40 100644 --- a/src/mocks/handlers/document/document.handlers.ts +++ b/src/mocks/handlers/document/document.handlers.ts @@ -15,6 +15,24 @@ export const handlers = [ return res(ctx.status(200)); }), + rest.put(umbracoPath('/document/:id/publish'), async (req, res, ctx) => { + const id = req.params.id as string; + if (!id) return; + const data = await req.json(); + if (!data) return; + umbDocumentData.publish(id, data); + return res(ctx.status(200)); + }), + + rest.put(umbracoPath('/document/:id/unpublish'), async (req, res, ctx) => { + const id = req.params.id as string; + if (!id) return; + const data = await req.json(); + if (!data) return; + umbDocumentData.unpublish(id, data); + return res(ctx.status(200)); + }), + rest.get(umbracoPath('/document/:id/allowed-document-types'), (req, res, ctx) => { const id = req.params.id as string; if (!id) return; diff --git a/src/packages/core/workspace/workspace-context/publishable-workspace-context.interface.ts b/src/packages/core/workspace/workspace-context/publishable-workspace-context.interface.ts index 2c562b628d..a8e07a9717 100644 --- a/src/packages/core/workspace/workspace-context/publishable-workspace-context.interface.ts +++ b/src/packages/core/workspace/workspace-context/publishable-workspace-context.interface.ts @@ -4,4 +4,5 @@ export interface UmbPublishableWorkspaceContextInterface extends UmbSaveableWorkspaceContextInterface { //getData(): EntityType | undefined; publish(): Promise; + unpublish(): Promise; } diff --git a/src/packages/documents/documents/entity-actions/publish.action.ts b/src/packages/documents/documents/entity-actions/publish.action.ts index fbdbcf7027..d00aba2a98 100644 --- a/src/packages/documents/documents/entity-actions/publish.action.ts +++ b/src/packages/documents/documents/entity-actions/publish.action.ts @@ -8,7 +8,8 @@ export class UmbPublishDocumentEntityAction extends UmbEntityActionBase) { + if (!id) throw new Error('id is missing'); + if (!variantIds) throw new Error('variant IDs are missing'); + await this.#init; + + const { error } = await this.#detailDataSource.saveAndPublish(id, variantIds); + + if (!error) { + // TODO: Update other stores based on above effect. + + const notification = { data: { message: `Document published` } }; + this.#notificationContext?.peek('positive', notification); + } + + return { error }; + } + + async unpublish(id: string, variantIds: Array) { + if (!id) throw new Error('id is missing'); + if (!variantIds) throw new Error('variant IDs are missing'); + await this.#init; + + const { error } = await this.#detailDataSource.unpublish(id, variantIds); + + if (!error) { + // TODO: Update other stores based on above effect. + + const notification = { data: { message: `Document unpublished` } }; + this.#notificationContext?.peek('positive', notification); + } + + return { error }; } async saveAndPreview() { @@ -260,14 +288,6 @@ export class UmbDocumentRepository alert('set public access'); } - async publish() { - alert('publish'); - } - - async unpublish() { - alert('unpublish'); - } - async rollback() { alert('rollback'); } diff --git a/src/packages/documents/documents/repository/sources/document.server.data.ts b/src/packages/documents/documents/repository/sources/document.server.data.ts index 4d20a5e1a4..98acdb0944 100644 --- a/src/packages/documents/documents/repository/sources/document.server.data.ts +++ b/src/packages/documents/documents/repository/sources/document.server.data.ts @@ -6,9 +6,12 @@ import { ContentStateModel, CreateDocumentRequestModel, UpdateDocumentRequestModel, + PublishDocumentRequestModel, + UnpublishDocumentRequestModel, } from '@umbraco-cms/backoffice/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; /** * A data source for the Document that fetches data from the server @@ -114,6 +117,43 @@ export class UmbDocumentServerDataSource return tryExecuteAndNotify(this.#host, DocumentResource.putDocumentById({ id, requestBody })); } + + /** + * Publish one or more variants of a Document + * @param {string} id + * @param {Array} variantIds + * @return {*} + * @memberof UmbDocumentServerDataSource + */ + async saveAndPublish(id: string, variantIds: Array) { + if (!id) throw new Error('Id is missing'); + + // TODO: THIS DOES NOT TAKE SEGMENTS INTO ACCOUNT!!!!!! + const requestBody: PublishDocumentRequestModel = { + cultures: variantIds.map((variant) => variant.toCultureString()), + }; + + return tryExecuteAndNotify(this.#host, DocumentResource.putDocumentByIdPublish({ id, requestBody })); + } + + /** + * Unpublish one or more variants of a Document + * @param {string} id + * @param {Array} variantIds + * @return {*} + * @memberof UmbDocumentServerDataSource + */ + async unpublish(id: string, variantIds: Array) { + if (!id) throw new Error('Id is missing'); + + // TODO: THIS DOES NOT TAKE SEGMENTS INTO ACCOUNT!!!!!! + const requestBody: UnpublishDocumentRequestModel = { + culture: variantIds.map((variant) => variant.toCultureString())[0], + }; + + return tryExecuteAndNotify(this.#host, DocumentResource.putDocumentByIdUnpublish({ id, requestBody })); + } + /** * Moves a Document to the recycle bin on the server * @param {string} id diff --git a/src/packages/documents/documents/workspace/actions/save-and-publish.action.ts b/src/packages/documents/documents/workspace/actions/save-and-publish.action.ts index 622fe6a0f1..91caa2c9ec 100644 --- a/src/packages/documents/documents/workspace/actions/save-and-publish.action.ts +++ b/src/packages/documents/documents/workspace/actions/save-and-publish.action.ts @@ -9,10 +9,11 @@ export class UmbDocumentSaveAndPublishWorkspaceAction extends UmbWorkspaceAction async execute() { if (!this.workspaceContext) return; + // TODO: Revisit, its unclear to me why we check the data of the context, should not matter IMO. // TODO: it doesn't get the updated value - const document = this.workspaceContext.getData(); + //const document = this.workspaceContext.getData(); // TODO: handle errors - if (!document) return; - this.workspaceContext.repository.saveAndPublish(); + //if (!document) return; + this.workspaceContext.publish(); } } diff --git a/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/packages/documents/documents/workspace/document-workspace.context.ts index 0b2f8561fd..6fbfc033e7 100644 --- a/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -9,6 +9,7 @@ import { UmbEditableWorkspaceContextBase, UmbWorkspaceSplitViewManager, UmbVariantableWorkspaceContextInterface, + UmbPublishableWorkspaceContextInterface, } from '@umbraco-cms/backoffice/workspace'; import type { CreateDocumentRequestModel, DocumentResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { @@ -23,7 +24,7 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; type EntityType = DocumentResponseModel; export class UmbDocumentWorkspaceContext extends UmbEditableWorkspaceContextBase - implements UmbVariantableWorkspaceContextInterface + implements UmbVariantableWorkspaceContextInterface, UmbPublishableWorkspaceContextInterface { /** * The document is the current stored version of the document. @@ -201,17 +202,41 @@ export class UmbDocumentWorkspaceContext this.saveComplete(this.getData()); } - async delete(id: string) { - await this.repository.delete(id); + async delete() { + const id = this.getEntityId(); + if(id) { + await this.repository.delete(id); + } } - /* - concept notes: - public saveAndPublish() { + public async publish() { + // TODO: This might be right to publish all, but we need a method that just publishes a declared range of variants. + const currentData = this.#currentData.value; + if(currentData) { + const variantIds = currentData.variants?.map((x) => UmbVariantId.Create(x)); + const id = this.getEntityId(); + if(variantIds && id) { + await this.repository.saveAndPublish(id, variantIds); + } + } + } + public async unpublish() { + // TODO: This might be right to unpublish all, but we need a method that just publishes a declared range of variants. + const currentData = this.#currentData.value; + if(currentData) { + const variantIds = currentData.variants?.map((x) => UmbVariantId.Create(x)); + const id = this.getEntityId(); + if(variantIds && id) { + await this.repository.unpublish(id, variantIds); + } + } } + /* + concept notes: + public saveAndPreview() { } diff --git a/src/packages/documents/documents/workspace/manifests.ts b/src/packages/documents/documents/workspace/manifests.ts index 9126a710cd..bc68d10e90 100644 --- a/src/packages/documents/documents/workspace/manifests.ts +++ b/src/packages/documents/documents/workspace/manifests.ts @@ -80,7 +80,6 @@ const workspaceViewCollections: Array = [ ]; const workspaceActions: Array = [ - /* { type: 'workspaceAction', alias: 'Umb.WorkspaceAction.Document.SaveAndPublish', @@ -99,7 +98,6 @@ const workspaceActions: Array = [ }, ], }, - */ { type: 'workspaceAction', alias: 'Umb.WorkspaceAction.Document.Save', @@ -108,7 +106,7 @@ const workspaceActions: Array = [ api: UmbSaveWorkspaceAction, meta: { label: 'Save', - look: 'primary', + look: 'secondary', color: 'positive', }, conditions: [ From cee6c8b7de31ac0542f65e4cbae43e01c6bd0fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 23 Nov 2023 13:54:44 +0100 Subject: [PATCH 3/3] correct save and publish --- ...publishable-workspace-context.interface.ts | 1 + .../repository/document.repository.ts | 21 ++++++++++++++++++- .../workspace/document-workspace.context.ts | 14 ++++++++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/packages/core/workspace/workspace-context/publishable-workspace-context.interface.ts b/src/packages/core/workspace/workspace-context/publishable-workspace-context.interface.ts index a8e07a9717..c435391d11 100644 --- a/src/packages/core/workspace/workspace-context/publishable-workspace-context.interface.ts +++ b/src/packages/core/workspace/workspace-context/publishable-workspace-context.interface.ts @@ -3,6 +3,7 @@ import type { UmbSaveableWorkspaceContextInterface } from './saveable-workspace- export interface UmbPublishableWorkspaceContextInterface extends UmbSaveableWorkspaceContextInterface { //getData(): EntityType | undefined; + saveAndPublish(): Promise; publish(): Promise; unpublish(): Promise; } diff --git a/src/packages/documents/documents/repository/document.repository.ts b/src/packages/documents/documents/repository/document.repository.ts index 1a2a68fe58..6afd5b74ba 100644 --- a/src/packages/documents/documents/repository/document.repository.ts +++ b/src/packages/documents/documents/repository/document.repository.ts @@ -218,7 +218,26 @@ export class UmbDocumentRepository return { error }; } - async saveAndPublish(id: string, variantIds: Array) { + async saveAndPublish(id: string, item: UpdateDocumentRequestModel, variantIds: Array) { + if (!id) throw new Error('id is missing'); + if (!variantIds) throw new Error('variant IDs are missing'); + //await this.#init; + + await this.save(id, item); + + const { error } = await this.#detailDataSource.saveAndPublish(id, variantIds); + + if (!error) { + // TODO: Update other stores based on above effect. + + const notification = { data: { message: `Document saved and published` } }; + this.#notificationContext?.peek('positive', notification); + } + + return { error }; + } + + async publish(id: string, variantIds: Array) { if (!id) throw new Error('id is missing'); if (!variantIds) throw new Error('variant IDs are missing'); await this.#init; diff --git a/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/packages/documents/documents/workspace/document-workspace.context.ts index 6fbfc033e7..fe551aeef5 100644 --- a/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -217,7 +217,19 @@ export class UmbDocumentWorkspaceContext const variantIds = currentData.variants?.map((x) => UmbVariantId.Create(x)); const id = this.getEntityId(); if(variantIds && id) { - await this.repository.saveAndPublish(id, variantIds); + await this.repository.publish(id, variantIds); + } + } + } + + public async saveAndPublish() { + // TODO: This might be right to publish all, but we need a method that just saves and publishes a declared range of variants. + const currentData = this.#currentData.value; + if(currentData) { + const variantIds = currentData.variants?.map((x) => UmbVariantId.Create(x)); + const id = currentData.id; + if(variantIds && id) { + await this.repository.saveAndPublish(id, currentData, variantIds); } } }