From 7cddc45e89417fa4c5454f3ecefbe967b1634e2f Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 31 Jul 2023 10:02:24 +0200 Subject: [PATCH 01/61] correct the type --- .../src/packages/templating/stylesheets/index.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts index 22804ab3ff..9bb36fdd52 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts @@ -1,9 +1,7 @@ -import { FileSystemTreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; +import { StylesheetResponseModel } from '@umbraco-cms/backoffice/backend-api'; // TODO: temp until we have a proper stylesheet model -export interface StylesheetDetails extends FileSystemTreeItemPresentationModel { - content: string; -} +export type StylesheetDetails = StylesheetResponseModel; export const STYLESHEET_ENTITY_TYPE = 'stylesheet'; export * from './repository/index.js'; From 076ea1f79ba425daf75e79e95343590312e0d1c8 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 31 Jul 2023 10:02:50 +0200 Subject: [PATCH 02/61] return the entity type from partial views --- .../partial-views/workspace/partial-views-workspace.context.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-views-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-views-workspace.context.ts index dd0e19057b..3c673c6c48 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-views-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-views-workspace.context.ts @@ -11,7 +11,7 @@ export class UmbPartialViewsWorkspaceContext extends UmbWorkspaceContext { const partialView = this.getData(); From 2d888b813e24e48a1607f278f2699e1743a0484b Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 31 Jul 2023 10:13:54 +0200 Subject: [PATCH 03/61] remove console.log --- .../partial-views/workspace/partial-views-workspace.context.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-views-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-views-workspace.context.ts index 3c673c6c48..6163c889fe 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-views-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-views-workspace.context.ts @@ -26,8 +26,7 @@ export class UmbPartialViewsWorkspaceContext extends UmbWorkspaceContext Date: Mon, 31 Jul 2023 10:14:14 +0200 Subject: [PATCH 04/61] add missing context methods --- .../workspace/stylesheet-workspace.context.ts | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index 245f9fca54..e49d7a966a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -2,26 +2,53 @@ import { UmbStylesheetRepository } from '../repository/stylesheet.repository.js' import { StylesheetDetails } from '../index.js'; import { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; -import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; +import { UmbBooleanState, UmbObjectState, createObservablePart } from '@umbraco-cms/backoffice/observable-api'; +import { loadCodeEditor } from '@umbraco-cms/backoffice/code-editor'; export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext { #data = new UmbObjectState(undefined); data = this.#data.asObservable(); + name = createObservablePart(this.#data, (data) => data?.name); + content = createObservablePart(this.#data, (data) => data?.content); + path = createObservablePart(this.#data, (data) => data?.path); + #isCodeEditorReady = new UmbBooleanState(false); + isCodeEditorReady = this.#isCodeEditorReady.asObservable(); + constructor(host: UmbControllerHostElement) { super(host, new UmbStylesheetRepository(host)); + this.#loadCodeEditor(); + } + async #loadCodeEditor() { + try { + await loadCodeEditor(); + this.#isCodeEditorReady.next(true); + } catch (error) { + console.error(error); + } + } + + getEntityType(): string { return 'stylesheet'; } + getEntityId() { + return this.getData()?.path || ''; + } + getData() { return this.#data.getValue(); } - getEntityId() { - return this.getData()?.path || ''; + setName(value: string) { + this.#data.next({ ...this.#data.value, name: value }); + } + + setContent(value: string) { + this.#data.next({ ...this.#data.value, content: value }); } async load(path: string) { @@ -36,6 +63,21 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext Date: Mon, 31 Jul 2023 10:50:24 +0200 Subject: [PATCH 05/61] add folder data source --- .../sources/stylesheet.folder.server.data.ts | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.folder.server.data.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.folder.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.folder.server.data.ts new file mode 100644 index 0000000000..4a36b6ea60 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.folder.server.data.ts @@ -0,0 +1,36 @@ +import { + CreateFolderRequestModel, + FolderModelBaseModel, + FolderReponseModel, + StylesheetResource, +} from '@umbraco-cms/backoffice/backend-api'; +import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; +import { DataSourceResponse, UmbFolderDataSource } from '@umbraco-cms/backoffice/repository'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; + +//! this is of any type in the backend-api +export type StylesheetGetFolderResponse = { path: string; parentPath: string; name: string }; + +export class UmbStylesheetFolderServerDataSource implements UmbFolderDataSource { + #host: UmbControllerHostElement; + + constructor(host: UmbControllerHostElement) { + this.#host = host; + } + + get(unique: string): Promise> { + return tryExecuteAndNotify(this.#host, StylesheetResource.getStylesheetFolder({ path: unique })); + } + insert(requestBody: CreateFolderRequestModel): Promise> { + return tryExecuteAndNotify(this.#host, StylesheetResource.postStylesheetFolder({ requestBody })); + } + delete(path: string): Promise> { + return tryExecuteAndNotify(this.#host, StylesheetResource.deleteStylesheetFolder({ path })); + } + update(unique: string, data: CreateFolderRequestModel): Promise> { + throw new Error('Method not implemented.'); + } + createScaffold(parentId: string | null): Promise> { + throw new Error('Method not implemented.'); + } +} From ce9db14c8571d2635618e982d2f92c06af2ed11c Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 31 Jul 2023 10:50:30 +0200 Subject: [PATCH 06/61] Update stylesheet-workspace.context.ts --- .../workspace/stylesheet-workspace.context.ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index e49d7a966a..b78255100f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -61,6 +61,30 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext Date: Mon, 31 Jul 2023 10:50:53 +0200 Subject: [PATCH 07/61] implement crud source details methods --- .../sources/stylesheet.server.data.ts | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.server.data.ts index e0844ce428..de80e00bbe 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.server.data.ts @@ -1,6 +1,12 @@ import type { StylesheetDetails } from '../../index.js'; import { DataSourceResponse, UmbDataSource } from '@umbraco-cms/backoffice/repository'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; +import { + CreateStylesheetRequestModel, + StylesheetResource, + UpdateStylesheetRequestModel, +} from '@umbraco-cms/backoffice/backend-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; /** * A data source for the Stylesheet that fetches data from the server @@ -8,7 +14,9 @@ import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api * @class UmbStylesheetServerDataSource * @implements {UmbStylesheetServerDataSource} */ -export class UmbStylesheetServerDataSource implements UmbDataSource { +export class UmbStylesheetServerDataSource + implements UmbDataSource +{ #host: UmbControllerHostElement; /** @@ -31,17 +39,16 @@ export class UmbStylesheetServerDataSource implements UmbDataSource> { - throw new Error('Method not implemented.'); + insert(data: StylesheetDetails): Promise> { + return tryExecuteAndNotify(this.#host, StylesheetResource.postStylesheet({ requestBody: data })); } update(path: string, data: StylesheetDetails): Promise> { - throw new Error('Method not implemented.'); + return tryExecuteAndNotify(this.#host, StylesheetResource.putStylesheet({ requestBody: data })); } delete(path: string): Promise { - throw new Error('Method not implemented.'); + return tryExecuteAndNotify(this.#host, StylesheetResource.deleteStylesheet({ path })); } } From 5c0573ea7950a5a3e7c554f9786b8f434072768a Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 31 Jul 2023 11:06:04 +0200 Subject: [PATCH 08/61] add docs and rules endpoints --- .../sources/stylesheet.server.data.ts | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.server.data.ts index de80e00bbe..43edfa7ac1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.server.data.ts @@ -3,6 +3,11 @@ import { DataSourceResponse, UmbDataSource } from '@umbraco-cms/backoffice/repos import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { CreateStylesheetRequestModel, + ExtractRichTextStylesheetRulesRequestModel, + ExtractRichTextStylesheetRulesResponseModel, + InterpolateRichTextStylesheetRequestModel, + InterpolateRichTextStylesheetResponseModel, + RichTextStylesheetRulesResponseModel, StylesheetResource, UpdateStylesheetRequestModel, } from '@umbraco-cms/backoffice/backend-api'; @@ -41,14 +46,77 @@ export class UmbStylesheetServerDataSource if (!path) throw new Error('Path is missing'); return tryExecuteAndNotify(this.#host, StylesheetResource.getStylesheet({ path })); } - + /** + * Creates a new Stylesheet + * + * @param {StylesheetDetails} data + * @return {*} {Promise>} + * @memberof UmbStylesheetServerDataSource + */ insert(data: StylesheetDetails): Promise> { return tryExecuteAndNotify(this.#host, StylesheetResource.postStylesheet({ requestBody: data })); } + /** + * Updates an existing Stylesheet + * + * @param {string} path + * @param {StylesheetDetails} data + * @return {*} {Promise>} + * @memberof UmbStylesheetServerDataSource + */ update(path: string, data: StylesheetDetails): Promise> { return tryExecuteAndNotify(this.#host, StylesheetResource.putStylesheet({ requestBody: data })); } + /** + * Deletes a Stylesheet. + * + * @param {string} path + * @return {*} {Promise} + * @memberof UmbStylesheetServerDataSource + */ delete(path: string): Promise { return tryExecuteAndNotify(this.#host, StylesheetResource.deleteStylesheet({ path })); } + /** + * Get's the rich text rules for a stylesheet + * + * @param {string} path + * @return {*} {(Promise>)} + * @memberof UmbStylesheetServerDataSource + */ + getStylesheetRichTextRules( + path: string + ): Promise> { + return tryExecuteAndNotify(this.#host, StylesheetResource.getStylesheetRichTextRules({ path })); + } + /** + * Extracts the rich text rules from a stylesheet string. In simple words: takes a stylesheet string and returns a array of rules. + * + * @param {ExtractRichTextStylesheetRulesRequestModel} data + * @return {*} {Promise>} + * @memberof UmbStylesheetServerDataSource + */ + postStylesheetRichTextExtractRules( + data: ExtractRichTextStylesheetRulesRequestModel + ): Promise> { + return tryExecuteAndNotify( + this.#host, + StylesheetResource.postStylesheetRichTextExtractRules({ requestBody: data }) + ); + } + /** + * Interpolates the rich text rules from a stylesheet string. In simple words: takes a array of rules and existing content. Returns new content with the rules applied. + * + * @param {InterpolateRichTextStylesheetRequestModel} data + * @return {*} {Promise>} + * @memberof UmbStylesheetServerDataSource + */ + postStylesheetRichTextInterpolateRules( + data: InterpolateRichTextStylesheetRequestModel + ): Promise> { + return tryExecuteAndNotify( + this.#host, + StylesheetResource.postStylesheetRichTextInterpolateRules({ requestBody: data }) + ); + } } From e1668c3d2824916a9054d07ee409ad9c796181b8 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 31 Jul 2023 11:27:01 +0200 Subject: [PATCH 09/61] implement repository interfaceces --- .../repository/stylesheet.repository.ts | 100 ++++++++++++++++-- 1 file changed, 89 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts index 5e1a4e41b2..8887f031ea 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts @@ -3,17 +3,41 @@ import { UmbStylesheetTreeServerDataSource } from './sources/stylesheet.tree.ser import { UmbStylesheetServerDataSource } from './sources/stylesheet.server.data.js'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; -import { UmbTreeRepository } from '@umbraco-cms/backoffice/repository'; -import { FileSystemTreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; +import { + DataSourceResponse, + UmbDataSourceErrorResponse, + UmbDetailRepository, + UmbFolderRepository, + UmbTreeRepository, +} from '@umbraco-cms/backoffice/repository'; +import { + CreateFolderRequestModel, + CreateStylesheetRequestModel, + CreateTextFileViewModelBaseModel, + FileSystemTreeItemPresentationModel, + FolderModelBaseModel, + FolderReponseModel, + ProblemDetails, + TextFileResponseModelBaseModel, + UpdateStylesheetRequestModel, + UpdateTextFileViewModelBaseModel, +} from '@umbraco-cms/backoffice/backend-api'; import type { UmbTreeRootFileSystemModel } from '@umbraco-cms/backoffice/tree'; +import { StylesheetDetails } from '../index.js'; +import { Observable } from 'rxjs'; +import { UmbStylesheetFolderServerDataSource } from './sources/stylesheet.folder.server.data.js'; export class UmbStylesheetRepository - implements UmbTreeRepository + implements + UmbTreeRepository, + UmbDetailRepository, + UmbFolderRepository { #host; #dataSource; #treeDataSource; #treeStore?: UmbStylesheetTreeStore; + #folderDataSource; #init; constructor(host: UmbControllerHostElement) { @@ -22,13 +46,73 @@ export class UmbStylesheetRepository // TODO: figure out how spin up get the correct data source this.#dataSource = new UmbStylesheetServerDataSource(this.#host); this.#treeDataSource = new UmbStylesheetTreeServerDataSource(this.#host); + this.#folderDataSource = new UmbStylesheetFolderServerDataSource(this.#host); this.#init = new UmbContextConsumerController(this.#host, UMB_STYLESHEET_TREE_STORE_CONTEXT_TOKEN, (instance) => { this.#treeStore = instance; }).asPromise(); } - // TREE: + //#region FOLDER: + + createFolderScaffold( + parentId: string | null + ): Promise<{ data?: FolderReponseModel | undefined; error?: ProblemDetails | undefined }> { + throw new Error('Method not implemented.'); + } + createFolder( + folderRequest: CreateFolderRequestModel + ): Promise<{ data?: string | undefined; error?: ProblemDetails | undefined }> { + throw new Error('Method not implemented.'); + } + requestFolder( + unique: string + ): Promise<{ data?: FolderReponseModel | undefined; error?: ProblemDetails | undefined }> { + throw new Error('Method not implemented.'); + } + updateFolder( + unique: string, + folder: FolderModelBaseModel + ): Promise<{ data?: FolderModelBaseModel | undefined; error?: ProblemDetails | undefined }> { + throw new Error('Method not implemented.'); + } + deleteFolder(id: string): Promise<{ error?: ProblemDetails | undefined }> { + throw new Error('Method not implemented.'); + } + + //#endregion + + //#region DETAIL: + + createScaffold( + parentId: string | null, + preset?: Partial | undefined + ): Promise> { + throw new Error('Method not implemented.'); + } + + async requestById(id: string): Promise> { + if (!id) throw new Error('id is missing'); + await this.#init; + const { data, error } = await this.#dataSource.get(id); + return { data, error }; + } + byId(id: string): Promise> { + throw new Error('Method not implemented.'); + } + create(data: CreateTextFileViewModelBaseModel): Promise> { + throw new Error('Method not implemented.'); + } + save(id: string, data: UpdateTextFileViewModelBaseModel): Promise { + throw new Error('Method not implemented.'); + } + delete(id: string): Promise { + throw new Error('Method not implemented.'); + } + + //#endregion + + //#region TREE: async requestTreeRoot() { await this.#init; @@ -93,11 +177,5 @@ export class UmbStylesheetRepository return this.#treeStore!.items(paths); } - // DETAILS - async requestByPath(path: string) { - if (!path) throw new Error('Path is missing'); - await this.#init; - const { data, error } = await this.#dataSource.get(path); - return { data, error }; - } + //#endregion } From 0fbdfb31cdf0d2ba58fc9af1c41f9fca125ec3c6 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 31 Jul 2023 11:35:57 +0200 Subject: [PATCH 10/61] implement folder methods --- .../repository/stylesheet.repository.ts | 40 ++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts index 8887f031ea..5cfbeb0ebf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts @@ -25,7 +25,10 @@ import { import type { UmbTreeRootFileSystemModel } from '@umbraco-cms/backoffice/tree'; import { StylesheetDetails } from '../index.js'; import { Observable } from 'rxjs'; -import { UmbStylesheetFolderServerDataSource } from './sources/stylesheet.folder.server.data.js'; +import { + StylesheetGetFolderResponse, + UmbStylesheetFolderServerDataSource, +} from './sources/stylesheet.folder.server.data.js'; export class UmbStylesheetRepository implements @@ -58,17 +61,31 @@ export class UmbStylesheetRepository createFolderScaffold( parentId: string | null ): Promise<{ data?: FolderReponseModel | undefined; error?: ProblemDetails | undefined }> { - throw new Error('Method not implemented.'); + const data: FolderReponseModel = { + name: '', + parentId, + }; + return Promise.resolve({ data, error: undefined }); } - createFolder( + + async createFolder( folderRequest: CreateFolderRequestModel ): Promise<{ data?: string | undefined; error?: ProblemDetails | undefined }> { - throw new Error('Method not implemented.'); + await this.#init; + const req = { + parentPath: folderRequest.parentId, + name: folderRequest.name, + }; + const promise = this.#folderDataSource.insert(req); + await promise; + this.requestTreeItemsOf(folderRequest.parentId ? folderRequest.parentId : null); + return promise; } - requestFolder( + async requestFolder( unique: string - ): Promise<{ data?: FolderReponseModel | undefined; error?: ProblemDetails | undefined }> { - throw new Error('Method not implemented.'); + ): Promise<{ data?: StylesheetGetFolderResponse | undefined; error?: ProblemDetails | undefined }> { + await this.#init; + return this.#folderDataSource.get(unique); } updateFolder( unique: string, @@ -76,8 +93,13 @@ export class UmbStylesheetRepository ): Promise<{ data?: FolderModelBaseModel | undefined; error?: ProblemDetails | undefined }> { throw new Error('Method not implemented.'); } - deleteFolder(id: string): Promise<{ error?: ProblemDetails | undefined }> { - throw new Error('Method not implemented.'); + async deleteFolder(path: string): Promise<{ error?: ProblemDetails | undefined }> { + await this.#init; + const { data } = await this.requestFolder(path); + const promise = this.#folderDataSource.delete(path); + await promise; + this.requestTreeItemsOf(data?.parentPath ? data?.parentPath : null); + return promise; } //#endregion From e72b0ff2ae1cb8163be2cf943ca39fabe9735502 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 31 Jul 2023 11:41:21 +0200 Subject: [PATCH 11/61] implement stylesheet rules methods in repository --- .../repository/stylesheet.repository.ts | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts index 5cfbeb0ebf..bbb53ad195 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts @@ -14,10 +14,15 @@ import { CreateFolderRequestModel, CreateStylesheetRequestModel, CreateTextFileViewModelBaseModel, + ExtractRichTextStylesheetRulesRequestModel, + ExtractRichTextStylesheetRulesResponseModel, FileSystemTreeItemPresentationModel, FolderModelBaseModel, FolderReponseModel, + InterpolateRichTextStylesheetRequestModel, + InterpolateRichTextStylesheetResponseModel, ProblemDetails, + RichTextStylesheetRulesResponseModel, TextFileResponseModelBaseModel, UpdateStylesheetRequestModel, UpdateTextFileViewModelBaseModel, @@ -122,14 +127,38 @@ export class UmbStylesheetRepository byId(id: string): Promise> { throw new Error('Method not implemented.'); } - create(data: CreateTextFileViewModelBaseModel): Promise> { - throw new Error('Method not implemented.'); + async create(data: CreateTextFileViewModelBaseModel): Promise> { + const promise = this.#dataSource.insert(data); + await promise; + this.requestTreeItemsOf(data.parentPath ? data.parentPath : null); + return promise; } save(id: string, data: UpdateTextFileViewModelBaseModel): Promise { - throw new Error('Method not implemented.'); + return this.#dataSource.update(id, data); } delete(id: string): Promise { - throw new Error('Method not implemented.'); + const promise = this.#dataSource.delete(id); + const parentPath = id.substring(0, id.lastIndexOf('/')); + this.requestTreeItemsOf(parentPath ? parentPath : null); + return promise; + } + + getStylesheetRules( + path: string + ): Promise> { + return this.#dataSource.getStylesheetRichTextRules(path); + } + + interpolateStylesheetRules( + data: InterpolateRichTextStylesheetRequestModel + ): Promise> { + return this.#dataSource.postStylesheetRichTextInterpolateRules(data); + } + + extractStylesheetRules( + data: ExtractRichTextStylesheetRulesRequestModel + ): Promise> { + return this.#dataSource.postStylesheetRichTextExtractRules(data); } //#endregion From 007ccfb254aed4a0c15b16b2cb3cddc854cf5c7f Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 31 Jul 2023 13:59:21 +0200 Subject: [PATCH 12/61] Update stylesheet-workspace.context.ts --- .../stylesheets/workspace/stylesheet-workspace.context.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index b78255100f..00c1b6c264 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -52,7 +52,7 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext Date: Mon, 31 Jul 2023 15:21:25 +0200 Subject: [PATCH 13/61] add some handlers --- .../src/mocks/data/stylesheet.data.ts | 103 ++++++++++++++++-- .../src/mocks/handlers/stylesheet.handlers.ts | 34 +++++- 2 files changed, 128 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts index 05548ef529..f23c5d19f9 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts @@ -1,13 +1,13 @@ import { UmbEntityData } from './entity.data.js'; -import { createFileSystemTreeItem } from './utils.js'; +import { createFileSystemTreeItem, createTextFileItem } from './utils.js'; import { + CreateTextFileViewModelBaseModel, FileSystemTreeItemPresentationModel, PagedFileSystemTreeItemPresentationModel, + StylesheetResponseModel, } from '@umbraco-cms/backoffice/backend-api'; -type StylesheetDBItem = FileSystemTreeItemPresentationModel & { - content: string; -}; +type StylesheetDBItem = StylesheetResponseModel & FileSystemTreeItemPresentationModel; export const data: Array = [ { @@ -16,7 +16,26 @@ export const data: Array = [ name: 'Stylesheet File 1.css', type: 'stylesheet', hasChildren: false, - content: `Stylesheet content 1`, + content: ` + h1 { + color: blue; + } + + /**umb_name:bjjh*/ + h1 { + color: blue; + } + + /**umb_name:comeone*/ + h1 { + color: blue; + } + + /**umb_name:lol*/ + h1 { + color: blue; + } + `, }, { path: 'Stylesheet File 2.css', @@ -24,7 +43,24 @@ export const data: Array = [ name: 'Stylesheet File 2.css', type: 'stylesheet', hasChildren: false, - content: `Stylesheet content 2`, + content: ` h1 { + color: green; + } + + /**umb_name:bjjh*/ + h1 { + color: green; + } + + /**umb_name:comeone*/ + h1 { + color: green; + } + + /**umb_name:lol*/ + h1 { + color: green; + }`, }, { path: 'Folder 1', @@ -32,7 +68,24 @@ export const data: Array = [ name: 'Folder 1', type: 'stylesheet', hasChildren: true, - content: `Stylesheet content 3`, + content: ` h1 { + color: pink; + } + + /**umb_name:bjjh*/ + h1 { + color: pink; + } + + /**umb_name:comeone*/ + h1 { + color: pink; + } + + /**umb_name:lol*/ + h1 { + color: pink; + }`, }, { path: 'Folder 1/Stylesheet File 3.css', @@ -40,7 +93,24 @@ export const data: Array = [ name: 'Stylesheet File 3.css', type: 'stylesheet', hasChildren: false, - content: `Stylesheet content 3`, + content: ` h1 { + color: red; + } + + /**umb_name:bjjh*/ + h1 { + color: red; + } + + /**umb_name:comeone*/ + h1 { + color: red; + } + + /**umb_name:lol*/ + h1 { + color: red; + }`, }, ]; @@ -71,6 +141,23 @@ class UmbStylesheetData extends UmbEntityData { const items = this.data.filter((item) => paths.includes(item.path ?? '')); return items.map((item) => createFileSystemTreeItem(item)); } + + getStylesheet(path: string): StylesheetDBItem | undefined { + return createTextFileItem(this.data.find((item) => item.path === path)); + } + + insertStyleSheet(item: CreateTextFileViewModelBaseModel) { + const newItem: StylesheetDBItem = { + ...item, + path: `${item.parentPath}/${item.name}.cshtml}`, + isFolder: false, + hasChildren: false, + type: 'partial-view', + }; + + this.insert(newItem); + return newItem; + } } export const umbStylesheetData = new UmbStylesheetData(); diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts index b4f3c3caff..c657affed5 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts @@ -1,8 +1,9 @@ const { rest } = window.MockServiceWorker; +import { CreateTextFileViewModelBaseModel } from '@umbraco-cms/backoffice/backend-api'; import { umbStylesheetData } from '../data/stylesheet.data.js'; import { umbracoPath } from '@umbraco-cms/backoffice/utils'; -export const handlers = [ +const treeHandlers = [ rest.get(umbracoPath('/tree/stylesheet/root'), (req, res, ctx) => { const response = umbStylesheetData.getTreeRoot(); return res(ctx.status(200), ctx.json(response)); @@ -24,3 +25,34 @@ export const handlers = [ return res(ctx.status(200), ctx.json(items)); }), ]; + +const detailHandlers = [ + rest.get(umbracoPath('/v1/stylesheet'), (req, res, ctx) => { + const path = req.url.searchParams.get('path'); + if (!path) return; + + const response = umbStylesheetData.getStylesheet(path); + return res(ctx.status(200), ctx.json(response)); + }), + rest.post(umbracoPath('/partial-view'), (req, res, ctx) => { + const requestBody = req.json() as CreateTextFileViewModelBaseModel; + if (!requestBody) return res(ctx.status(400, 'no body found')); + const response = umbStylesheetData.insertStyleSheet(requestBody); + return res(ctx.status(200), ctx.json(response)); + }), + + rest.delete(umbracoPath('/partial-view'), (req, res, ctx) => { + const path = req.url.searchParams.get('path'); + if (!path) return res(ctx.status(400)); + const response = umbStylesheetData.delete([path]); + return res(ctx.status(200), ctx.json(response)); + }), + rest.put(umbracoPath('/partial-view'), (req, res, ctx) => { + const requestBody = req.json() as CreateTextFileViewModelBaseModel; + if (!requestBody) return res(ctx.status(400, 'no body found')); + const response = umbStylesheetData.updateData(requestBody); + return res(ctx.status(200)); + }), +]; + +export const handlers = [...treeHandlers, ...detailHandlers]; From b547e523e991ae80f174b0cf0ddbcb04fe1a7ce7 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Thu, 3 Aug 2023 14:07:39 +0200 Subject: [PATCH 14/61] add views --- .../src/mocks/data/stylesheet.data.ts | 48 ++++++++++++-- .../src/mocks/data/utils.ts | 6 ++ .../src/mocks/handlers/stylesheet.handlers.ts | 48 ++++++++++++-- .../stylesheets/workspace/manifests.ts | 35 +++++++++- .../stylesheet-workspace-edit.element.ts | 66 +++++++++++++++++-- ...heet-workspace-view-code-editor.element.ts | 21 ++++++ ...workspace-view-rich-text-editor.element.ts | 21 ++++++ 7 files changed, 228 insertions(+), 17 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts index f23c5d19f9..2893fbe822 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts @@ -1,17 +1,19 @@ import { UmbEntityData } from './entity.data.js'; -import { createFileSystemTreeItem, createTextFileItem } from './utils.js'; +import { createFileSystemTreeItem, createItem, createTextFileItem } from './utils.js'; import { CreateTextFileViewModelBaseModel, FileSystemTreeItemPresentationModel, PagedFileSystemTreeItemPresentationModel, + PagedStylesheetOverviewResponseModel, StylesheetResponseModel, } from '@umbraco-cms/backoffice/backend-api'; -type StylesheetDBItem = StylesheetResponseModel & FileSystemTreeItemPresentationModel; +type StylesheetDBItem = StylesheetResponseModel & FileSystemTreeItemPresentationModel & { icon?: string }; export const data: Array = [ { path: 'Stylesheet File 1.css', + icon: 'style', isFolder: false, name: 'Stylesheet File 1.css', type: 'stylesheet', @@ -40,6 +42,8 @@ export const data: Array = [ { path: 'Stylesheet File 2.css', isFolder: false, + icon: 'style', + name: 'Stylesheet File 2.css', type: 'stylesheet', hasChildren: false, @@ -65,6 +69,8 @@ export const data: Array = [ { path: 'Folder 1', isFolder: true, + icon: 'folder', + name: 'Folder 1', type: 'stylesheet', hasChildren: true, @@ -90,6 +96,8 @@ export const data: Array = [ { path: 'Folder 1/Stylesheet File 3.css', isFolder: false, + icon: 'style', + name: 'Stylesheet File 3.css', type: 'stylesheet', hasChildren: false, @@ -142,17 +150,47 @@ class UmbStylesheetData extends UmbEntityData { return items.map((item) => createFileSystemTreeItem(item)); } - getStylesheet(path: string): StylesheetDBItem | undefined { + getStylesheetItem(path: string): StylesheetDBItem | undefined { + return createItem(this.data.find((item) => item.path === path)); + } + + getStylesheet(path: string): StylesheetResponseModel | undefined { return createTextFileItem(this.data.find((item) => item.path === path)); } + getAllStylesheets(): PagedStylesheetOverviewResponseModel { + return { + items: this.data.map((item) => createTextFileItem(item)), + total: this.data.map((item) => !item.isFolder).length, + }; + } + + getFolder(path: string): StylesheetDBItem | undefined { + return this.data.find((item) => item.path === path && item.isFolder === true); + } + + insertFolder(item: CreateTextFileViewModelBaseModel) { + const newItem: StylesheetDBItem = { + ...item, + path: `${item.parentPath}/${item.name}`, + isFolder: true, + hasChildren: false, + type: 'stylesheet', + icon: 'folder', + }; + + this.insert(newItem); + return newItem; + } + insertStyleSheet(item: CreateTextFileViewModelBaseModel) { const newItem: StylesheetDBItem = { ...item, - path: `${item.parentPath}/${item.name}.cshtml}`, + path: `${item.parentPath}/${item.name}.css`, isFolder: false, hasChildren: false, - type: 'partial-view', + type: 'stylesheet', + icon: 'style', }; this.insert(newItem); diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/utils.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/utils.ts index df924c2e71..32caed7acf 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/utils.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/utils.ts @@ -80,3 +80,9 @@ export const createTextFileItem = (item: any): TextFileResponseModelBaseModel => name: item.name, content: item.content, }); + +export const createItem = (item: any): any => ({ + path: item.path, + name: item.name, + icon: item.icon, +}); diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts index c657affed5..daa04b5623 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts @@ -1,6 +1,6 @@ const { rest } = window.MockServiceWorker; -import { CreateTextFileViewModelBaseModel } from '@umbraco-cms/backoffice/backend-api'; import { umbStylesheetData } from '../data/stylesheet.data.js'; +import { CreateTextFileViewModelBaseModel } from '@umbraco-cms/backoffice/backend-api'; import { umbracoPath } from '@umbraco-cms/backoffice/utils'; const treeHandlers = [ @@ -27,32 +27,68 @@ const treeHandlers = [ ]; const detailHandlers = [ - rest.get(umbracoPath('/v1/stylesheet'), (req, res, ctx) => { + rest.get(umbracoPath('/stylesheet'), (req, res, ctx) => { const path = req.url.searchParams.get('path'); if (!path) return; const response = umbStylesheetData.getStylesheet(path); return res(ctx.status(200), ctx.json(response)); }), - rest.post(umbracoPath('/partial-view'), (req, res, ctx) => { + rest.post(umbracoPath('/stylesheet'), (req, res, ctx) => { const requestBody = req.json() as CreateTextFileViewModelBaseModel; if (!requestBody) return res(ctx.status(400, 'no body found')); const response = umbStylesheetData.insertStyleSheet(requestBody); return res(ctx.status(200), ctx.json(response)); }), - rest.delete(umbracoPath('/partial-view'), (req, res, ctx) => { + rest.delete(umbracoPath('/stylesheet'), (req, res, ctx) => { const path = req.url.searchParams.get('path'); if (!path) return res(ctx.status(400)); const response = umbStylesheetData.delete([path]); return res(ctx.status(200), ctx.json(response)); }), - rest.put(umbracoPath('/partial-view'), (req, res, ctx) => { + rest.put(umbracoPath('/stylesheet'), (req, res, ctx) => { const requestBody = req.json() as CreateTextFileViewModelBaseModel; if (!requestBody) return res(ctx.status(400, 'no body found')); const response = umbStylesheetData.updateData(requestBody); return res(ctx.status(200)); }), + rest.get(umbracoPath('/v1/stylesheet/all'), (req, res, ctx) => { + const path = req.url.searchParams.get('path'); + if (!path) return; + + const response = umbStylesheetData.getAllStylesheets(); + return res(ctx.status(200), ctx.json(response)); + }), + rest.get(umbracoPath('/v1/stylesheet/item'), (req, res, ctx) => { + const paths = req.url.searchParams.getAll('path'); + if (!paths) return; + + const items = umbStylesheetData.getStylesheetItem(paths[0]); + return res(ctx.status(200), ctx.json(items)); + }), ]; -export const handlers = [...treeHandlers, ...detailHandlers]; +const folderHandlers = [ + rest.get(umbracoPath('/v1/stylesheet/all'), (req, res, ctx) => { + const path = req.url.searchParams.get('path'); + if (!path) return; + + const response = umbStylesheetData.getFolder(path); + return res(ctx.status(200), ctx.json(response)); + }), + rest.post(umbracoPath('/stylesheet/folder'), (req, res, ctx) => { + const requestBody = req.json() as CreateTextFileViewModelBaseModel; + if (!requestBody) return res(ctx.status(400, 'no body found')); + const response = umbStylesheetData.insertFolder(requestBody); + return res(ctx.status(200), ctx.json(response)); + }), + rest.delete(umbracoPath('/stylesheet/folder'), (req, res, ctx) => { + const path = req.url.searchParams.get('path'); + if (!path) return res(ctx.status(400)); + const response = umbStylesheetData.delete([path]); + return res(ctx.status(200), ctx.json(response)); + }), +]; + +export const handlers = [...treeHandlers, ...detailHandlers, ...folderHandlers]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts index f341fbee8f..f2238b5937 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts @@ -14,7 +14,38 @@ const workspace: ManifestWorkspace = { }, }; -const workspaceViews: Array = []; +const workspaceEditorViews: Array = [ + { + type: 'workspaceEditorView', + alias: 'Umb.WorkspaceView.Stylesheet.CodeEditor', + name: 'Stylesheet Workspace Code Editor View', + loader: () => import('./views/code-editor/stylesheet-workspace-view-code-editor.element.js'), + weight: 700, + meta: { + label: 'Code', + pathname: 'code', + icon: 'umb:brackets', + }, + conditions: { + workspaces: ['Umb.Workspace.StyleSheet'], + }, + }, + { + type: 'workspaceEditorView', + alias: 'Umb.WorkspaceView.Stylesheet.RichTextEditor', + name: 'Stylesheet Workspace Rich Text Editor View', + loader: () => import('./views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.js'), + weight: 800, + meta: { + label: 'Rich Text Editor', + pathname: 'rich-text-editor', + icon: 'umb:font', + }, + conditions: { + workspaces: ['Umb.Workspace.StyleSheet'], + }, + }, +]; const workspaceActions: Array = []; -export const manifests = [workspace, ...workspaceViews, ...workspaceActions]; +export const manifests = [workspace, ...workspaceEditorViews, ...workspaceActions]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts index a9d15b63d8..eae185aa4a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts @@ -1,10 +1,68 @@ -import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui'; -import { css, html, LitElement, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UUIInputElement, UUIInputEvent, UUITextStyles } from '@umbraco-cms/backoffice/external/uui'; +import { css, html, LitElement, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbStylesheetWorkspaceContext } from './stylesheet-workspace.context.js'; +import { UMB_MODAL_MANAGER_CONTEXT_TOKEN, UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; +import { UMB_ENTITY_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; @customElement('umb-stylesheet-workspace-edit') -export class UmbStylesheetWorkspaceEditElement extends LitElement { +export class UmbStylesheetWorkspaceEditElement extends UmbLitElement { + #workspaceContext?: UmbStylesheetWorkspaceContext; + + @state() + private _name?: string; + + @state() + private _path?: string; + + private _modalContext?: UmbModalManagerContext; + + constructor() { + super(); + + this.consumeContext(UMB_ENTITY_WORKSPACE_CONTEXT, (instance) => { + this.#workspaceContext = instance as UmbStylesheetWorkspaceContext; + }); + + this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { + this._modalContext = instance; + }); + } + + #onNameChange(event: UUIInputEvent) { + if (event instanceof UUIInputEvent) { + const target = event.composedPath()[0] as UUIInputElement; + + if (typeof target?.value === 'string') { + const oldName = this._name; + const newName = event.target.value.toString(); + this.#workspaceContext?.setName(target.value); + } + } + } + render() { - return html` Stylesheet workspace `; + return html` + + + +
+ + + Keyboard Shortcuts + + ALT + + + shift + + + k + + +
+
+ `; } static styles = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts new file mode 100644 index 0000000000..fee430117a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts @@ -0,0 +1,21 @@ +import { UUITextStyles } from '@umbraco-ui/uui-css'; +import { css, html } from 'lit'; +import { customElement } from 'lit/decorators.js'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; + +@customElement('umb-stylesheet-workspace-view-code-editor') +export class UmbStylesheetWorkspaceViewCodeEditorElement extends UmbLitElement { + render() { + return html`umb-stylesheet-workspace-view-code-editor`; + } + + static styles = [UUITextStyles, css``]; +} + +export default UmbStylesheetWorkspaceViewCodeEditorElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-stylesheet-workspace-view-code-editor': UmbStylesheetWorkspaceViewCodeEditorElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts new file mode 100644 index 0000000000..8ebb040a0f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts @@ -0,0 +1,21 @@ +import { UUITextStyles } from '@umbraco-ui/uui-css'; +import { css, html } from 'lit'; +import { customElement } from 'lit/decorators.js'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; + +@customElement('umb-stylesheet-workspace-view-rich-text-editor') +export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitElement { + render() { + return html`umb-stylesheet-workspace-view-RICH_TEXT-editor`; + } + + static styles = [UUITextStyles, css``]; +} + +export default UmbStylesheetWorkspaceViewRichTextEditorElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-stylesheet-workspace-view-code-editor': UmbStylesheetWorkspaceViewRichTextEditorElement; + } +} From 8b45a1c937b4c221ee48d02b71562f04434c1f3b Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Thu, 3 Aug 2023 14:13:59 +0200 Subject: [PATCH 15/61] add path and name and save action --- .../stylesheets/workspace/manifests.ts | 18 ++++++++++++++++- .../stylesheet-workspace-edit.element.ts | 20 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts index f2238b5937..195b540c50 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts @@ -3,6 +3,7 @@ import type { ManifestWorkspaceAction, ManifestWorkspaceEditorView, } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbSaveWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; const workspace: ManifestWorkspace = { type: 'workspace', @@ -46,6 +47,21 @@ const workspaceEditorViews: Array = [ }, }, ]; -const workspaceActions: Array = []; +const workspaceActions: Array = [ + { + type: 'workspaceAction', + alias: 'Umb.WorkspaceAction.Stylesheet.Save', + name: 'Save Stylesheet Workspace Action', + meta: { + label: 'Save', + look: 'primary', + color: 'positive', + api: UmbSaveWorkspaceAction, + }, + conditions: { + workspaces: ['Umb.Workspace.DocumentType'], + }, + }, +]; export const manifests = [workspace, ...workspaceEditorViews, ...workspaceActions]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts index eae185aa4a..d779149251 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts @@ -22,6 +22,7 @@ export class UmbStylesheetWorkspaceEditElement extends UmbLitElement { this.consumeContext(UMB_ENTITY_WORKSPACE_CONTEXT, (instance) => { this.#workspaceContext = instance as UmbStylesheetWorkspaceContext; + this.#observeNameAndPath(); }); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { @@ -29,6 +30,12 @@ export class UmbStylesheetWorkspaceEditElement extends UmbLitElement { }); } + #observeNameAndPath() { + if (!this.#workspaceContext) return; + this.observe(this.#workspaceContext.name, (name) => (this._name = name)); + this.observe(this.#workspaceContext.path, (path) => (this._path = path)); + } + #onNameChange(event: UUIInputEvent) { if (event instanceof UUIInputEvent) { const target = event.composedPath()[0] as UUIInputElement; @@ -46,6 +53,7 @@ export class UmbStylesheetWorkspaceEditElement extends UmbLitElement {
@@ -73,6 +81,18 @@ export class UmbStylesheetWorkspaceEditElement extends UmbLitElement { width: 100%; height: 100%; } + + #header { + display: flex; + flex: 1 1 auto; + flex-direction: column; + } + + #name { + width: 100%; + flex: 1 1 auto; + align-items: center; + } `, ]; } From f9138711a584892965deabf1756a1396adc983df Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Thu, 3 Aug 2023 14:45:37 +0200 Subject: [PATCH 16/61] add code editor --- .../stylesheets/workspace/manifests.ts | 2 +- .../stylesheet-workspace-edit.element.ts | 2 - .../workspace/stylesheet-workspace.element.ts | 1 + ...heet-workspace-view-code-editor.element.ts | 104 +++++++++++++++++- ...workspace-view-rich-text-editor.element.ts | 2 +- 5 files changed, 103 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts index 195b540c50..f20d29a5d6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts @@ -59,7 +59,7 @@ const workspaceActions: Array = [ api: UmbSaveWorkspaceAction, }, conditions: { - workspaces: ['Umb.Workspace.DocumentType'], + workspaces: ['Umb.Workspace.StyleSheet'], }, }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts index d779149251..fa5970de99 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts @@ -41,8 +41,6 @@ export class UmbStylesheetWorkspaceEditElement extends UmbLitElement { const target = event.composedPath()[0] as UUIInputElement; if (typeof target?.value === 'string') { - const oldName = this._name; - const newName = event.target.value.toString(); this.#workspaceContext?.setName(target.value); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts index e4b3882c19..5bc8de5657 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts @@ -20,6 +20,7 @@ export class UmbStylesheetWorkspaceElement extends UmbLitElement { setup: (_component, info) => { const path = info.match.params.path; const serverPath = serverFilePathFromUrlFriendlyPath(path); + console.log('load'); this.#workspaceContext.load(serverPath); new UmbWorkspaceIsNewRedirectController( diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts index fee430117a..326b50e8ad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts @@ -1,15 +1,111 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; import { css, html } from 'lit'; -import { customElement } from 'lit/decorators.js'; +import { customElement, query, state } from 'lit/decorators.js'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor'; +import { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; +import { UmbStylesheetWorkspaceContext } from '../../stylesheet-workspace.context.js'; @customElement('umb-stylesheet-workspace-view-code-editor') export class UmbStylesheetWorkspaceViewCodeEditorElement extends UmbLitElement { - render() { - return html`umb-stylesheet-workspace-view-code-editor`; + @state() + private _content?: string | null = ''; + + @state() + private _path?: string | null = ''; + + @state() + private _ready?: boolean = false; + + @query('umb-code-editor') + private _codeEditor?: UmbCodeEditorElement; + + #stylesheetWorkspaceContext?: UmbStylesheetWorkspaceContext; + private _modalContext?: UmbModalManagerContext; + + #isNew = false; + + constructor() { + super(); + + //tODO: should this be called something else here? + this.consumeContext('UmbEntityWorkspaceContext', (workspaceContext: UmbStylesheetWorkspaceContext) => { + this.#stylesheetWorkspaceContext = workspaceContext; + + this.observe(this.#stylesheetWorkspaceContext.content, (content) => { + this._content = content; + }); + + this.observe(this.#stylesheetWorkspaceContext.path, (path) => { + this._path = path; + }); + + this.observe(this.#stylesheetWorkspaceContext.isNew, (isNew) => { + this.#isNew = !!isNew; + }); + + this.observe(this.#stylesheetWorkspaceContext.isCodeEditorReady, (isReady) => { + this._ready = isReady; + }); + }); } - static styles = [UUITextStyles, css``]; + #onCodeEditorInput(event: Event) { + const target = event.target as UmbCodeEditorElement; + const value = target.code as string; + this.#stylesheetWorkspaceContext?.setContent(value); + } + + #renderCodeEditor() { + return html``; + } + + render() { + return html` +
+ ${this._ready + ? this.#renderCodeEditor() + : html`
+ +
`} +
`; + } + + static styles = [ + UUITextStyles, + css` + :host { + display: block; + width: 100%; + } + + #loader-container { + display: grid; + place-items: center; + min-height: calc(100dvh - 300px); + } + + umb-code-editor { + --editor-height: calc(100dvh - 300px); + } + + uui-box { + min-height: calc(100dvh - 360px); + margin: var(--uui-size-layout-1); + --uui-box-default-padding: 0; + /* remove header border bottom as code editor looks better in this box */ + --uui-color-divider-standalone: transparent; + } + + #workspace-header { + width: 100%; + } + `, + ]; } export default UmbStylesheetWorkspaceViewCodeEditorElement; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts index 8ebb040a0f..2e49b60893 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts @@ -16,6 +16,6 @@ export default UmbStylesheetWorkspaceViewRichTextEditorElement; declare global { interface HTMLElementTagNameMap { - 'umb-stylesheet-workspace-view-code-editor': UmbStylesheetWorkspaceViewRichTextEditorElement; + 'umb-stylesheet-workspace-view-rich-text-editor': UmbStylesheetWorkspaceViewRichTextEditorElement; } } From 4f6dda5513e692d650fd3c1ab223e093a6408e03 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Fri, 4 Aug 2023 12:44:10 +0200 Subject: [PATCH 17/61] commit --- .../src/mocks/data/stylesheet.data.ts | 27 ------------------- .../stylesheets/workspace/manifests.ts | 27 ++++++++++++------- .../stylesheet-workspace-edit.element.ts | 8 +++--- .../workspace/stylesheet-workspace.element.ts | 25 ++++++++++++----- 4 files changed, 40 insertions(+), 47 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts index 2893fbe822..1fcfd1b7fb 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts @@ -93,33 +93,6 @@ export const data: Array = [ color: pink; }`, }, - { - path: 'Folder 1/Stylesheet File 3.css', - isFolder: false, - icon: 'style', - - name: 'Stylesheet File 3.css', - type: 'stylesheet', - hasChildren: false, - content: ` h1 { - color: red; - } - - /**umb_name:bjjh*/ - h1 { - color: red; - } - - /**umb_name:comeone*/ - h1 { - color: red; - } - - /**umb_name:lol*/ - h1 { - color: red; - }`, - }, ]; // Temp mocked database diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts index f20d29a5d6..1e342aeae9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts @@ -27,9 +27,12 @@ const workspaceEditorViews: Array = [ pathname: 'code', icon: 'umb:brackets', }, - conditions: { - workspaces: ['Umb.Workspace.StyleSheet'], - }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.StyleSheet', + }, + ], }, { type: 'workspaceEditorView', @@ -42,9 +45,12 @@ const workspaceEditorViews: Array = [ pathname: 'rich-text-editor', icon: 'umb:font', }, - conditions: { - workspaces: ['Umb.Workspace.StyleSheet'], - }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.StyleSheet', + }, + ], }, ]; const workspaceActions: Array = [ @@ -58,9 +64,12 @@ const workspaceActions: Array = [ color: 'positive', api: UmbSaveWorkspaceAction, }, - conditions: { - workspaces: ['Umb.Workspace.StyleSheet'], - }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.StyleSheet', + }, + ], }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts index fa5970de99..20f7bcc45b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts @@ -1,8 +1,8 @@ import { UUIInputElement, UUIInputEvent, UUITextStyles } from '@umbraco-cms/backoffice/external/uui'; -import { css, html, LitElement, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbStylesheetWorkspaceContext } from './stylesheet-workspace.context.js'; import { UMB_MODAL_MANAGER_CONTEXT_TOKEN, UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; -import { UMB_ENTITY_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; +import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; @customElement('umb-stylesheet-workspace-edit') @@ -20,7 +20,7 @@ export class UmbStylesheetWorkspaceEditElement extends UmbLitElement { constructor() { super(); - this.consumeContext(UMB_ENTITY_WORKSPACE_CONTEXT, (instance) => { + this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => { this.#workspaceContext = instance as UmbStylesheetWorkspaceContext; this.#observeNameAndPath(); }); @@ -50,7 +50,7 @@ export class UmbStylesheetWorkspaceEditElement extends UmbLitElement { return html` diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts index 5bc8de5657..444c06101a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts @@ -14,20 +14,31 @@ export class UmbStylesheetWorkspaceElement extends UmbLitElement { @state() _routes: UmbRoute[] = [ + // { + // path: 'create/:parentId', + // component: () => this.#element, + // setup: async (_component, info) => { + // const path = info.match.params.path; + // const serverPath = serverFilePathFromUrlFriendlyPath(path); + // this.#workspaceContext.setIsNew(false); + // console.log('load'); + // await this.#workspaceContext.load(serverPath); + + // new UmbWorkspaceIsNewRedirectController( + // this, + // this.#workspaceContext, + // this.shadowRoot!.querySelector('umb-router-slot')! + // ); + // }, + // }, { path: 'edit/:path', component: () => this.#element, setup: (_component, info) => { + this.removeControllerByAlias('_observeIsNew'); const path = info.match.params.path; const serverPath = serverFilePathFromUrlFriendlyPath(path); - console.log('load'); this.#workspaceContext.load(serverPath); - - new UmbWorkspaceIsNewRedirectController( - this, - this.#workspaceContext, - this.shadowRoot!.querySelector('umb-router-slot')! - ); }, }, ]; From fe3acd927d4a54e85f71e718cd5f0f9508dedf0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 4 Aug 2023 13:08:00 +0200 Subject: [PATCH 18/61] use alias reference from workspace manifest --- .../packages/templating/stylesheets/workspace/manifests.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts index 1e342aeae9..d2786fb7ea 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts @@ -30,7 +30,7 @@ const workspaceEditorViews: Array = [ conditions: [ { alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.StyleSheet', + match: workspace.alias, }, ], }, @@ -48,7 +48,7 @@ const workspaceEditorViews: Array = [ conditions: [ { alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.StyleSheet', + match: workspace.alias, }, ], }, @@ -67,7 +67,7 @@ const workspaceActions: Array = [ conditions: [ { alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.StyleSheet', + match: workspace.alias, }, ], }, From 4e08419743375810bc3f0319bd5b0a673e45bfdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 4 Aug 2023 13:08:22 +0200 Subject: [PATCH 19/61] correct workspace alias --- .../stylesheets/workspace/stylesheet-workspace.context.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index 5d4640ca9f..34c354e1c7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -14,10 +14,9 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext Date: Fri, 4 Aug 2023 13:25:05 +0200 Subject: [PATCH 20/61] use context token --- .../stylesheet-workspace-view-code-editor.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts index 326b50e8ad..2335172942 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts @@ -5,6 +5,7 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor'; import { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; import { UmbStylesheetWorkspaceContext } from '../../stylesheet-workspace.context.js'; +import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; @customElement('umb-stylesheet-workspace-view-code-editor') export class UmbStylesheetWorkspaceViewCodeEditorElement extends UmbLitElement { @@ -29,7 +30,7 @@ export class UmbStylesheetWorkspaceViewCodeEditorElement extends UmbLitElement { super(); //tODO: should this be called something else here? - this.consumeContext('UmbEntityWorkspaceContext', (workspaceContext: UmbStylesheetWorkspaceContext) => { + this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext: UmbStylesheetWorkspaceContext) => { this.#stylesheetWorkspaceContext = workspaceContext; this.observe(this.#stylesheetWorkspaceContext.content, (content) => { From 43187e7e2ad707ed6f81340a689a811291775964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 4 Aug 2023 13:34:55 +0200 Subject: [PATCH 21/61] remove to editor --- ...ent.ts => stylesheet-workspace-editor.element.ts} | 12 ++++++------ .../workspace/stylesheet-workspace.element.ts | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/{stylesheet-workspace-edit.element.ts => stylesheet-workspace-editor.element.ts} (88%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts similarity index 88% rename from src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts index 20f7bcc45b..7389d09506 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts @@ -5,8 +5,8 @@ import { UMB_MODAL_MANAGER_CONTEXT_TOKEN, UmbModalManagerContext } from '@umbrac import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -@customElement('umb-stylesheet-workspace-edit') -export class UmbStylesheetWorkspaceEditElement extends UmbLitElement { +@customElement('umb-stylesheet-workspace-editor') +export class UmbStylesheetWorkspaceEditorElement extends UmbLitElement { #workspaceContext?: UmbStylesheetWorkspaceContext; @state() @@ -32,8 +32,8 @@ export class UmbStylesheetWorkspaceEditElement extends UmbLitElement { #observeNameAndPath() { if (!this.#workspaceContext) return; - this.observe(this.#workspaceContext.name, (name) => (this._name = name)); - this.observe(this.#workspaceContext.path, (path) => (this._path = path)); + this.observe(this.#workspaceContext.name, (name) => (this._name = name), '_observeName'); + this.observe(this.#workspaceContext.path, (path) => (this._path = path), '_observePath'); } #onNameChange(event: UUIInputEvent) { @@ -95,10 +95,10 @@ export class UmbStylesheetWorkspaceEditElement extends UmbLitElement { ]; } -export default UmbStylesheetWorkspaceEditElement; +export default UmbStylesheetWorkspaceEditorElement; declare global { interface HTMLElementTagNameMap { - 'umb-stylesheet-workspace-edit': UmbStylesheetWorkspaceEditElement; + 'umb-stylesheet-workspace-editor': UmbStylesheetWorkspaceEditorElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts index 444c06101a..44a2a8952a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts @@ -1,5 +1,5 @@ import { serverFilePathFromUrlFriendlyPath } from '../../utils.js'; -import { UmbStylesheetWorkspaceEditElement } from './stylesheet-workspace-edit.element.js'; +import { UmbStylesheetWorkspaceEditorElement } from './stylesheet-workspace-editor.element.js'; import { UmbStylesheetWorkspaceContext } from './stylesheet-workspace.context.js'; import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; @@ -10,7 +10,7 @@ import { UmbWorkspaceIsNewRedirectController } from '@umbraco-cms/backoffice/wor @customElement('umb-stylesheet-workspace') export class UmbStylesheetWorkspaceElement extends UmbLitElement { #workspaceContext = new UmbStylesheetWorkspaceContext(this); - #element = new UmbStylesheetWorkspaceEditElement(); + #element = new UmbStylesheetWorkspaceEditorElement(); @state() _routes: UmbRoute[] = [ From 738fa7fcd75f1df3bf935be84c8a7caac5b9ee3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 4 Aug 2023 13:41:54 +0200 Subject: [PATCH 22/61] fix import --- .../workspace/stylesheet-workspace-editor.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts index 7389d09506..b4923e7800 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts @@ -1,6 +1,6 @@ +import { UmbStylesheetWorkspaceContext } from './stylesheet-workspace.context.js'; import { UUIInputElement, UUIInputEvent, UUITextStyles } from '@umbraco-cms/backoffice/external/uui'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbStylesheetWorkspaceContext } from './stylesheet-workspace.context.js'; import { UMB_MODAL_MANAGER_CONTEXT_TOKEN, UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; From 8b9f1d12b8a19577680d0577d35dfbd7a528c555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 4 Aug 2023 13:46:03 +0200 Subject: [PATCH 23/61] type casting fix --- .../workspace/stylesheet-workspace-editor.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts index b4923e7800..4e63c45894 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts @@ -21,7 +21,7 @@ export class UmbStylesheetWorkspaceEditorElement extends UmbLitElement { super(); this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => { - this.#workspaceContext = instance as UmbStylesheetWorkspaceContext; + this.#workspaceContext = instance as unknown as UmbStylesheetWorkspaceContext; this.#observeNameAndPath(); }); From 6338557772f574fc93d95eb6f9e855319cb0a4f2 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Thu, 10 Aug 2023 10:28:37 +0200 Subject: [PATCH 24/61] fix ts error --- .../stylesheet-workspace-view-code-editor.element.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts index 2335172942..6de288de66 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts @@ -1,10 +1,10 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; import { css, html } from 'lit'; import { customElement, query, state } from 'lit/decorators.js'; +import { UmbStylesheetWorkspaceContext } from '../../stylesheet-workspace.context.js'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor'; import { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; -import { UmbStylesheetWorkspaceContext } from '../../stylesheet-workspace.context.js'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; @customElement('umb-stylesheet-workspace-view-code-editor') @@ -30,8 +30,8 @@ export class UmbStylesheetWorkspaceViewCodeEditorElement extends UmbLitElement { super(); //tODO: should this be called something else here? - this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext: UmbStylesheetWorkspaceContext) => { - this.#stylesheetWorkspaceContext = workspaceContext; + this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => { + this.#stylesheetWorkspaceContext = workspaceContext as UmbStylesheetWorkspaceContext; this.observe(this.#stylesheetWorkspaceContext.content, (content) => { this._content = content; From ba0a83a3d185c3daed998f2f8cdbcab81b455453 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Fri, 11 Aug 2023 09:02:43 +0200 Subject: [PATCH 25/61] the other workspace wip --- .../src/mocks/data/stylesheet.data.ts | 21 +++ .../repository/stylesheet.repository.ts | 18 +-- .../workspace/stylesheet-workspace.context.ts | 9 +- ...workspace-view-rich-text-editor.element.ts | 129 +++++++++++++++++- 4 files changed, 163 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts index 1fcfd1b7fb..d39dcc79d0 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts @@ -5,6 +5,7 @@ import { FileSystemTreeItemPresentationModel, PagedFileSystemTreeItemPresentationModel, PagedStylesheetOverviewResponseModel, + RichTextRuleModel, StylesheetResponseModel, } from '@umbraco-cms/backoffice/backend-api'; @@ -142,6 +143,26 @@ class UmbStylesheetData extends UmbEntityData { return this.data.find((item) => item.path === path && item.isFolder === true); } + getRules(path: string): Array { + return [ + { + "name": "bjjh", + "selector": "h1", + "styles": "color: blue;" + }, + { + "name": "comeone", + "selector": "h1", + "styles": "color: blue;" + }, + { + "name": "lol", + "selector": "h1", + "styles": "color: blue;" + } + ] + } + insertFolder(item: CreateTextFileViewModelBaseModel) { const newItem: StylesheetDBItem = { ...item, diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts index bbb53ad195..82835cadca 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts @@ -1,6 +1,12 @@ +import { Observable } from 'rxjs'; +import { StylesheetDetails } from '../index.js'; import { UmbStylesheetTreeStore, UMB_STYLESHEET_TREE_STORE_CONTEXT_TOKEN } from './stylesheet.tree.store.js'; import { UmbStylesheetTreeServerDataSource } from './sources/stylesheet.tree.server.data.js'; import { UmbStylesheetServerDataSource } from './sources/stylesheet.server.data.js'; +import { + StylesheetGetFolderResponse, + UmbStylesheetFolderServerDataSource, +} from './sources/stylesheet.folder.server.data.js'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; import { @@ -18,7 +24,7 @@ import { ExtractRichTextStylesheetRulesResponseModel, FileSystemTreeItemPresentationModel, FolderModelBaseModel, - FolderReponseModel, + FolderResponseModel, InterpolateRichTextStylesheetRequestModel, InterpolateRichTextStylesheetResponseModel, ProblemDetails, @@ -28,12 +34,6 @@ import { UpdateTextFileViewModelBaseModel, } from '@umbraco-cms/backoffice/backend-api'; import type { UmbTreeRootFileSystemModel } from '@umbraco-cms/backoffice/tree'; -import { StylesheetDetails } from '../index.js'; -import { Observable } from 'rxjs'; -import { - StylesheetGetFolderResponse, - UmbStylesheetFolderServerDataSource, -} from './sources/stylesheet.folder.server.data.js'; export class UmbStylesheetRepository implements @@ -65,8 +65,8 @@ export class UmbStylesheetRepository createFolderScaffold( parentId: string | null - ): Promise<{ data?: FolderReponseModel | undefined; error?: ProblemDetails | undefined }> { - const data: FolderReponseModel = { + ): Promise<{ data?: FolderResponseModel | undefined; error?: ProblemDetails | undefined }> { + const data: FolderResponseModel = { name: '', parentId, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index 34c354e1c7..c60225af89 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -4,9 +4,11 @@ import { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { UmbBooleanState, UmbObjectState, createObservablePart } from '@umbraco-cms/backoffice/observable-api'; import { loadCodeEditor } from '@umbraco-cms/backoffice/code-editor'; +import { RichTextStylesheetRulesResponseModel } from '@umbraco-cms/backoffice/backend-api'; export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext { #data = new UmbObjectState(undefined); + #rules = new UmbObjectState(undefined); data = this.#data.asObservable(); name = createObservablePart(this.#data, (data) => data?.name); content = createObservablePart(this.#data, (data) => data?.content); @@ -50,11 +52,16 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext { + this.#stylesheetWorkspaceContext = workspaceContext as UmbStylesheetWorkspaceContext; + + this.observe(this.#stylesheetWorkspaceContext.content, (content) => { + this._content = content; + }); + + this.observe(this.#stylesheetWorkspaceContext.path, (path) => { + this._path = path; + }); + + this.observe(this.#stylesheetWorkspaceContext.isNew, (isNew) => { + this.#isNew = !!isNew; + }); + + this.observe(this.#stylesheetWorkspaceContext.isCodeEditorReady, (isReady) => { + this._ready = isReady; + }); + }); } - static styles = [UUITextStyles, css``]; + renderRule(rule: RichTextRuleModel) { + return html`
+
${rule.name}
+
EditRemove
+
`; + } + render() { + return html` + +
+ +

Define the styles that should be available in the rich text editor for this stylesheet

+
+ ${this._rules?.map((rule) => this.renderRule(rule))} +
+
+ +
`; + } + + static styles = [ + UUITextStyles, + css` + :host { + display: block; + width: 100%; + } + + #box-row { + display: flex; + gap: var(--uui-size-layout-1); + } + + #description { + flex: 0 0 250px + } + + #rules { + flex: 1 1 auto; + max-width: 600px; + } + + .rule { + display: flex; + width: 100%; + justify-content: space-between; + padding: var(--uui-size-2); + align-items: center; + border-radius: var(--uui-size-border-radius); + background-color: var(--uui-color-surface-alt); + margin-bottom: var(--uui-size-space-4); + } + + uui-box { + margin: var(--uui-size-layout-1); + /* remove header border bottom as code editor looks better in this box */ + --uui-color-divider-standalone: transparent; + } + + + `, + ]; } export default UmbStylesheetWorkspaceViewRichTextEditorElement; From 9b98497b0cd1cf16cc164f2654626e889485acd4 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Fri, 11 Aug 2023 12:43:05 +0200 Subject: [PATCH 26/61] add modal --- .../stylesheets/workspace/manifests.ts | 15 ++- ...ace-view-rich-text-editor-style-sidebar.ts | 74 ++++++++++++++ ...workspace-view-rich-text-editor.element.ts | 97 +++++++++++++------ 3 files changed, 153 insertions(+), 33 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts index d2786fb7ea..3c6dde658c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts @@ -1,4 +1,5 @@ import type { + ManifestModal, ManifestWorkspace, ManifestWorkspaceAction, ManifestWorkspaceEditorView, @@ -73,4 +74,16 @@ const workspaceActions: Array = [ }, ]; -export const manifests = [workspace, ...workspaceEditorViews, ...workspaceActions]; +export const UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR = + 'Umb.Modal.Templating.Stylesheet.RichTextEditorStyle.Sidebar'; + +const modals: Array = [ + { + type: 'modal', + alias: UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR, + name: 'Rich text editor style modal', + loader: () => import('./views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.js'), + }, +]; + +export const manifests = [workspace, ...workspaceEditorViews, ...workspaceActions, ...modals]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.ts new file mode 100644 index 0000000000..768758b1f5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.ts @@ -0,0 +1,74 @@ +import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui'; +import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; +import { RichTextRuleModel } from '@umbraco-cms/backoffice/backend-api'; + +export interface StylesheetRichTextEditorStyleModalData { + rule?: RichTextRuleModel; +} + +export interface StylesheetRichTextEditorStyleModalResult { + rule: RichTextRuleModel; +} + +@customElement('umb-stylesheet-rich-text-editor-style-modal') +export default class UmbStylesheetRichTextEditorStyleModalElement extends UmbModalBaseElement< + StylesheetRichTextEditorStyleModalData, + StylesheetRichTextEditorStyleModalResult +> { + private _close() { + this.modalContext?.reject(); + } + + render() { + return html` + +
+ +

Rule

+

${this.data?.rule?.name}

+

${this.data?.rule?.selector}

+

${this.data?.rule?.styles}

+
+
+
+ Close +
+
+ `; + } + + static styles = [ + UUITextStyles, + css` + :host { + display: block; + color: var(--uui-color-text); + --umb-header-layout-height: 70px; + } + + #main { + box-sizing: border-box; + height: calc( + 100dvh - var(--umb-header-layout-height) - var(--umb-footer-layout-height) - 2 * var(--uui-size-layout-1) + ); + } + + #main uui-button:not(:last-of-type) { + display: block; + margin-bottom: var(--uui-size-space-5); + } + + h3, + p { + text-align: left; + } + `, + ]; +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-stylesheet-rich-text-editor-style-modal': UmbStylesheetRichTextEditorStyleModalElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts index fcb366d0ac..c7d7883ac4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts @@ -1,16 +1,28 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; import { css, html } from 'lit'; -import { customElement, query, state } from 'lit/decorators.js'; +import { customElement, state } from 'lit/decorators.js'; +import { UmbStylesheetWorkspaceContext } from '../../stylesheet-workspace.context.js'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; -import { UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor'; -import { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; -import { UmbStylesheetWorkspaceContext } from '../../stylesheet-workspace.context.js'; +import { + UMB_MODAL_MANAGER_CONTEXT_TOKEN, + UmbModalContext, + UmbModalManagerContext, + UmbModalToken, +} from '@umbraco-cms/backoffice/modal'; import { RichTextRuleModel } from '@umbraco-cms/backoffice/backend-api'; +import { UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR } from '../../manifests.js'; +import { StylesheetRichTextEditorStyleModalResult } from './stylesheet-workspace-view-rich-text-editor-style-sidebar.js'; +export const UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR_MODAL = new UmbModalToken<{ rule: RichTextRuleModel }>( + UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR, + { + type: 'sidebar', + size: 'small', + }, +); @customElement('umb-stylesheet-workspace-view-rich-text-editor') export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitElement { - @state() private _content?: string | null = ''; @@ -23,26 +35,27 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme @state() private _rules?: RichTextRuleModel[] = [ { - "name": "bjjh", - "selector": "h1", - "styles": "color: blue;" + name: 'bjjh', + selector: 'h1', + styles: 'color: blue;', }, { - "name": "comeone", - "selector": "h1", - "styles": "color: blue;" + name: 'comeone', + selector: 'h1', + styles: 'color: blue;', }, { - "name": "lol", - "selector": "h1", - "styles": "color: blue;" - } + name: 'lol', + selector: 'h1', + styles: 'color: blue;', + }, ]; #stylesheetWorkspaceContext?: UmbStylesheetWorkspaceContext; private _modalContext?: UmbModalManagerContext; #isNew = false; + #modal?: UmbModalContext; constructor() { super(); @@ -67,25 +80,40 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme this._ready = isReady; }); }); + + this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { + this._modalContext = instance; + }); } + #openModal = (rule: RichTextRuleModel = {}) => { + if (!this._modalContext) throw new Error('Modal context not found'); + const modal = this._modalContext.open(UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR_MODAL, { + rule, + }); + modal?.onSubmit().then((closedModal) => { + console.log(closedModal); + }); + }; + renderRule(rule: RichTextRuleModel) { return html`
-
${rule.name}
-
EditRemove
+
${rule.name}
+
+ this.#openModal(rule)}>EditRemove +
`; } render() { return html` - -
- -

Define the styles that should be available in the rich text editor for this stylesheet

-
- ${this._rules?.map((rule) => this.renderRule(rule))} -
-
- +
+

Define the styles that should be available in the rich text editor for this stylesheet.

+
+ ${this._rules?.map((rule) => this.renderRule(rule))} + Add +
+
`; } @@ -103,7 +131,8 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme } #description { - flex: 0 0 250px + margin-top: 0; + flex: 0 0 250px; } #rules { @@ -111,24 +140,28 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme max-width: 600px; } + .rule-name { + display: flex; + align-items: center; + gap: var(--uui-size-2); + padding-left: var(--uui-size-2); + font-weight: bold; + } + .rule { display: flex; width: 100%; justify-content: space-between; padding: var(--uui-size-2); align-items: center; - border-radius: var(--uui-size-border-radius); + border-radius: var(--uui-border-radius); background-color: var(--uui-color-surface-alt); margin-bottom: var(--uui-size-space-4); } uui-box { margin: var(--uui-size-layout-1); - /* remove header border bottom as code editor looks better in this box */ - --uui-color-divider-standalone: transparent; } - - `, ]; } From 8a5db330ee560cd863ce707976b0fe8ac6871b93 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Fri, 11 Aug 2023 13:29:54 +0200 Subject: [PATCH 27/61] create form with preview --- ...ace-view-rich-text-editor-style-sidebar.ts | 73 ++++++++++++++++--- ...workspace-view-rich-text-editor.element.ts | 11 ++- 2 files changed, 73 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.ts index 768758b1f5..6b3681a33a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.ts @@ -1,5 +1,5 @@ import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui'; -import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; import { RichTextRuleModel } from '@umbraco-cms/backoffice/backend-api'; @@ -20,19 +20,63 @@ export default class UmbStylesheetRichTextEditorStyleModalElement extends UmbMod this.modalContext?.reject(); } + #submit() { + const rule = this.data?.rule ?? {}; + this.modalContext?.submit({ rule }); + } + render() { return html` - +
-

Rule

-

${this.data?.rule?.name}

-

${this.data?.rule?.selector}

-

${this.data?.rule?.styles}

+ +
+ + Name + The name displayed in the editor style selector + + + + + Selector + Uses CSS syntax, e.g. "h1" or ".redHeader" + + + + + Selector + The CSS that should be applied in the rich text editor, e.g. "color:red;" + + + + + Preview + How the text will look like in the rich text editor. +
+ a b c d e f g h i j k l m n o p q r s t u v w x t z +
+ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z +
+ 1 2 3 4 5 6 7 8 9 0 € £ $ % & (.,;:'"!?) +
+ Just keep examining every bid quoted for zinc etchings. +
+
+
+
Close + Submit
`; @@ -59,9 +103,20 @@ export default class UmbStylesheetRichTextEditorStyleModalElement extends UmbMod margin-bottom: var(--uui-size-space-5); } - h3, - p { - text-align: left; + uui-input { + width: 100%; + } + + #styles { + font-family: + Monaco, + Menlo, + Consolas, + Courier New, + monospace; + --uui-textarea-min-height: 100px; + resize: none; + width: 300px; } `, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts index c7d7883ac4..d84c269358 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts @@ -18,7 +18,7 @@ export const UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR_MODAL = new UmbMo UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR, { type: 'sidebar', - size: 'small', + size: 'medium', }, ); @customElement('umb-stylesheet-workspace-view-rich-text-editor') @@ -96,12 +96,19 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme }); }; + #removeRule = (rule: RichTextRuleModel) => { + this._rules = this._rules?.filter((r) => r !== rule); + throw new Error('Method not implemented.'); + }; + renderRule(rule: RichTextRuleModel) { return html`
${rule.name}
this.#openModal(rule)}>EditRemove + > this.#removeRule(rule)} + >Remove
`; } From f0de7cd7b438311bb536800bbcaad9b01703dfa9 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Fri, 11 Aug 2023 14:57:26 +0200 Subject: [PATCH 28/61] Update stylesheet-workspace-view-rich-text-editor-style-sidebar.ts --- ...ace-view-rich-text-editor-style-sidebar.ts | 57 ++++++++++++++++--- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.ts index 6b3681a33a..e5266b4e78 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.ts @@ -1,5 +1,5 @@ import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui'; -import { css, html, customElement, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, ifDefined, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; import { RichTextRuleModel } from '@umbraco-cms/backoffice/backend-api'; @@ -21,8 +21,39 @@ export default class UmbStylesheetRichTextEditorStyleModalElement extends UmbMod } #submit() { - const rule = this.data?.rule ?? {}; - this.modalContext?.submit({ rule }); + this.modalContext?.submit({ rule: this._rule ?? {} }); + } + + connectedCallback() { + super.connectedCallback(); + this._rule = this.data?.rule ?? null; + } + + @state() + private _rule?: RichTextRuleModel | null = null; + + #updateName(event: Event) { + const name = (event.target as HTMLInputElement).value; + this._rule = { + ...this._rule, + name, + }; + } + + #updateSelector(event: Event) { + const selector = (event.target as HTMLInputElement).value; + this._rule = { + ...this._rule, + selector, + }; + } + + #updateStyles(event: Event) { + const styles = (event.target as HTMLInputElement).value; + this._rule = { + ...this._rule, + styles, + }; } render() { @@ -35,7 +66,13 @@ export default class UmbStylesheetRichTextEditorStyleModalElement extends UmbMod Name The name displayed in the editor style selector - + @@ -44,8 +81,9 @@ export default class UmbStylesheetRichTextEditorStyleModalElement extends UmbMod @@ -54,13 +92,18 @@ export default class UmbStylesheetRichTextEditorStyleModalElement extends UmbMod The CSS that should be applied in the rich text editor, e.g. "color:red;" - + Preview How the text will look like in the rich text editor. -
+
a b c d e f g h i j k l m n o p q r s t u v w x t z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z From 9d1bf1ec3ab0df8c01d23d7b49e4b03eec644901 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Tue, 15 Aug 2023 11:01:53 +0200 Subject: [PATCH 29/61] add create actions --- .../packages/templating/stylesheets/config.ts | 15 ++++ .../create/create-rtf.action.ts | 16 ++++ .../entity-actions/create/create.action.ts | 12 +++ .../stylesheets/entity-actions/manifests.ts | 88 +++++++++++++++++++ .../packages/templating/stylesheets/index.ts | 2 +- .../templating/stylesheets/manifests.ts | 9 +- .../stylesheets/repository/manifests.ts | 4 +- .../templating/stylesheets/tree/manifests.ts | 3 +- .../workspace/stylesheet-workspace.context.ts | 18 ++-- .../workspace/stylesheet-workspace.element.ts | 31 ++++--- 10 files changed, 166 insertions(+), 32 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/config.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/create-rtf.action.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/create.action.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/config.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/config.ts new file mode 100644 index 0000000000..cb6e44810e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/config.ts @@ -0,0 +1,15 @@ +export const STYLESHEET_ENTITY_TYPE = 'stylesheet'; + +export const STYLESHEET_ROOT_ENTITY_TYPE = 'stylesheet-root'; +export const STYLESHEET_FOLDER_ENTITY_TYPE = 'stylesheet-folder'; +export const STYLESHEET_FOLDER_EMPTY_ENTITY_TYPE = 'stylesheet-folder-empty'; + +export const STYLESHEET_REPOSITORY_ALIAS = 'Umb.Repository.Stylesheet'; + +export const STYLESHEET_TREE_ALIAS = 'Umb.Tree.Stylesheet'; + +export const UMB_STYLESHEET_TREE_STORE_CONTEXT_TOKEN_ALIAS = 'Umb.Store.Stylesheet.Tree'; +export const UMB_STYLESHEET_STORE_CONTEXT_TOKEN_ALIAS = 'Umb.Store.Stylesheet'; + +export const STYLESHEET_STORE_ALIAS = 'Umb.Store.Stylesheet'; +export const STYLESHEET_TREE_STORE_ALIAS = 'Umb.Store.StylesheetTree'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/create-rtf.action.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/create-rtf.action.ts new file mode 100644 index 0000000000..9bc1e2ec28 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/create-rtf.action.ts @@ -0,0 +1,16 @@ +import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; +import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; + +export class UmbCreateRTFStylesheetAction }> extends UmbEntityActionBase { + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { + super(host, repositoryAlias, unique); + } + + async execute() { + history.pushState( + null, + '', + `section/settings/workspace/stylesheet/create/${this.unique ?? 'null'}/view/rich-text-editor`, + ); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/create.action.ts new file mode 100644 index 0000000000..b5b4e71368 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/create/create.action.ts @@ -0,0 +1,12 @@ +import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; +import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; + +export class UmbCreateStylesheetAction }> extends UmbEntityActionBase { + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { + super(host, repositoryAlias, unique); + } + + async execute() { + history.pushState(null, '', `section/settings/workspace/stylesheet/create/${this.unique ?? 'null'}/view/code`); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/manifests.ts new file mode 100644 index 0000000000..3ccce2036f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/manifests.ts @@ -0,0 +1,88 @@ +import { + STYLESHEET_ENTITY_TYPE, + STYLESHEET_FOLDER_EMPTY_ENTITY_TYPE, + STYLESHEET_FOLDER_ENTITY_TYPE, + STYLESHEET_REPOSITORY_ALIAS, + STYLESHEET_ROOT_ENTITY_TYPE, +} from '../config.js'; +import { UmbCreateRTFStylesheetAction } from './create/create-rtf.action.js'; +import { UmbCreateStylesheetAction } from './create/create.action.js'; +import { + UmbCreateFolderEntityAction, + UmbDeleteEntityAction, + UmbDeleteFolderEntityAction, +} from '@umbraco-cms/backoffice/entity-action'; +import { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +//TODO: this is temporary until we have a proper way of registering actions for folder types in a specific tree + +//Actions for partial view files +const stylesheetActions: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.Stylesheet.Delete', + name: 'Delete Stylesheet Entity Action', + meta: { + icon: 'umb:trash', + label: 'Delete', + api: UmbDeleteEntityAction, + repositoryAlias: STYLESHEET_REPOSITORY_ALIAS, + entityTypes: [STYLESHEET_ENTITY_TYPE], + }, + }, +]; + +//TODO: add create folder action when the generic folder action is implemented +//Actions for directories +const stylesheetFolderActions: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.Stylesheet.Folder.Create', + name: 'Create Stylesheet Entity Under Directory Action', + meta: { + icon: 'umb:script', + label: 'New stylesheet file', + api: UmbCreateStylesheetAction, + repositoryAlias: STYLESHEET_REPOSITORY_ALIAS, + entityTypes: [STYLESHEET_FOLDER_ENTITY_TYPE, STYLESHEET_ROOT_ENTITY_TYPE], + }, + }, + { + type: 'entityAction', + alias: 'Umb.EntityAction.Stylesheet.Folder.Create.RTF', + name: 'Create RTF Stylesheet Entity Under Directory Action', + meta: { + icon: 'umb:script', + label: 'New Rich Text Editor style sheet file', + api: UmbCreateRTFStylesheetAction, + repositoryAlias: STYLESHEET_REPOSITORY_ALIAS, + entityTypes: [STYLESHEET_FOLDER_ENTITY_TYPE, STYLESHEET_ROOT_ENTITY_TYPE], + }, + }, + { + type: 'entityAction', + alias: 'Umb.EntityAction.Stylesheet.Folder.DeleteFolder', + name: 'Remove empty folder', + meta: { + icon: 'umb:trash', + label: 'Remove folder', + api: UmbDeleteFolderEntityAction, + repositoryAlias: STYLESHEET_REPOSITORY_ALIAS, + entityTypes: [STYLESHEET_FOLDER_EMPTY_ENTITY_TYPE], + }, + }, + { + type: 'entityAction', + alias: 'Umb.EntityAction.Stylesheet.Folder.CreateFolder', + name: 'Create empty folder', + meta: { + icon: 'umb:add', + label: 'Create folder', + api: UmbCreateFolderEntityAction, + repositoryAlias: STYLESHEET_REPOSITORY_ALIAS, + entityTypes: [STYLESHEET_FOLDER_EMPTY_ENTITY_TYPE, STYLESHEET_FOLDER_ENTITY_TYPE, STYLESHEET_ROOT_ENTITY_TYPE], + }, + }, +]; + +export const manifests = [...stylesheetActions, ...stylesheetFolderActions]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts index 9bb36fdd52..e3d083d6f8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts @@ -3,5 +3,5 @@ import { StylesheetResponseModel } from '@umbraco-cms/backoffice/backend-api'; // TODO: temp until we have a proper stylesheet model export type StylesheetDetails = StylesheetResponseModel; -export const STYLESHEET_ENTITY_TYPE = 'stylesheet'; + export * from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/manifests.ts index ebc952eb39..12f1863639 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/manifests.ts @@ -2,5 +2,12 @@ import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as menuItemManifests } from './menu-item/manifests.js'; import { manifests as treeManifests } from './tree/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; +import { manifests as entityActionManifests } from './entity-actions/manifests.js'; -export const manifests = [...repositoryManifests, ...menuItemManifests, ...treeManifests, ...workspaceManifests]; +export const manifests = [ + ...repositoryManifests, + ...menuItemManifests, + ...treeManifests, + ...workspaceManifests, + ...entityActionManifests, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/manifests.ts index ef28d9ac67..b645728c43 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/manifests.ts @@ -1,8 +1,8 @@ +import { STYLESHEET_REPOSITORY_ALIAS, STYLESHEET_TREE_STORE_ALIAS } from '../config.js'; import { UmbStylesheetRepository } from './stylesheet.repository.js'; import { UmbStylesheetTreeStore } from './stylesheet.tree.store.js'; import { ManifestRepository, ManifestTreeStore } from '@umbraco-cms/backoffice/extension-registry'; -export const STYLESHEET_REPOSITORY_ALIAS = 'Umb.Repository.Stylesheet'; const repository: ManifestRepository = { type: 'repository', @@ -11,8 +11,6 @@ const repository: ManifestRepository = { class: UmbStylesheetRepository, }; -export const STYLESHEET_STORE_ALIAS = 'Umb.Store.Stylesheet'; -export const STYLESHEET_TREE_STORE_ALIAS = 'Umb.Store.StylesheetTree'; const treeStore: ManifestTreeStore = { type: 'treeStore', diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/manifests.ts index 4118b0b889..108889cea8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/tree/manifests.ts @@ -1,5 +1,4 @@ -import { STYLESHEET_ENTITY_TYPE } from '../index.js'; -import { STYLESHEET_REPOSITORY_ALIAS } from '../repository/manifests.js'; +import { STYLESHEET_ENTITY_TYPE, STYLESHEET_REPOSITORY_ALIAS } from '../config.js'; import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extension-registry'; export const STYLESHEET_TREE_ALIAS = 'Umb.Tree.Stylesheet'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index c60225af89..05079cc74c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -93,15 +93,15 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext this.#element, - // setup: async (_component, info) => { - // const path = info.match.params.path; - // const serverPath = serverFilePathFromUrlFriendlyPath(path); - // this.#workspaceContext.setIsNew(false); - // console.log('load'); - // await this.#workspaceContext.load(serverPath); + { + path: 'create/:parentId', + component: () => this.#element, + setup: async (_component, info) => { + const path = info.match.params.path; + const serverPath = serverFilePathFromUrlFriendlyPath(path); + this.#workspaceContext.setIsNew(true); + await this.#workspaceContext.load(serverPath); - // new UmbWorkspaceIsNewRedirectController( - // this, - // this.#workspaceContext, - // this.shadowRoot!.querySelector('umb-router-slot')! - // ); - // }, - // }, + new UmbWorkspaceIsNewRedirectController( + this, + this.#workspaceContext, + this.shadowRoot!.querySelector('umb-router-slot')!, + ); + }, + }, { path: 'edit/:path', component: () => this.#element, From aede6112de4d55fc29127e697e3c8c060de5fe98 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Tue, 15 Aug 2023 11:28:07 +0200 Subject: [PATCH 30/61] fix wrong route parameter --- .../stylesheet-workspace-editor.element.ts | 23 +++++++++++++++---- .../workspace/stylesheet-workspace.context.ts | 11 ++++----- .../workspace/stylesheet-workspace.element.ts | 4 ++-- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts index 4e63c45894..c75b88d3ad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts @@ -17,6 +17,8 @@ export class UmbStylesheetWorkspaceEditorElement extends UmbLitElement { private _modalContext?: UmbModalManagerContext; + #isNew = false; + constructor() { super(); @@ -32,8 +34,15 @@ export class UmbStylesheetWorkspaceEditorElement extends UmbLitElement { #observeNameAndPath() { if (!this.#workspaceContext) return; - this.observe(this.#workspaceContext.name, (name) => (this._name = name), '_observeName'); - this.observe(this.#workspaceContext.path, (path) => (this._path = path), '_observePath'); + this.observe(this.#workspaceContext.name, (name) => (this._name = name ?? ''), '_observeName'); + this.observe(this.#workspaceContext.path, (path) => (this._path = path ?? ''), '_observePath'); + this.observe( + this.#workspaceContext.isNew, + (isNew) => { + this.#isNew = !!isNew; + }, + '_observeIsNew', + ); } #onNameChange(event: UUIInputEvent) { @@ -50,8 +59,14 @@ export class UmbStylesheetWorkspaceEditorElement extends UmbLitElement { return html`
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index 05079cc74c..a469f4f5e7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -52,7 +52,10 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext this.#element, setup: async (_component, info) => { - const path = info.match.params.path; + const path = info.match.params.parentId; const serverPath = serverFilePathFromUrlFriendlyPath(path); this.#workspaceContext.setIsNew(true); - await this.#workspaceContext.load(serverPath); + await this.#workspaceContext.create(serverPath); new UmbWorkspaceIsNewRedirectController( this, From 56227bb161b666b97eeeb864db4e2ac97c62c622 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Tue, 15 Aug 2023 12:35:16 +0200 Subject: [PATCH 31/61] add save method --- .../workspace/stylesheet-workspace.context.ts | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index a469f4f5e7..28acc2f198 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -4,7 +4,10 @@ import { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { UmbBooleanState, UmbObjectState, createObservablePart } from '@umbraco-cms/backoffice/observable-api'; import { loadCodeEditor } from '@umbraco-cms/backoffice/code-editor'; -import { RichTextStylesheetRulesResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import { + RichTextStylesheetRulesResponseModel, + UpdateStylesheetRequestModel, +} from '@umbraco-cms/backoffice/backend-api'; export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext { #data = new UmbObjectState(undefined); @@ -68,31 +71,28 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext Date: Mon, 21 Aug 2023 10:55:31 +0200 Subject: [PATCH 32/61] add empty folder to action --- .../packages/templating/partial-views/workspace/manifests.ts | 3 +-- .../templating/stylesheets/entity-actions/manifests.ts | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/manifests.ts index 7fb04dcb3a..1765d62c51 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/manifests.ts @@ -16,11 +16,10 @@ const workspaceActions: Array = [ type: 'workspaceAction', alias: 'Umb.WorkspaceAction.PartialView.Save', name: 'Save Partial View', - weight: 70, meta: { + label: 'Save', look: 'primary', color: 'positive', - label: 'Save', api: UmbSaveWorkspaceAction, }, conditions: [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/manifests.ts index 3ccce2036f..cb90d2b298 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/entity-actions/manifests.ts @@ -44,7 +44,7 @@ const stylesheetFolderActions: Array = [ label: 'New stylesheet file', api: UmbCreateStylesheetAction, repositoryAlias: STYLESHEET_REPOSITORY_ALIAS, - entityTypes: [STYLESHEET_FOLDER_ENTITY_TYPE, STYLESHEET_ROOT_ENTITY_TYPE], + entityTypes: [STYLESHEET_FOLDER_ENTITY_TYPE, STYLESHEET_FOLDER_EMPTY_ENTITY_TYPE, STYLESHEET_ROOT_ENTITY_TYPE], }, }, { @@ -56,7 +56,7 @@ const stylesheetFolderActions: Array = [ label: 'New Rich Text Editor style sheet file', api: UmbCreateRTFStylesheetAction, repositoryAlias: STYLESHEET_REPOSITORY_ALIAS, - entityTypes: [STYLESHEET_FOLDER_ENTITY_TYPE, STYLESHEET_ROOT_ENTITY_TYPE], + entityTypes: [STYLESHEET_FOLDER_ENTITY_TYPE, STYLESHEET_FOLDER_EMPTY_ENTITY_TYPE, STYLESHEET_ROOT_ENTITY_TYPE], }, }, { From 0a14150d9c7cf15d152a42f878a7bac29a7129bf Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 21 Aug 2023 11:04:34 +0200 Subject: [PATCH 33/61] fix name input --- .../stylesheet-workspace-editor.element.ts | 26 +++++++++++++------ .../workspace/stylesheet-workspace.context.ts | 2 +- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts index c75b88d3ad..337ba18cbe 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts @@ -4,13 +4,22 @@ import { css, html, customElement, state } from '@umbraco-cms/backoffice/externa import { UMB_MODAL_MANAGER_CONTEXT_TOKEN, UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { Subject, debounceTime } from '@umbraco-cms/backoffice/external/rxjs'; @customElement('umb-stylesheet-workspace-editor') export class UmbStylesheetWorkspaceEditorElement extends UmbLitElement { #workspaceContext?: UmbStylesheetWorkspaceContext; + #name: string | undefined = ''; @state() - private _name?: string; + private get _name() { + return this.#name; + } + + private set _name(value) { + this.#name = value?.replace('.css', ''); + this.requestUpdate(); + } @state() private _path?: string; @@ -19,12 +28,17 @@ export class UmbStylesheetWorkspaceEditorElement extends UmbLitElement { #isNew = false; + private inputQuery$ = new Subject(); + constructor() { super(); this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => { this.#workspaceContext = instance as unknown as UmbStylesheetWorkspaceContext; this.#observeNameAndPath(); + this.inputQuery$.pipe(debounceTime(250)).subscribe((nameInputValue: string) => { + this.#workspaceContext?.setName(`${nameInputValue}.css`); + }); }); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { @@ -46,13 +60,9 @@ export class UmbStylesheetWorkspaceEditorElement extends UmbLitElement { } #onNameChange(event: UUIInputEvent) { - if (event instanceof UUIInputEvent) { - const target = event.composedPath()[0] as UUIInputElement; - - if (typeof target?.value === 'string') { - this.#workspaceContext?.setName(target.value); - } - } + const target = event.target as UUIInputElement; + const value = target.value as string; + this.inputQuery$.next(value); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index 28acc2f198..3eb68868d9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -79,7 +79,7 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext Date: Mon, 21 Aug 2023 11:36:08 +0200 Subject: [PATCH 34/61] add rules observable --- .../workspace/stylesheet-workspace.context.ts | 16 +++++++------ ...workspace-view-rich-text-editor.element.ts | 23 +++++-------------- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index 3eb68868d9..08ef653320 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -2,17 +2,15 @@ import { UmbStylesheetRepository } from '../repository/stylesheet.repository.js' import { StylesheetDetails } from '../index.js'; import { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; -import { UmbBooleanState, UmbObjectState, createObservablePart } from '@umbraco-cms/backoffice/observable-api'; +import { UmbArrayState, UmbBooleanState, UmbObjectState, createObservablePart } from '@umbraco-cms/backoffice/observable-api'; import { loadCodeEditor } from '@umbraco-cms/backoffice/code-editor'; -import { - RichTextStylesheetRulesResponseModel, - UpdateStylesheetRequestModel, -} from '@umbraco-cms/backoffice/backend-api'; +import { RichTextRuleModel, UpdateStylesheetRequestModel } from '@umbraco-cms/backoffice/backend-api'; export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext { #data = new UmbObjectState(undefined); - #rules = new UmbObjectState(undefined); + #rules = new UmbArrayState([]); data = this.#data.asObservable(); + rules = this.#rules.asObservable(); name = createObservablePart(this.#data, (data) => data?.name); content = createObservablePart(this.#data, (data) => data?.content); path = createObservablePart(this.#data, (data) => data?.path); @@ -46,6 +44,10 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext { this._ready = isReady; }); + + this.observe(this.#stylesheetWorkspaceContext.rules, (rules) => { + debugger; + this._rules = rules; + }); }); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { From 52cb0b916c301d3200f12e8e96904b19db12ba35 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 21 Aug 2023 14:45:01 +0200 Subject: [PATCH 35/61] add rules methods to context --- .../repository/stylesheet.repository.ts | 34 +++++++++++++------ .../workspace/stylesheet-workspace.context.ts | 22 ++++++++++++ ...workspace-view-rich-text-editor.element.ts | 1 - 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts index 82835cadca..5e625766aa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/stylesheet.repository.ts @@ -64,7 +64,7 @@ export class UmbStylesheetRepository //#region FOLDER: createFolderScaffold( - parentId: string | null + parentId: string | null, ): Promise<{ data?: FolderResponseModel | undefined; error?: ProblemDetails | undefined }> { const data: FolderResponseModel = { name: '', @@ -74,7 +74,7 @@ export class UmbStylesheetRepository } async createFolder( - folderRequest: CreateFolderRequestModel + folderRequest: CreateFolderRequestModel, ): Promise<{ data?: string | undefined; error?: ProblemDetails | undefined }> { await this.#init; const req = { @@ -87,14 +87,14 @@ export class UmbStylesheetRepository return promise; } async requestFolder( - unique: string + unique: string, ): Promise<{ data?: StylesheetGetFolderResponse | undefined; error?: ProblemDetails | undefined }> { await this.#init; return this.#folderDataSource.get(unique); } updateFolder( unique: string, - folder: FolderModelBaseModel + folder: FolderModelBaseModel, ): Promise<{ data?: FolderModelBaseModel | undefined; error?: ProblemDetails | undefined }> { throw new Error('Method not implemented.'); } @@ -113,7 +113,7 @@ export class UmbStylesheetRepository createScaffold( parentId: string | null, - preset?: Partial | undefined + preset?: Partial | undefined, ): Promise> { throw new Error('Method not implemented.'); } @@ -144,19 +144,31 @@ export class UmbStylesheetRepository } getStylesheetRules( - path: string + path: string, ): Promise> { return this.#dataSource.getStylesheetRichTextRules(path); } - + /** + * Existing content + array of rules => new content string + * + * @param {InterpolateRichTextStylesheetRequestModel} data + * @return {*} {Promise>} + * @memberof UmbStylesheetRepository + */ interpolateStylesheetRules( - data: InterpolateRichTextStylesheetRequestModel + data: InterpolateRichTextStylesheetRequestModel, ): Promise> { return this.#dataSource.postStylesheetRichTextInterpolateRules(data); } - + /** + * content string => array of rules + * + * @param {ExtractRichTextStylesheetRulesRequestModel} data + * @return {*} {Promise>} + * @memberof UmbStylesheetRepository + */ extractStylesheetRules( - data: ExtractRichTextStylesheetRulesRequestModel + data: ExtractRichTextStylesheetRulesRequestModel, ): Promise> { return this.#dataSource.postStylesheetRichTextExtractRules(data); } @@ -204,7 +216,7 @@ export class UmbStylesheetRepository return { data, error, asObservable: () => this.#treeStore!.childrenOf(path) }; } - async requestItemsLegacy(paths: Array) { + async requestItems(paths: Array) { if (!paths) throw new Error('Paths are missing'); await this.#init; const { data, error } = await this.#treeDataSource.getItems(paths); diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index 08ef653320..19913a4d19 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -48,6 +48,10 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext { - debugger; this._rules = rules; }); }); From 9bcb091b6b96ea9b38fd77812484daa72a26043d Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Tue, 22 Aug 2023 10:03:21 +0200 Subject: [PATCH 36/61] fix font in language selector --- .../app-language-select.element.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/languages/app-language-select/app-language-select.element.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/languages/app-language-select/app-language-select.element.ts index ff9a3284db..fd7bbcc359 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/settings/languages/app-language-select/app-language-select.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/settings/languages/app-language-select/app-language-select.element.ts @@ -94,14 +94,13 @@ export class UmbAppLanguageSelectElement extends UmbLitElement { ${repeat( this._languages, (language) => language.isoCode, - (language) => - html` - - ` + (language) => html` + + `, )}
`; } @@ -128,6 +127,7 @@ export class UmbAppLanguageSelectElement extends UmbLitElement { align-items: center; justify-content: space-between; cursor: pointer; + font-family: inherit; } #toggle:hover { From 78f13f4e530b151516d5421397fd137be075dbc8 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Wed, 23 Aug 2023 10:08:27 +0200 Subject: [PATCH 37/61] updating rules and content --- .../workspace/stylesheet-workspace.context.ts | 2 + ...ace-view-rich-text-editor-style-sidebar.ts | 13 ++-- ...workspace-view-rich-text-editor.element.ts | 73 ++++++++++++------- 3 files changed, 54 insertions(+), 34 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index 19913a4d19..a56a3dc52d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -50,6 +50,7 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext>; @customElement('umb-stylesheet-rich-text-editor-style-modal') export default class UmbStylesheetRichTextEditorStyleModalElement extends UmbModalBaseElement< @@ -21,7 +19,7 @@ export default class UmbStylesheetRichTextEditorStyleModalElement extends UmbMod } #submit() { - this.modalContext?.submit({ rule: this._rule ?? {} }); + this.modalContext?.submit({ rule: this._rule }); } connectedCallback() { @@ -30,10 +28,11 @@ export default class UmbStylesheetRichTextEditorStyleModalElement extends UmbMod } @state() - private _rule?: RichTextRuleModel | null = null; + private _rule: RichTextRuleModel | null = null; #updateName(event: Event) { const name = (event.target as HTMLInputElement).value; + this._rule = { ...this._rule, name, @@ -42,6 +41,7 @@ export default class UmbStylesheetRichTextEditorStyleModalElement extends UmbMod #updateSelector(event: Event) { const selector = (event.target as HTMLInputElement).value; + this._rule = { ...this._rule, selector, @@ -50,6 +50,7 @@ export default class UmbStylesheetRichTextEditorStyleModalElement extends UmbMod #updateStyles(event: Event) { const styles = (event.target as HTMLInputElement).value; + this._rule = { ...this._rule, styles, diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts index 56af258ad7..6faaa34fc2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts @@ -2,6 +2,11 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; import { css, html } from 'lit'; import { customElement, state } from 'lit/decorators.js'; import { UmbStylesheetWorkspaceContext } from '../../stylesheet-workspace.context.js'; +import { UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR } from '../../manifests.js'; +import { + StylesheetRichTextEditorStyleModalData, + StylesheetRichTextEditorStyleModalResult, +} from './stylesheet-workspace-view-rich-text-editor-style-sidebar.js'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; import { @@ -11,60 +16,60 @@ import { UmbModalToken, } from '@umbraco-cms/backoffice/modal'; import { RichTextRuleModel } from '@umbraco-cms/backoffice/backend-api'; -import { UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR } from '../../manifests.js'; -import { StylesheetRichTextEditorStyleModalResult } from './stylesheet-workspace-view-rich-text-editor-style-sidebar.js'; -export const UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR_MODAL = new UmbModalToken<{ rule: RichTextRuleModel }>( - UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR, - { - type: 'sidebar', - size: 'medium', - }, -); +export const UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR_MODAL = new UmbModalToken< + StylesheetRichTextEditorStyleModalData, + StylesheetRichTextEditorStyleModalResult +>(UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR, { + type: 'sidebar', + size: 'medium', +}); @customElement('umb-stylesheet-workspace-view-rich-text-editor') export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitElement { @state() - private _content?: string | null = ''; + private _content: string = ''; @state() - private _path?: string | null = ''; + private _path: string = ''; @state() - private _ready?: boolean = false; + private _ready: boolean = false; @state() - private _rules?: RichTextRuleModel[] = []; + _rules: RichTextRuleModel[] = []; - #stylesheetWorkspaceContext?: UmbStylesheetWorkspaceContext; + #context?: UmbStylesheetWorkspaceContext; private _modalContext?: UmbModalManagerContext; #isNew = false; #modal?: UmbModalContext; + #currentlyEditing: RichTextRuleModel | null = null; + constructor() { super(); //tODO: should this be called something else here? this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => { - this.#stylesheetWorkspaceContext = workspaceContext as UmbStylesheetWorkspaceContext; + this.#context = workspaceContext as UmbStylesheetWorkspaceContext; - this.observe(this.#stylesheetWorkspaceContext.content, (content) => { - this._content = content; + this.observe(this.#context.content, (content) => { + this._content = content ?? ''; }); - this.observe(this.#stylesheetWorkspaceContext.path, (path) => { - this._path = path; + this.observe(this.#context.path, (path) => { + this._path = path ?? ''; }); - this.observe(this.#stylesheetWorkspaceContext.isNew, (isNew) => { + this.observe(this.#context.isNew, (isNew) => { this.#isNew = !!isNew; }); - this.observe(this.#stylesheetWorkspaceContext.isCodeEditorReady, (isReady) => { + this.observe(this.#context.isCodeEditorReady, (isReady) => { this._ready = isReady; }); - this.observe(this.#stylesheetWorkspaceContext.rules, (rules) => { + this.observe(this.#context.rules, (rules) => { this._rules = rules; }); }); @@ -74,21 +79,33 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme }); } - #openModal = (rule: RichTextRuleModel = {}) => { + #openModal = (rule: RichTextRuleModel | null = null) => { if (!this._modalContext) throw new Error('Modal context not found'); + this.#currentlyEditing = rule; const modal = this._modalContext.open(UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR_MODAL, { rule, }); - modal?.onSubmit().then((closedModal) => { - console.log(closedModal); + modal?.onSubmit().then((result) => { + if (this.#currentlyEditing && result.rule) { + this.#replaceRule(result.rule); + this.#currentlyEditing = null; + return; + } + if (result.rule) { + this.#context?.setRules([...this._rules, result.rule]); + this.#currentlyEditing = null; + } }); }; #removeRule = (rule: RichTextRuleModel) => { - this._rules = this._rules?.filter((r) => r !== rule); - throw new Error('Method not implemented.'); + this.#context?.setRules(this._rules?.filter((r) => r !== rule)); }; + #replaceRule(rule: RichTextRuleModel) { + this.#context?.setRules(this._rules?.map((r) => (r === this.#currentlyEditing ? rule : r))); + } + renderRule(rule: RichTextRuleModel) { return html`
${rule.name}
@@ -106,7 +123,7 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme

Define the styles that should be available in the rich text editor for this stylesheet.

${this._rules?.map((rule) => this.renderRule(rule))} - Add + this.#openModal(null)}>Add
`; From cee92f3a851175b97351f1db0db3a199e30e6aa0 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Thu, 24 Aug 2023 15:18:28 +0200 Subject: [PATCH 38/61] extract rules from content --- .../stylesheets/workspace/stylesheet-workspace.context.ts | 3 +++ .../stylesheet-workspace-view-code-editor.element.ts | 5 +++++ .../stylesheet-workspace-view-rich-text-editor.element.ts | 4 +++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index a56a3dc52d..391bfe0daa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -88,6 +88,9 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext`; } + disconnectedCallback(): void { + super.disconnectedCallback(); + console.log('disconnected'); + } + render() { return html`
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts index 6faaa34fc2..cf384204a6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts @@ -49,9 +49,9 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme constructor() { super(); - //tODO: should this be called something else here? this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => { this.#context = workspaceContext as UmbStylesheetWorkspaceContext; + this.#context.sendContentGetRules(); this.observe(this.#context.content, (content) => { this._content = content ?? ''; @@ -79,6 +79,8 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme }); } + + #openModal = (rule: RichTextRuleModel | null = null) => { if (!this._modalContext) throw new Error('Modal context not found'); this.#currentlyEditing = rule; From 5acc7192c44a709df5233ac5ba9a961d950cbdb6 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 28 Aug 2023 08:52:41 +0200 Subject: [PATCH 39/61] add todo about bug --- .../core/workspace/workspace-editor/workspace-editor.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-editor/workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-editor/workspace-editor.element.ts index 9bf7e9a930..a16f658e8e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-editor/workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-editor/workspace-editor.element.ts @@ -24,7 +24,7 @@ import { componentHasManifestProperty } from '@umbraco-cms/backoffice/utils'; * @class UmbWorkspaceLayout * @extends {UmbLitElement} */ -// TODO: stop naming this something with layout. as its not just an layout. it hooks up with extensions. +// TODO: This element has a bug in the tabs. After the url changes - for example a new entity/file is chosen in the tree and loaded to the workspace the links in the tabs still point to the previous url and therefore views do not change correctly @customElement('umb-workspace-editor') export class UmbWorkspaceEditorElement extends UmbLitElement { @property() From 75faffbb6b86ab7d2e00164bf64aa05d716a8d9e Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 28 Aug 2023 08:53:02 +0200 Subject: [PATCH 40/61] correct null routing --- .../stylesheets/workspace/stylesheet-workspace.element.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts index 436ff5068b..d6a6bb30cf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts @@ -15,12 +15,11 @@ export class UmbStylesheetWorkspaceElement extends UmbLitElement { @state() _routes: UmbRoute[] = [ { - path: 'create/:parentId', + path: 'create/:path', component: () => this.#element, setup: async (_component, info) => { - const path = info.match.params.parentId; - const serverPath = serverFilePathFromUrlFriendlyPath(path); - this.#workspaceContext.setIsNew(true); + const path = info.match.params.path === 'null' ? null : info.match.params.path; + const serverPath = path === null ? null : serverFilePathFromUrlFriendlyPath(path); await this.#workspaceContext.create(serverPath); new UmbWorkspaceIsNewRedirectController( From 7b94bcc47fd9f2997a2b30b6733c2b1face44a8c Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 28 Aug 2023 08:53:15 +0200 Subject: [PATCH 41/61] cleanup --- .../stylesheet-workspace-view-code-editor.element.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts index 96004df930..0387291433 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts @@ -65,10 +65,6 @@ export class UmbStylesheetWorkspaceViewCodeEditorElement extends UmbLitElement { @input=${this.#onCodeEditorInput}>`; } - disconnectedCallback(): void { - super.disconnectedCallback(); - console.log('disconnected'); - } render() { return html` From 17f6838cdb1ca3f5b223e1e37555c672f080befd Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 28 Aug 2023 15:35:11 +0200 Subject: [PATCH 42/61] implement sorting --- .../workspace/stylesheet-workspace.context.ts | 25 +++++++++---- ...workspace-view-rich-text-editor.element.ts | 36 ++++++++++++++++--- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index 391bfe0daa..4556460fee 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -6,9 +6,11 @@ import { UmbArrayState, UmbBooleanState, UmbObjectState, createObservablePart } import { loadCodeEditor } from '@umbraco-cms/backoffice/code-editor'; import { RichTextRuleModel, UpdateStylesheetRequestModel } from '@umbraco-cms/backoffice/backend-api'; +export type RichTextRuleModelSortable = RichTextRuleModel & { sortOrder?: number }; + export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext { #data = new UmbObjectState(undefined); - #rules = new UmbArrayState([]); + #rules = new UmbArrayState([]); data = this.#data.asObservable(); rules = this.#rules.asObservable(); name = createObservablePart(this.#data, (data) => data?.name); @@ -20,6 +22,7 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext (a.sortOrder ?? 0) - (b.sortOrder ?? 0)); this.#loadCodeEditor(); } @@ -49,7 +52,7 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext ({ ...r, sortOrder: i }))); this.sendRulesGetContent(); } @@ -73,7 +76,7 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext ({ ...r, sortOrder: i })) ?? []); } } @@ -88,9 +91,8 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext (a.sortOrder ?? 0) - (b.sortOrder ?? 0)); + const oldIndex = rules.findIndex((r) => r.name === rule.name); + + if (oldIndex === -1) return false; + rules.splice(oldIndex, 1); + rules.splice(newIndex, 0, rule); + this.setRules(rules.map((r, i) => ({ ...r, sortOrder: i }))); + return true; + } + public async save() { const stylesheet = this.getData(); @@ -130,8 +143,8 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext = { + compareElementToModel: (element: HTMLElement, model: RichTextRuleModel) => { + return element.getAttribute('data-umb-rule-name') === model.name; + }, + querySelectModelToElement: (container: HTMLElement, modelEntry: RichTextRuleModel) => { + return container.querySelector('data-umb-rule-name[' + modelEntry.name + ']'); + }, + identifier: 'stylesheet-rules-sorter', + itemSelector: '[data-umb-rule-name]', + disabledItemSelector: '[inherited]', + containerSelector: '#rules-container', +}; + @customElement('umb-stylesheet-workspace-view-rich-text-editor') export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitElement { @state() @@ -46,6 +62,19 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme #currentlyEditing: RichTextRuleModel | null = null; + #sorter = new UmbSorterController(this, { + ...SORTER_CONFIG, + performItemInsert: ({ item, newIndex }) => { + //return true; + + return this.#context?.findNewSortOrder(item, newIndex) ?? false; + }, + performItemRemove: (args) => { + console.log(args, 'remove'); + return true; + }, + }); + constructor() { super(); @@ -71,6 +100,7 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme this.observe(this.#context.rules, (rules) => { this._rules = rules; + this.#sorter.setModel(this._rules); }); }); @@ -79,8 +109,6 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme }); } - - #openModal = (rule: RichTextRuleModel | null = null) => { if (!this._modalContext) throw new Error('Modal context not found'); this.#currentlyEditing = rule; @@ -109,7 +137,7 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme } renderRule(rule: RichTextRuleModel) { - return html`
+ return html`
${rule.name}
this.#openModal(rule)}>Edit

Define the styles that should be available in the rich text editor for this stylesheet.

- ${this._rules?.map((rule) => this.renderRule(rule))} +
${repeat(this._rules, (rule) => rule.name, this.renderRule)}
this.#openModal(null)}>Add
From 456f0a25612e0578856c4e891e83c27d0986875c Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Tue, 29 Aug 2023 12:43:46 +0200 Subject: [PATCH 43/61] add rule element --- .../stylesheets/workspace/manifests.ts | 3 +- .../workspace/stylesheet-workspace.context.ts | 11 +- ...pace-view-rich-text-editor-rule.element.ts | 87 ++++++++++++++ ...rich-text-editor-style-sidebar.element.ts} | 3 +- ...workspace-view-rich-text-editor.element.ts | 112 ++++-------------- 5 files changed, 122 insertions(+), 94 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-rule.element.ts rename src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/{stylesheet-workspace-view-rich-text-editor-style-sidebar.ts => stylesheet-workspace-view-rich-text-editor-style-sidebar.element.ts} (97%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts index 3c6dde658c..6f6bfff160 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/manifests.ts @@ -82,7 +82,8 @@ const modals: Array = [ type: 'modal', alias: UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR, name: 'Rich text editor style modal', - loader: () => import('./views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.js'), + loader: () => + import('./views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.element.js'), }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index 4556460fee..fac1510f4b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -10,7 +10,7 @@ export type RichTextRuleModelSortable = RichTextRuleModel & { sortOrder?: number export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext { #data = new UmbObjectState(undefined); - #rules = new UmbArrayState([]); + #rules = new UmbArrayState([], (rule) => rule.name); data = this.#data.asObservable(); rules = this.#rules.asObservable(); name = createObservablePart(this.#data, (data) => data?.name); @@ -51,8 +51,13 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext ({ ...r, sortOrder: i }))); + updateRule(unique: string, rule: RichTextRuleModelSortable) { + this.#rules.updateOne(unique, rule); + } + + setRules(rules: RichTextRuleModelSortable[]) { + const newRules = rules.map((r, i) => ({ ...r, sortOrder: i })); + this.#rules.next(newRules); this.sendRulesGetContent(); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-rule.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-rule.element.ts new file mode 100644 index 0000000000..71cd598dbf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-rule.element.ts @@ -0,0 +1,87 @@ +import { UmbStylesheetWorkspaceContext } from '../../stylesheet-workspace.context.js'; +import { UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR_MODAL } from './stylesheet-workspace-view-rich-text-editor.element.js'; +import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui'; +import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; +import { RichTextRuleModel } from '@umbraco-cms/backoffice/backend-api'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; +import { UMB_MODAL_MANAGER_CONTEXT_TOKEN, UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; + +@customElement('umb-stylesheet-rich-text-editor-rule') +export default class UmbStylesheetRichTextEditorRuleElement extends UmbLitElement { + @property({ type: Object, attribute: false }) + private rule: RichTextRuleModel | null = null; + + #context?: UmbStylesheetWorkspaceContext; + private _modalContext?: UmbModalManagerContext; + + constructor() { + super(); + + this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => { + this.#context = workspaceContext as UmbStylesheetWorkspaceContext; + }); + + this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { + this._modalContext = instance; + }); + } + + openModal = () => { + if (!this._modalContext) throw new Error('Modal context not found'); + const modal = this._modalContext.open(UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR_MODAL, { + rule: this.rule, + }); + modal?.onSubmit().then((result) => { + if (result.rule && this.rule?.name) { + this.#context?.updateRule(this.rule?.name, result.rule); + } + }); + }; + + removeRule = () => { + //TODO: SPORTER BREAKS THAT - rules are removed from the data but not from the DOM + if (!this.#context) throw new Error('Context not found'); + this.#context.setRules(this.#context.getRules().filter((r) => r.name !== this.rule?.name)); + }; + + render() { + return html` +
${this.rule?.name}
+
+ EditRemove +
+ `; + } + + static styles = [ + UUITextStyles, + css` + :host { + display: flex; + width: 100%; + justify-content: space-between; + padding: var(--uui-size-2); + align-items: center; + border-radius: var(--uui-border-radius); + background-color: var(--uui-color-surface-alt); + margin-bottom: var(--uui-size-space-4); + } + + .rule-name { + display: flex; + align-items: center; + gap: var(--uui-size-2); + padding-left: var(--uui-size-2); + font-weight: bold; + } + `, + ]; +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-stylesheet-rich-text-editor-rule': UmbStylesheetRichTextEditorRuleElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.element.ts similarity index 97% rename from src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.ts rename to src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.element.ts index ff2db7e201..147952cf48 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.element.ts @@ -2,9 +2,10 @@ import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui'; import { css, html, customElement, ifDefined, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; import { RichTextRuleModel } from '@umbraco-cms/backoffice/backend-api'; +import { RichTextRuleModelSortable } from '../../stylesheet-workspace.context.js'; export interface StylesheetRichTextEditorStyleModalData { - rule: RichTextRuleModel | null; + rule: RichTextRuleModelSortable | null; } export type StylesheetRichTextEditorStyleModalResult = NonNullable>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts index 40b5d7e6c0..a84967deb4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts @@ -1,24 +1,21 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; import { css, html } from 'lit'; import { customElement, state } from 'lit/decorators.js'; -import { UmbStylesheetWorkspaceContext } from '../../stylesheet-workspace.context.js'; +import { RichTextRuleModelSortable, UmbStylesheetWorkspaceContext } from '../../stylesheet-workspace.context.js'; import { UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR } from '../../manifests.js'; import { StylesheetRichTextEditorStyleModalData, StylesheetRichTextEditorStyleModalResult, -} from './stylesheet-workspace-view-rich-text-editor-style-sidebar.js'; +} from './stylesheet-workspace-view-rich-text-editor-style-sidebar.element.js'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; -import { - UMB_MODAL_MANAGER_CONTEXT_TOKEN, - UmbModalContext, - UmbModalManagerContext, - UmbModalToken, -} from '@umbraco-cms/backoffice/modal'; +import { UMB_MODAL_MANAGER_CONTEXT_TOKEN, UmbModalManagerContext, UmbModalToken } from '@umbraco-cms/backoffice/modal'; import { RichTextRuleModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbSorterConfig, UmbSorterController } from '@umbraco-cms/backoffice/sorter'; import { ifDefined, repeat } from '@umbraco-cms/backoffice/external/lit'; +import './stylesheet-workspace-view-rich-text-editor-rule.element.js'; + export const UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR_MODAL = new UmbModalToken< StylesheetRichTextEditorStyleModalData, StylesheetRichTextEditorStyleModalResult @@ -35,33 +32,18 @@ const SORTER_CONFIG: UmbSorterConfig = { return container.querySelector('data-umb-rule-name[' + modelEntry.name + ']'); }, identifier: 'stylesheet-rules-sorter', - itemSelector: '[data-umb-rule-name]', - disabledItemSelector: '[inherited]', + itemSelector: 'umb-stylesheet-rich-text-editor-rule', containerSelector: '#rules-container', }; @customElement('umb-stylesheet-workspace-view-rich-text-editor') export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitElement { @state() - private _content: string = ''; - - @state() - private _path: string = ''; - - @state() - private _ready: boolean = false; - - @state() - _rules: RichTextRuleModel[] = []; + _rules: RichTextRuleModelSortable[] = []; #context?: UmbStylesheetWorkspaceContext; private _modalContext?: UmbModalManagerContext; - #isNew = false; - #modal?: UmbModalContext; - - #currentlyEditing: RichTextRuleModel | null = null; - #sorter = new UmbSorterController(this, { ...SORTER_CONFIG, performItemInsert: ({ item, newIndex }) => { @@ -70,7 +52,6 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme return this.#context?.findNewSortOrder(item, newIndex) ?? false; }, performItemRemove: (args) => { - console.log(args, 'remove'); return true; }, }); @@ -82,22 +63,6 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme this.#context = workspaceContext as UmbStylesheetWorkspaceContext; this.#context.sendContentGetRules(); - this.observe(this.#context.content, (content) => { - this._content = content ?? ''; - }); - - this.observe(this.#context.path, (path) => { - this._path = path ?? ''; - }); - - this.observe(this.#context.isNew, (isNew) => { - this.#isNew = !!isNew; - }); - - this.observe(this.#context.isCodeEditorReady, (isReady) => { - this._ready = isReady; - }); - this.observe(this.#context.rules, (rules) => { this._rules = rules; this.#sorter.setModel(this._rules); @@ -109,51 +74,39 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme }); } - #openModal = (rule: RichTextRuleModel | null = null) => { + openModal = (rule: RichTextRuleModelSortable | null = null) => { if (!this._modalContext) throw new Error('Modal context not found'); - this.#currentlyEditing = rule; const modal = this._modalContext.open(UMB_MODAL_TEMPLATING_STYLESHEET_RTF_STYLE_SIDEBAR_MODAL, { rule, }); modal?.onSubmit().then((result) => { - if (this.#currentlyEditing && result.rule) { - this.#replaceRule(result.rule); - this.#currentlyEditing = null; - return; - } if (result.rule) { - this.#context?.setRules([...this._rules, result.rule]); - this.#currentlyEditing = null; + this.#context?.setRules([...this._rules, { ...result.rule, sortOrder: this._rules.length }]); } }); }; - #removeRule = (rule: RichTextRuleModel) => { - this.#context?.setRules(this._rules?.filter((r) => r !== rule)); + removeRule = (rule: RichTextRuleModelSortable) => { + const rules = this._rules?.filter((r) => r.name !== rule.name); + this.#context?.setRules(rules); }; - #replaceRule(rule: RichTextRuleModel) { - this.#context?.setRules(this._rules?.map((r) => (r === this.#currentlyEditing ? rule : r))); - } - - renderRule(rule: RichTextRuleModel) { - return html`
-
${rule.name}
-
- this.#openModal(rule)}>Edit this.#removeRule(rule)} - >Remove -
-
`; - } render() { return html`

Define the styles that should be available in the rich text editor for this stylesheet.

-
${repeat(this._rules, (rule) => rule.name, this.renderRule)}
- this.#openModal(null)}>Add +
+ ${repeat( + this._rules, + (rule) => rule?.name ?? '' + rule?.sortOrder ?? '', + (rule) => + html``, + )} +
+ this.openModal(null)}>Add
`; @@ -182,25 +135,6 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme max-width: 600px; } - .rule-name { - display: flex; - align-items: center; - gap: var(--uui-size-2); - padding-left: var(--uui-size-2); - font-weight: bold; - } - - .rule { - display: flex; - width: 100%; - justify-content: space-between; - padding: var(--uui-size-2); - align-items: center; - border-radius: var(--uui-border-radius); - background-color: var(--uui-color-surface-alt); - margin-bottom: var(--uui-size-space-4); - } - uui-box { margin: var(--uui-size-layout-1); } From bb408dd355892e3e950e74967ea4f605e39d097c Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Tue, 29 Aug 2023 14:23:12 +0200 Subject: [PATCH 44/61] clenaup --- .../packages/templating/stylesheets/index.ts | 2 -- .../stylesheet-workspace-editor.element.ts | 15 ------------- ...heet-workspace-view-code-editor.element.ts | 22 +------------------ ...-rich-text-editor-style-sidebar.element.ts | 2 +- ...workspace-view-rich-text-editor.element.ts | 5 ++--- 5 files changed, 4 insertions(+), 42 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts index e3d083d6f8..ec91672f86 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/index.ts @@ -1,7 +1,5 @@ import { StylesheetResponseModel } from '@umbraco-cms/backoffice/backend-api'; -// TODO: temp until we have a proper stylesheet model export type StylesheetDetails = StylesheetResponseModel; - export * from './repository/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts index 337ba18cbe..404ec695ca 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts @@ -24,10 +24,6 @@ export class UmbStylesheetWorkspaceEditorElement extends UmbLitElement { @state() private _path?: string; - private _modalContext?: UmbModalManagerContext; - - #isNew = false; - private inputQuery$ = new Subject(); constructor() { @@ -40,23 +36,12 @@ export class UmbStylesheetWorkspaceEditorElement extends UmbLitElement { this.#workspaceContext?.setName(`${nameInputValue}.css`); }); }); - - this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { - this._modalContext = instance; - }); } #observeNameAndPath() { if (!this.#workspaceContext) return; this.observe(this.#workspaceContext.name, (name) => (this._name = name ?? ''), '_observeName'); this.observe(this.#workspaceContext.path, (path) => (this._path = path ?? ''), '_observePath'); - this.observe( - this.#workspaceContext.isNew, - (isNew) => { - this.#isNew = !!isNew; - }, - '_observeIsNew', - ); } #onNameChange(event: UUIInputEvent) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts index 0387291433..614870d536 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts @@ -1,10 +1,9 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; import { css, html } from 'lit'; -import { customElement, query, state } from 'lit/decorators.js'; +import { customElement, state } from 'lit/decorators.js'; import { UmbStylesheetWorkspaceContext } from '../../stylesheet-workspace.context.js'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor'; -import { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; @customElement('umb-stylesheet-workspace-view-code-editor') @@ -12,24 +11,14 @@ export class UmbStylesheetWorkspaceViewCodeEditorElement extends UmbLitElement { @state() private _content?: string | null = ''; - @state() - private _path?: string | null = ''; - @state() private _ready?: boolean = false; - @query('umb-code-editor') - private _codeEditor?: UmbCodeEditorElement; - #stylesheetWorkspaceContext?: UmbStylesheetWorkspaceContext; - private _modalContext?: UmbModalManagerContext; - - #isNew = false; constructor() { super(); - //tODO: should this be called something else here? this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => { this.#stylesheetWorkspaceContext = workspaceContext as UmbStylesheetWorkspaceContext; @@ -37,14 +26,6 @@ export class UmbStylesheetWorkspaceViewCodeEditorElement extends UmbLitElement { this._content = content; }); - this.observe(this.#stylesheetWorkspaceContext.path, (path) => { - this._path = path; - }); - - this.observe(this.#stylesheetWorkspaceContext.isNew, (isNew) => { - this.#isNew = !!isNew; - }); - this.observe(this.#stylesheetWorkspaceContext.isCodeEditorReady, (isReady) => { this._ready = isReady; }); @@ -65,7 +46,6 @@ export class UmbStylesheetWorkspaceViewCodeEditorElement extends UmbLitElement { @input=${this.#onCodeEditorInput}>`; } - render() { return html`
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.element.ts index 147952cf48..6b1c8c51da 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.element.ts @@ -1,8 +1,8 @@ +import { RichTextRuleModelSortable } from '../../stylesheet-workspace.context.js'; import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui'; import { css, html, customElement, ifDefined, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; import { RichTextRuleModel } from '@umbraco-cms/backoffice/backend-api'; -import { RichTextRuleModelSortable } from '../../stylesheet-workspace.context.js'; export interface StylesheetRichTextEditorStyleModalData { rule: RichTextRuleModelSortable | null; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts index a84967deb4..d6db2a93f2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor.element.ts @@ -47,11 +47,10 @@ export class UmbStylesheetWorkspaceViewRichTextEditorElement extends UmbLitEleme #sorter = new UmbSorterController(this, { ...SORTER_CONFIG, performItemInsert: ({ item, newIndex }) => { - //return true; - return this.#context?.findNewSortOrder(item, newIndex) ?? false; }, - performItemRemove: (args) => { + performItemRemove: () => { + //defined so the default does not run return true; }, }); From e24a04ccbac4be0b8667014799f29e524565cf8c Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Wed, 30 Aug 2023 12:48:16 +0200 Subject: [PATCH 45/61] Update stylesheet.folder.server.data.ts --- .../repository/sources/stylesheet.folder.server.data.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.folder.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.folder.server.data.ts index 4a36b6ea60..a20273ca95 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.folder.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/repository/sources/stylesheet.folder.server.data.ts @@ -1,7 +1,7 @@ import { CreateFolderRequestModel, FolderModelBaseModel, - FolderReponseModel, + FolderResponseModel, StylesheetResource, } from '@umbraco-cms/backoffice/backend-api'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; @@ -30,7 +30,7 @@ export class UmbStylesheetFolderServerDataSource implements UmbFolderDataSource update(unique: string, data: CreateFolderRequestModel): Promise> { throw new Error('Method not implemented.'); } - createScaffold(parentId: string | null): Promise> { + createScaffold(parentId: string | null): Promise> { throw new Error('Method not implemented.'); } } From f1247541854e34de39355d865788ded0fc75e330 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Mon, 4 Sep 2023 10:18:49 +0200 Subject: [PATCH 46/61] rename create item utils funcion --- .../src/mocks/data/stylesheet.data.ts | 26 +++++++++---------- .../src/mocks/data/utils.ts | 5 ++-- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts index d39dcc79d0..8b78df25d9 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts @@ -1,5 +1,5 @@ import { UmbEntityData } from './entity.data.js'; -import { createFileSystemTreeItem, createItem, createTextFileItem } from './utils.js'; +import { createFileSystemTreeItem, createFileItemResponseModelBaseModel, createTextFileItem } from './utils.js'; import { CreateTextFileViewModelBaseModel, FileSystemTreeItemPresentationModel, @@ -125,7 +125,7 @@ class UmbStylesheetData extends UmbEntityData { } getStylesheetItem(path: string): StylesheetDBItem | undefined { - return createItem(this.data.find((item) => item.path === path)); + return createFileItemResponseModelBaseModel(this.data.find((item) => item.path === path)); } getStylesheet(path: string): StylesheetResponseModel | undefined { @@ -146,21 +146,21 @@ class UmbStylesheetData extends UmbEntityData { getRules(path: string): Array { return [ { - "name": "bjjh", - "selector": "h1", - "styles": "color: blue;" + name: 'bjjh', + selector: 'h1', + styles: 'color: blue;', }, { - "name": "comeone", - "selector": "h1", - "styles": "color: blue;" + name: 'comeone', + selector: 'h1', + styles: 'color: blue;', }, { - "name": "lol", - "selector": "h1", - "styles": "color: blue;" - } - ] + name: 'lol', + selector: 'h1', + styles: 'color: blue;', + }, + ]; } insertFolder(item: CreateTextFileViewModelBaseModel) { diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/utils.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/utils.ts index 32caed7acf..33adf91412 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/utils.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/utils.ts @@ -8,6 +8,7 @@ import type { FileSystemTreeItemPresentationModel, DocumentResponseModel, TextFileResponseModelBaseModel, + FileItemResponseModelBaseModel, } from '@umbraco-cms/backoffice/backend-api'; export const createEntityTreeItem = (item: any): EntityTreeItemResponseModel => { @@ -40,7 +41,7 @@ export const createContentTreeItem = (item: any): ContentTreeItemResponseModel & // TODO: remove isTrashed type extension when we have found a solution to trashed items export const createDocumentTreeItem = ( - item: DocumentResponseModel + item: DocumentResponseModel, ): DocumentTreeItemResponseModel & { isTrashed: boolean } => { return { ...createContentTreeItem(item), @@ -81,7 +82,7 @@ export const createTextFileItem = (item: any): TextFileResponseModelBaseModel => content: item.content, }); -export const createItem = (item: any): any => ({ +export const createFileItemResponseModelBaseModel = (item: any): FileItemResponseModelBaseModel => ({ path: item.path, name: item.name, icon: item.icon, From 811f0772111fb658318a283dacb7077f48879438 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Tue, 5 Sep 2023 11:19:47 +0200 Subject: [PATCH 47/61] add handlers --- .../src/mocks/data/stylesheet.data.ts | 79 +++++++++++++++---- .../src/mocks/handlers/stylesheet.handlers.ts | 38 ++++++++- 2 files changed, 98 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts index 8b78df25d9..f1e41f9981 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts @@ -2,13 +2,18 @@ import { UmbEntityData } from './entity.data.js'; import { createFileSystemTreeItem, createFileItemResponseModelBaseModel, createTextFileItem } from './utils.js'; import { CreateTextFileViewModelBaseModel, + ExtractRichTextStylesheetRulesRequestModel, FileSystemTreeItemPresentationModel, + InterpolateRichTextStylesheetRequestModel, PagedFileSystemTreeItemPresentationModel, PagedStylesheetOverviewResponseModel, RichTextRuleModel, StylesheetResponseModel, } from '@umbraco-cms/backoffice/backend-api'; +//prettier-ignore +// eslint-disable-next-line no-useless-escape + type StylesheetDBItem = StylesheetResponseModel & FileSystemTreeItemPresentationModel & { icon?: string }; export const data: Array = [ @@ -144,23 +149,63 @@ class UmbStylesheetData extends UmbEntityData { } getRules(path: string): Array { - return [ - { - name: 'bjjh', - selector: 'h1', - styles: 'color: blue;', - }, - { - name: 'comeone', - selector: 'h1', - styles: 'color: blue;', - }, - { - name: 'lol', - selector: 'h1', - styles: 'color: blue;', - }, - ]; + const regex = /\*\*\s*umb_name:\s*(?[^*\r\n]*?)\s*\*\/\s*(?[^,{]*?)\s*{\s*(?.*?)\s*}/gis; + const item = this.data.find((item) => item.path === path); + if (!item) throw Error('item not found'); + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + //@ts-ignore + // eslint-disable-next-line no-unsafe-optional-chaining + const rules = [...item.content?.matchAll(regex)].map((match) => match.groups); + return rules; + } + + extractRules({ + requestBody, + }: { + requestBody?: ExtractRichTextStylesheetRulesRequestModel, + }) { + const regex = /\*\*\s*umb_name:\s*(?[^*\r\n]*?)\s*\*\/\s*(?[^,{]*?)\s*{\s*(?.*?)\s*}/gis; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + //@ts-ignore + // eslint-disable-next-line no-unsafe-optional-chaining + const rules = [...requestBody.content?.matchAll(regex)].map((match) => match.groups); + return rules; + + } + + interpolateRules({ + requestBody, + }: { + requestBody?: InterpolateRichTextStylesheetRequestModel, + }) { + debugger; + const regex = /\/\*\*\s*umb_name:\s*(?[^*\r\n]*?)\s*\*\/\s*(?[^,{]*?)\s*{\s*(?.*?)\s*}/gis; + if(!requestBody) { + throw Error('No request body') + } + const {content, rules} = requestBody; + + if(!content && !rules) return {content: ''}; + + console.log(content) + + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + //@ts-ignore + // eslint-disable-next-line no-unsafe-optional-chaining + const cleanedContent = content?.replaceAll(regex, '') + + const newContent = rules?.map(rule => + `/**umb_name:${rule.name}*/ + ${rule.selector} { + ${rule.styles} + } + ${cleanedContent} + `) + + return {content: newContent}; + } insertFolder(item: CreateTextFileViewModelBaseModel) { diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts index daa04b5623..5d2f24e77f 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts @@ -1,6 +1,11 @@ const { rest } = window.MockServiceWorker; import { umbStylesheetData } from '../data/stylesheet.data.js'; -import { CreateTextFileViewModelBaseModel } from '@umbraco-cms/backoffice/backend-api'; +import { + CreateTextFileViewModelBaseModel, + ExtractRichTextStylesheetRulesRequestModel, + ExtractRichTextStylesheetRulesResponseModel, + InterpolateRichTextStylesheetRequestModel, +} from '@umbraco-cms/backoffice/backend-api'; import { umbracoPath } from '@umbraco-cms/backoffice/utils'; const treeHandlers = [ @@ -69,6 +74,35 @@ const detailHandlers = [ }), ]; +type getRulesRequestBody = { path?: string }; + +const rulesHandlers = [ + rest.post(umbracoPath('/stylesheet/rich-text/extract-rules'), (req, res, ctx) => { + const requestBody = req.json() as ExtractRichTextStylesheetRulesRequestModel; + if (!requestBody) return res(ctx.status(400, 'no body found')); + const response = umbStylesheetData.extractRules({ requestBody }); + return res(ctx.status(200), ctx.json(response)); + }), + + rest.post(umbracoPath('/stylesheet/rich-text/interpolate-rules'), (req, res, ctx) => { + const requestBody = req.json() as InterpolateRichTextStylesheetRequestModel; + if (!requestBody) return res(ctx.status(400, 'no body found')); + const response = umbStylesheetData.interpolateRules({ requestBody }); + return res(ctx.status(200), ctx.json(response)); + }), + + rest.get(umbracoPath('/stylesheet/rich-text/rules'), (req, res, ctx) => { + const path = req.url.searchParams.get('path'); + if (!path) return res(ctx.status(400)); + try { + const response = umbStylesheetData.getRules(path); + return res(ctx.status(200), ctx.json(response)); + } catch (e) { + return res(ctx.status(404)); + } + }), +]; + const folderHandlers = [ rest.get(umbracoPath('/v1/stylesheet/all'), (req, res, ctx) => { const path = req.url.searchParams.get('path'); @@ -91,4 +125,4 @@ const folderHandlers = [ }), ]; -export const handlers = [...treeHandlers, ...detailHandlers, ...folderHandlers]; +export const handlers = [...treeHandlers, ...detailHandlers, ...folderHandlers, ...rulesHandlers]; From 550d39bbc32c47ef3d0039a7a595ac43fdd25cf0 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Tue, 5 Sep 2023 12:36:05 +0200 Subject: [PATCH 48/61] fix handlers --- .../src/mocks/data/stylesheet.data.ts | 57 +++++++++---------- .../workspace/stylesheet-workspace.context.ts | 4 +- ...workspace-view-rich-text-editor.element.ts | 1 - 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts index f1e41f9981..318e0c4421 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts @@ -3,6 +3,7 @@ import { createFileSystemTreeItem, createFileItemResponseModelBaseModel, createT import { CreateTextFileViewModelBaseModel, ExtractRichTextStylesheetRulesRequestModel, + ExtractRichTextStylesheetRulesResponseModel, FileSystemTreeItemPresentationModel, InterpolateRichTextStylesheetRequestModel, PagedFileSystemTreeItemPresentationModel, @@ -148,7 +149,7 @@ class UmbStylesheetData extends UmbEntityData { return this.data.find((item) => item.path === path && item.isFolder === true); } - getRules(path: string): Array { + getRules(path: string): ExtractRichTextStylesheetRulesResponseModel { const regex = /\*\*\s*umb_name:\s*(?[^*\r\n]*?)\s*\*\/\s*(?[^,{]*?)\s*{\s*(?.*?)\s*}/gis; const item = this.data.find((item) => item.path === path); if (!item) throw Error('item not found'); @@ -157,55 +158,49 @@ class UmbStylesheetData extends UmbEntityData { //@ts-ignore // eslint-disable-next-line no-unsafe-optional-chaining const rules = [...item.content?.matchAll(regex)].map((match) => match.groups); - return rules; + return { rules }; } - extractRules({ - requestBody, - }: { - requestBody?: ExtractRichTextStylesheetRulesRequestModel, - }) { + async extractRules({ requestBody }: { requestBody?: ExtractRichTextStylesheetRulesRequestModel }) { const regex = /\*\*\s*umb_name:\s*(?[^*\r\n]*?)\s*\*\/\s*(?[^,{]*?)\s*{\s*(?.*?)\s*}/gis; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - //@ts-ignore - // eslint-disable-next-line no-unsafe-optional-chaining - const rules = [...requestBody.content?.matchAll(regex)].map((match) => match.groups); - return rules; + if (!requestBody) { + throw Error('No request body'); + } + const { content } = await requestBody; + if (!content) return { rules: [] }; + + const rules = [...content.matchAll(regex)].map((match) => match.groups); + return { rules }; } - interpolateRules({ - requestBody, - }: { - requestBody?: InterpolateRichTextStylesheetRequestModel, - }) { - debugger; + interpolateRules({ requestBody }: { requestBody?: InterpolateRichTextStylesheetRequestModel }) { const regex = /\/\*\*\s*umb_name:\s*(?[^*\r\n]*?)\s*\*\/\s*(?[^,{]*?)\s*{\s*(?.*?)\s*}/gis; - if(!requestBody) { - throw Error('No request body') + if (!requestBody) { + throw Error('No request body'); } - const {content, rules} = requestBody; + const { content, rules } = requestBody; - if(!content && !rules) return {content: ''}; + if (!content && !rules) return { content: '' }; - console.log(content) + console.log(content); - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // eslint-disable-next-line @typescript-eslint/ban-ts-comment //@ts-ignore // eslint-disable-next-line no-unsafe-optional-chaining - const cleanedContent = content?.replaceAll(regex, '') + const cleanedContent = content?.replaceAll(regex, ''); - const newContent = rules?.map(rule => - `/**umb_name:${rule.name}*/ + const newContent = rules?.map( + (rule) => + `/**umb_name:${rule.name}*/ ${rule.selector} { ${rule.styles} } ${cleanedContent} - `) - - return {content: newContent}; + `, + ); + return { content: newContent }; } insertFolder(item: CreateTextFileViewModelBaseModel) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index fac1510f4b..8ee2e24e01 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -81,7 +81,8 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext ({ ...r, sortOrder: i })) ?? []); + const x = rules.data.rules?.map((r, i) => ({ ...r, sortOrder: i })) ?? []; + this.#rules.next(x); } } @@ -96,6 +97,7 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext { this.#context = workspaceContext as UmbStylesheetWorkspaceContext; - this.#context.sendContentGetRules(); this.observe(this.#context.rules, (rules) => { this._rules = rules; From f668f4fc6f36694be2ab8644cef7879c796ae339 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Tue, 5 Sep 2023 12:45:04 +0200 Subject: [PATCH 49/61] add diconnected callback --- .../src/external/monaco-editor/index.ts | 2 +- .../stylesheet-workspace-view-code-editor.element.ts | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/external/monaco-editor/index.ts b/src/Umbraco.Web.UI.Client/src/external/monaco-editor/index.ts index 82dd0fdf1e..d77864aa8c 100644 --- a/src/Umbraco.Web.UI.Client/src/external/monaco-editor/index.ts +++ b/src/Umbraco.Web.UI.Client/src/external/monaco-editor/index.ts @@ -1,4 +1,4 @@ -import styles from 'monaco-editor/min/vs/editor/editor.main.css'; +import styles from 'monaco-editor/min/vs/editor/editor.main.css?inline'; //eslint-disable-next-line import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker'; //eslint-disable-next-line diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts index 614870d536..4963b9931c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-workspace-view-code-editor.element.ts @@ -32,6 +32,11 @@ export class UmbStylesheetWorkspaceViewCodeEditorElement extends UmbLitElement { }); } + disconnectedCallback(): void { + super.disconnectedCallback(); + this.#stylesheetWorkspaceContext?.sendContentGetRules(); + } + #onCodeEditorInput(event: Event) { const target = event.target as UmbCodeEditorElement; const value = target.code as string; From f0ceea556722ece282fe209ac320af526c7b58cf Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Tue, 5 Sep 2023 13:15:54 +0200 Subject: [PATCH 50/61] remove vite inline import --- src/Umbraco.Web.UI.Client/src/external/monaco-editor/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/external/monaco-editor/index.ts b/src/Umbraco.Web.UI.Client/src/external/monaco-editor/index.ts index d77864aa8c..82dd0fdf1e 100644 --- a/src/Umbraco.Web.UI.Client/src/external/monaco-editor/index.ts +++ b/src/Umbraco.Web.UI.Client/src/external/monaco-editor/index.ts @@ -1,4 +1,4 @@ -import styles from 'monaco-editor/min/vs/editor/editor.main.css?inline'; +import styles from 'monaco-editor/min/vs/editor/editor.main.css'; //eslint-disable-next-line import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker'; //eslint-disable-next-line From 92a6773978a826b76a2a7001f8071352fd54cc26 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Wed, 6 Sep 2023 09:12:09 +0200 Subject: [PATCH 51/61] fix typo --- ...eet-workspace-view-rich-text-editor-style-sidebar.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.element.ts index 6b1c8c51da..5d383ac3c1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/rich-text-editor/stylesheet-workspace-view-rich-text-editor-style-sidebar.element.ts @@ -90,7 +90,7 @@ export default class UmbStylesheetRichTextEditorStyleModalElement extends UmbMod - Selector + Styles The CSS that should be applied in the rich text editor, e.g. "color:red;" From ab0a5cc11b05089dc9515bc4d7e12a09f5eaaf4b Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Wed, 6 Sep 2023 10:08:17 +0200 Subject: [PATCH 52/61] fix bug with content --- .../src/mocks/data/stylesheet.data.ts | 15 ++++++--------- .../src/mocks/handlers/stylesheet.handlers.ts | 4 ++-- .../workspace/stylesheet-workspace.context.ts | 3 ++- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts index 318e0c4421..1403fa051a 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts @@ -169,7 +169,6 @@ class UmbStylesheetData extends UmbEntityData { } const { content } = await requestBody; if (!content) return { rules: [] }; - const rules = [...content.matchAll(regex)].map((match) => match.groups); return { rules }; } @@ -180,25 +179,23 @@ class UmbStylesheetData extends UmbEntityData { throw Error('No request body'); } const { content, rules } = requestBody; - if (!content && !rules) return { content: '' }; - console.log(content); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment //@ts-ignore - // eslint-disable-next-line no-unsafe-optional-chaining const cleanedContent = content?.replaceAll(regex, ''); - const newContent = rules?.map( - (rule) => - `/**umb_name:${rule.name}*/ + const newContent = rules + ?.map( + (rule) => + `/**umb_name:${rule.name}*/ ${rule.selector} { ${rule.styles} } ${cleanedContent} `, - ); + ) + .join(''); return { content: newContent }; } diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts index 5d2f24e77f..a035c5d62a 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts @@ -84,8 +84,8 @@ const rulesHandlers = [ return res(ctx.status(200), ctx.json(response)); }), - rest.post(umbracoPath('/stylesheet/rich-text/interpolate-rules'), (req, res, ctx) => { - const requestBody = req.json() as InterpolateRichTextStylesheetRequestModel; + rest.post(umbracoPath('/stylesheet/rich-text/interpolate-rules'), async (req, res, ctx) => { + const requestBody = (await req.json()) as InterpolateRichTextStylesheetRequestModel; if (!requestBody) return res(ctx.status(400, 'no body found')); const response = umbStylesheetData.interpolateRules({ requestBody }); return res(ctx.status(200), ctx.json(response)); diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index 84ab0d335a..069b4d8846 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -54,6 +54,8 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext Date: Wed, 6 Sep 2023 10:33:26 +0200 Subject: [PATCH 53/61] fix fake data mistakes --- .../src/mocks/data/stylesheet.data.ts | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts index 1403fa051a..bd383186c0 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts @@ -50,7 +50,6 @@ export const data: Array = [ path: 'Stylesheet File 2.css', isFolder: false, icon: 'style', - name: 'Stylesheet File 2.css', type: 'stylesheet', hasChildren: false, @@ -58,44 +57,50 @@ export const data: Array = [ color: green; } - /**umb_name:bjjh*/ + /**umb_name:HELLO*/ h1 { color: green; } - /**umb_name:comeone*/ + /**umb_name:SOMETHING*/ h1 { color: green; } - /**umb_name:lol*/ + /**umb_name:NIOCE*/ h1 { color: green; }`, }, { path: 'Folder 1', + name: 'Folder 1', isFolder: true, icon: 'folder', - - name: 'Folder 1', type: 'stylesheet', hasChildren: true, + }, + { + path: 'Folder 1/Stylesheet File 3.css', + name: 'Stylesheet File 3.css', + type: 'stylesheet', + hasChildren: true, + isFolder: false, content: ` h1 { color: pink; } - /**umb_name:bjjh*/ + /**umb_name:ONE*/ h1 { color: pink; } - /**umb_name:comeone*/ + /**umb_name:TWO*/ h1 { color: pink; } - /**umb_name:lol*/ + /**umb_name:THREE*/ h1 { color: pink; }`, From c27611528314f7b936609f1c01ade6d2dff53153 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Wed, 6 Sep 2023 10:38:25 +0200 Subject: [PATCH 54/61] load component on route change --- .../stylesheets/workspace/stylesheet-workspace.element.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts index d6a6bb30cf..9b18405108 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts @@ -16,7 +16,7 @@ export class UmbStylesheetWorkspaceElement extends UmbLitElement { _routes: UmbRoute[] = [ { path: 'create/:path', - component: () => this.#element, + component: import('./stylesheet-workspace-editor.element.js'), setup: async (_component, info) => { const path = info.match.params.path === 'null' ? null : info.match.params.path; const serverPath = path === null ? null : serverFilePathFromUrlFriendlyPath(path); @@ -31,7 +31,7 @@ export class UmbStylesheetWorkspaceElement extends UmbLitElement { }, { path: 'edit/:path', - component: () => this.#element, + component: import('./stylesheet-workspace-editor.element.js'), setup: (_component, info) => { this.removeControllerByAlias('_observeIsNew'); const path = info.match.params.path; From 3dfd9783365f1ef463bef2a0714d01189c658319 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Wed, 6 Sep 2023 10:44:53 +0200 Subject: [PATCH 55/61] fix rules --- .../src/mocks/handlers/stylesheet.handlers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts index a035c5d62a..3f66a5c3e1 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts @@ -77,10 +77,10 @@ const detailHandlers = [ type getRulesRequestBody = { path?: string }; const rulesHandlers = [ - rest.post(umbracoPath('/stylesheet/rich-text/extract-rules'), (req, res, ctx) => { + rest.post(umbracoPath('/stylesheet/rich-text/extract-rules'), async (req, res, ctx) => { const requestBody = req.json() as ExtractRichTextStylesheetRulesRequestModel; if (!requestBody) return res(ctx.status(400, 'no body found')); - const response = umbStylesheetData.extractRules({ requestBody }); + const response = await umbStylesheetData.extractRules({ requestBody }); return res(ctx.status(200), ctx.json(response)); }), From 07190318566c8b5f952954a7f66d663298c7f128 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Wed, 6 Sep 2023 11:19:29 +0200 Subject: [PATCH 56/61] fix formatting --- .../src/mocks/data/stylesheet.data.ts | 134 +++++++++--------- .../src/mocks/handlers/stylesheet.handlers.ts | 1 - 2 files changed, 67 insertions(+), 68 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts index bd383186c0..42253c24b4 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts @@ -25,26 +25,24 @@ export const data: Array = [ name: 'Stylesheet File 1.css', type: 'stylesheet', hasChildren: false, - content: ` - h1 { - color: blue; - } - - /**umb_name:bjjh*/ - h1 { - color: blue; - } - - /**umb_name:comeone*/ - h1 { - color: blue; - } - - /**umb_name:lol*/ - h1 { - color: blue; - } - `, + content: `h1 { + color: blue; +} + +/**umb_name:bjjh*/ +h1 { + color: blue; +} + +/**umb_name:comeone*/ +h1 { + color: blue; +} + +/**umb_name:lol*/ +h1 { + color: blue; +}`, }, { path: 'Stylesheet File 2.css', @@ -53,24 +51,24 @@ export const data: Array = [ name: 'Stylesheet File 2.css', type: 'stylesheet', hasChildren: false, - content: ` h1 { - color: green; - } - - /**umb_name:HELLO*/ - h1 { - color: green; - } - - /**umb_name:SOMETHING*/ - h1 { - color: green; - } - - /**umb_name:NIOCE*/ - h1 { - color: green; - }`, + content: `h1 { + color: green; +} + +/**umb_name:HELLO*/ +h1 { + color: green; +} + +/**umb_name:SOMETHING*/ +h1 { + color: green; +} + +/**umb_name:NIOCE*/ +h1 { + color: green; +}`, }, { path: 'Folder 1', @@ -86,24 +84,24 @@ export const data: Array = [ type: 'stylesheet', hasChildren: true, isFolder: false, - content: ` h1 { - color: pink; - } - - /**umb_name:ONE*/ - h1 { - color: pink; - } - - /**umb_name:TWO*/ - h1 { - color: pink; - } - - /**umb_name:THREE*/ - h1 { - color: pink; - }`, + content: `h1 { + color: pink; +} + +/**umb_name:ONE*/ +h1 { + color: pink; +} + +/**umb_name:TWO*/ +h1 { + color: pink; +} + +/**umb_name:THREE*/ +h1 { + color: pink; +}`, }, ]; @@ -190,17 +188,19 @@ class UmbStylesheetData extends UmbEntityData { //@ts-ignore const cleanedContent = content?.replaceAll(regex, ''); - const newContent = rules - ?.map( - (rule) => - `/**umb_name:${rule.name}*/ - ${rule.selector} { - ${rule.styles} - } - ${cleanedContent} - `, - ) - .join(''); + const newContent = `${cleanedContent.replace(/[\r\n]+$/, '')} + +${rules + ?.map( + (rule) => + `/**umb_name:${rule.name}*/ +${rule.selector} { + ${rule.styles} +} + +`, + ) + .join('')}`; return { content: newContent }; } diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts index 3f66a5c3e1..33e04255bd 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts @@ -74,7 +74,6 @@ const detailHandlers = [ }), ]; -type getRulesRequestBody = { path?: string }; const rulesHandlers = [ rest.post(umbracoPath('/stylesheet/rich-text/extract-rules'), async (req, res, ctx) => { From 094933a61f07bfe815d857aa1ca97f0089cc2ef7 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Wed, 6 Sep 2023 11:21:44 +0200 Subject: [PATCH 57/61] cleanup --- src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts | 1 - .../src/mocks/handlers/stylesheet.handlers.ts | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts index 42253c24b4..686dd7eaa1 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts @@ -8,7 +8,6 @@ import { InterpolateRichTextStylesheetRequestModel, PagedFileSystemTreeItemPresentationModel, PagedStylesheetOverviewResponseModel, - RichTextRuleModel, StylesheetResponseModel, } from '@umbraco-cms/backoffice/backend-api'; diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts index 33e04255bd..28990ca33b 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts @@ -3,7 +3,6 @@ import { umbStylesheetData } from '../data/stylesheet.data.js'; import { CreateTextFileViewModelBaseModel, ExtractRichTextStylesheetRulesRequestModel, - ExtractRichTextStylesheetRulesResponseModel, InterpolateRichTextStylesheetRequestModel, } from '@umbraco-cms/backoffice/backend-api'; import { umbracoPath } from '@umbraco-cms/backoffice/utils'; @@ -55,7 +54,7 @@ const detailHandlers = [ rest.put(umbracoPath('/stylesheet'), (req, res, ctx) => { const requestBody = req.json() as CreateTextFileViewModelBaseModel; if (!requestBody) return res(ctx.status(400, 'no body found')); - const response = umbStylesheetData.updateData(requestBody); + umbStylesheetData.updateData(requestBody); return res(ctx.status(200)); }), rest.get(umbracoPath('/v1/stylesheet/all'), (req, res, ctx) => { From 826211771707871ac2702a5b440081fdb7d8f8fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 6 Sep 2023 12:00:08 +0200 Subject: [PATCH 58/61] corrections for stylesheet mock data handler --- .../src/mocks/data/stylesheet.data.ts | 70 +++++++++++++++++-- .../src/mocks/handlers/stylesheet.handlers.ts | 6 +- .../stylesheet-workspace-editor.element.ts | 1 - .../workspace/stylesheet-workspace.context.ts | 7 +- ...heet-workspace-view-code-editor.element.ts | 7 +- 5 files changed, 79 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts index 686dd7eaa1..d202cc391b 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts @@ -1,4 +1,4 @@ -import { UmbEntityData } from './entity.data.js'; +import { UmbData } from './data.js'; import { createFileSystemTreeItem, createFileItemResponseModelBaseModel, createTextFileItem } from './utils.js'; import { CreateTextFileViewModelBaseModel, @@ -9,6 +9,7 @@ import { PagedFileSystemTreeItemPresentationModel, PagedStylesheetOverviewResponseModel, StylesheetResponseModel, + UpdateStylesheetRequestModel, } from '@umbraco-cms/backoffice/backend-api'; //prettier-ignore @@ -24,7 +25,10 @@ export const data: Array = [ name: 'Stylesheet File 1.css', type: 'stylesheet', hasChildren: false, - content: `h1 { + content: ` + /** Stylesheet 1 */ + + h1 { color: blue; } @@ -50,7 +54,9 @@ h1 { name: 'Stylesheet File 2.css', type: 'stylesheet', hasChildren: false, - content: `h1 { + content: ` + /** Stylesheet 2 */ +h1 { color: green; } @@ -108,7 +114,7 @@ h1 { // TODO: all properties are optional in the server schema. I don't think this is correct. // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore -class UmbStylesheetData extends UmbEntityData { +class UmbStylesheetData extends UmbData { constructor() { super(data); } @@ -231,6 +237,62 @@ ${rule.selector} { this.insert(newItem); return newItem; } + + + insert(item: StylesheetDBItem) { + const exits = this.data.find((i) => i.path === item.path); + + if (exits) { + throw new Error(`Item with path ${item.path} already exists`); + } + + this.data.push(item); + + return item; + } + + updateData(updateItem: UpdateStylesheetRequestModel) { + console.log("update data", updateItem) + const itemIndex = this.data.findIndex((item) => item.path === updateItem.existingPath); + const item = this.data[itemIndex]; + console.log("existing", item) + if (!item) return; + + // TODO: revisit this code, seems like something we can solve smarter/type safer now: + const itemKeys = Object.keys(item); + const newItem = {...item}; + + for (const [key] of Object.entries(updateItem)) { + if (itemKeys.indexOf(key) !== -1) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + newItem[key] = updateItem[key]; + } + } + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + this.data[itemIndex] = newItem; + + + console.log("result", this.data[itemIndex]) + } + + delete(paths: Array) { + const deletedPaths = this.data + .filter((item) => { + if (!item.path) throw new Error('Item has no path'); + paths.includes(item.path); + }) + .map((item) => item.path); + + this.data = this.data.filter((item) => { + if (!item.path) throw new Error('Item has no path'); + paths.indexOf(item.path) === -1; + }); + + return deletedPaths; + } } export const umbStylesheetData = new UmbStylesheetData(); diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts index 28990ca33b..3ae10d1f33 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/stylesheet.handlers.ts @@ -4,6 +4,7 @@ import { CreateTextFileViewModelBaseModel, ExtractRichTextStylesheetRulesRequestModel, InterpolateRichTextStylesheetRequestModel, + UpdateStylesheetRequestModel, } from '@umbraco-cms/backoffice/backend-api'; import { umbracoPath } from '@umbraco-cms/backoffice/utils'; @@ -51,12 +52,13 @@ const detailHandlers = [ const response = umbStylesheetData.delete([path]); return res(ctx.status(200), ctx.json(response)); }), - rest.put(umbracoPath('/stylesheet'), (req, res, ctx) => { - const requestBody = req.json() as CreateTextFileViewModelBaseModel; + rest.put(umbracoPath('/stylesheet'), async (req, res, ctx) => { + const requestBody = await req.json() as UpdateStylesheetRequestModel; if (!requestBody) return res(ctx.status(400, 'no body found')); umbStylesheetData.updateData(requestBody); return res(ctx.status(200)); }), + rest.get(umbracoPath('/v1/stylesheet/all'), (req, res, ctx) => { const path = req.url.searchParams.get('path'); if (!path) return; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts index 404ec695ca..fcea614d8a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts @@ -1,7 +1,6 @@ import { UmbStylesheetWorkspaceContext } from './stylesheet-workspace.context.js'; import { UUIInputElement, UUIInputEvent, UUITextStyles } from '@umbraco-cms/backoffice/external/uui'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import { UMB_MODAL_MANAGER_CONTEXT_TOKEN, UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { Subject, debounceTime } from '@umbraco-cms/backoffice/external/rxjs'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts index 069b4d8846..b91f3fc128 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts @@ -81,11 +81,15 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext ({ ...r, sortOrder: i })) ?? []; this.#rules.next(x); + } else { + this.#rules.next([]); } } @@ -124,8 +128,9 @@ export class UmbStylesheetWorkspaceContext extends UmbWorkspaceContext { - this.#stylesheetWorkspaceContext = workspaceContext as UmbStylesheetWorkspaceContext; + this.consumeContext(UMB_STYLESHEET_WORKSPACE_CONTEXT, (workspaceContext) => { + this.#stylesheetWorkspaceContext = workspaceContext; this.observe(this.#stylesheetWorkspaceContext.content, (content) => { this._content = content; From 29f63ac2acf1ee62a2378e8ecc51ce4afce65417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 6 Sep 2023 12:29:03 +0200 Subject: [PATCH 59/61] code idea --- .../src/mocks/data/stylesheet.data.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts index d202cc391b..331c8ec52a 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts @@ -252,10 +252,8 @@ ${rule.selector} { } updateData(updateItem: UpdateStylesheetRequestModel) { - console.log("update data", updateItem) const itemIndex = this.data.findIndex((item) => item.path === updateItem.existingPath); const item = this.data[itemIndex]; - console.log("existing", item) if (!item) return; // TODO: revisit this code, seems like something we can solve smarter/type safer now: @@ -270,12 +268,12 @@ ${rule.selector} { } } + // Specific to stylesheet, we need to update path based on name: + //newItem.path = updateItem.name; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore this.data[itemIndex] = newItem; - - - console.log("result", this.data[itemIndex]) } delete(paths: Array) { From 1cd34088139cee3a4d0e5aa6f4fc394f591c47cf Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Wed, 6 Sep 2023 13:59:52 +0200 Subject: [PATCH 60/61] fix data saving --- src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts index 331c8ec52a..ee13418aca 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts @@ -267,9 +267,9 @@ ${rule.selector} { newItem[key] = updateItem[key]; } } - // Specific to stylesheet, we need to update path based on name: - //newItem.path = updateItem.name; + const dirName = updateItem.existingPath?.substring(0, updateItem.existingPath.lastIndexOf('/')); + newItem.path = `${dirName}${dirName ? '/' : ''}${updateItem.name}`; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore From cdf4714ba235b2b9d03471b29b862624cff86698 Mon Sep 17 00:00:00 2001 From: Julia Gru <56249914+julczka@users.noreply.github.com> Date: Wed, 6 Sep 2023 14:01:13 +0200 Subject: [PATCH 61/61] Update stylesheet.data.ts --- src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts index ee13418aca..26f845a4b1 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/stylesheet.data.ts @@ -258,7 +258,7 @@ ${rule.selector} { // TODO: revisit this code, seems like something we can solve smarter/type safer now: const itemKeys = Object.keys(item); - const newItem = {...item}; + const newItem = { ...item }; for (const [key] of Object.entries(updateItem)) { if (itemKeys.indexOf(key) !== -1) { @@ -267,7 +267,7 @@ ${rule.selector} { newItem[key] = updateItem[key]; } } - // Specific to stylesheet, we need to update path based on name: + // Specific to fileSystem, we need to update path based on name: const dirName = updateItem.existingPath?.substring(0, updateItem.existingPath.lastIndexOf('/')); newItem.path = `${dirName}${dirName ? '/' : ''}${updateItem.name}`;