Skip to content

Commit b7be95b

Browse files
Add folder workspace icon (#19366)
* add slot for icon * expose icon data * render icon * load type for scaffold * rename * render icon for media * add observable for content type icon * request data in data source * wire up document scaffolding * remove unused * export server data source * render icon for member * rename data source to align with other detail sources * rename data source * remove unused styling * remove console log Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * remove console log Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * remove console log * render workspace icon for document type folders * make folder workspace editor * use element * remove const * use folder-workspace-editor for templating folders * introduce name write guard manager * prevent name change of file system folders * Update script-folder-workspace-editor.element.ts * make guard optional --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 376a2c8 commit b7be95b

File tree

15 files changed

+123
-124
lines changed

15 files changed

+123
-124
lines changed
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
export * from './modal/index.js';
21
export * from './entity-action/index.js';
2+
export * from './modal/index.js';
3+
export * from './workspace/index.js';
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { html, customElement, css } from '@umbraco-cms/backoffice/external/lit';
2+
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
3+
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
4+
5+
@customElement('umb-folder-workspace-editor')
6+
export class UmbFolderWorkspaceEditorElement extends UmbLitElement {
7+
override render() {
8+
return html`<umb-workspace-editor>
9+
<umb-icon id="icon" slot="header" name="icon-folder"></umb-icon>
10+
<umb-workspace-header-name-editable slot="header"></umb-workspace-header-name-editable>
11+
</umb-workspace-editor>`;
12+
}
13+
14+
static override styles = [
15+
UmbTextStyles,
16+
css`
17+
#icon {
18+
display: inline-block;
19+
font-size: var(--uui-size-6);
20+
margin-right: var(--uui-size-space-4);
21+
}
22+
`,
23+
];
24+
}
25+
26+
declare global {
27+
interface HTMLElementTagNameMap {
28+
['umb-folder-workspace-editor']: UmbFolderWorkspaceEditorElement;
29+
}
30+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import './folder-workspace-editor.element.js';
2+
export * from './folder-workspace-editor.element.js';

src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-header-name-editable/workspace-header-name-editable.element.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ export class UmbWorkspaceHeaderNameEditableElement extends UmbLitElement {
3131
@state()
3232
private _name = '';
3333

34+
@state()
35+
private _isWritableName = true;
36+
3437
#workspaceContext?: typeof UMB_NAMABLE_WORKSPACE_CONTEXT.TYPE;
3538

3639
constructor() {
@@ -39,9 +42,20 @@ export class UmbWorkspaceHeaderNameEditableElement extends UmbLitElement {
3942
this.consumeContext(UMB_NAMABLE_WORKSPACE_CONTEXT, (workspaceContext) => {
4043
this.#workspaceContext = workspaceContext;
4144
this.#observeName();
45+
this.#observeNameWriteGuardRules();
4246
});
4347
}
4448

49+
#observeNameWriteGuardRules() {
50+
this.observe(
51+
this.#workspaceContext?.nameWriteGuard?.isPermittedForName(),
52+
(isPermitted) => {
53+
this._isWritableName = isPermitted ?? true;
54+
},
55+
'umbObserveWorkspaceNameWriteGuardRules',
56+
);
57+
}
58+
4559
#observeName() {
4660
if (!this.#workspaceContext) return;
4761
this.observe(
@@ -73,7 +87,7 @@ export class UmbWorkspaceHeaderNameEditableElement extends UmbLitElement {
7387
@input="${this.#onNameInput}"
7488
label=${this.label ?? this.localize.term('placeholders_entername')}
7589
placeholder=${this.placeholder ?? this.localize.term('placeholders_entername')}
76-
?readonly=${this.readonly}
90+
?readonly=${this.readonly || !this._isWritableName}
7791
required
7892
${umbBindToValidation(this, `$.name`, this._name)}
7993
${umbFocus()}></uui-input>`;

src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-named-detail-workspace-base.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import type { UmbNamableWorkspaceContext } from '../types.js';
2+
import { UmbNameWriteGuardManager } from '../namable/index.js';
23
import { UmbEntityDetailWorkspaceContextBase } from './entity-detail-workspace-base.js';
3-
import type { UmbEntityDetailWorkspaceContextCreateArgs } from './types.js';
4+
import type { UmbEntityDetailWorkspaceContextArgs, UmbEntityDetailWorkspaceContextCreateArgs } from './types.js';
45
import type { UmbNamedEntityModel } from '@umbraco-cms/backoffice/entity';
56
import type { UmbDetailRepository } from '@umbraco-cms/backoffice/repository';
7+
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
68

79
export abstract class UmbEntityNamedDetailWorkspaceContextBase<
810
NamedDetailModelType extends UmbNamedEntityModel = UmbNamedEntityModel,
@@ -17,7 +19,14 @@ export abstract class UmbEntityNamedDetailWorkspaceContextBase<
1719
// Just for context token safety:
1820
public readonly IS_ENTITY_NAMED_DETAIL_WORKSPACE_CONTEXT = true;
1921

20-
readonly name = this._data.createObservablePartOfCurrent((data) => data?.name);
22+
public readonly name = this._data.createObservablePartOfCurrent((data) => data?.name);
23+
24+
public readonly nameWriteGuard = new UmbNameWriteGuardManager(this);
25+
26+
constructor(host: UmbControllerHost, args: UmbEntityDetailWorkspaceContextArgs) {
27+
super(host, args);
28+
this.nameWriteGuard.fallbackToPermitted();
29+
}
2130

2231
getName() {
2332
return this._data.getCurrent()?.name;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from './namable-workspace.context-token.js';
2+
export * from './name-write-guard.manager.js';
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import type { UmbWorkspaceContext } from '../workspace-context.interface.js';
2+
import type { UmbNameWriteGuardManager } from './name-write-guard.manager.js';
23
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
34

45
export interface UmbNamableWorkspaceContext extends UmbWorkspaceContext {
56
name: Observable<string | undefined>;
67
getName(): string | undefined;
78
setName(name: string): void;
9+
// TODO: implement across all namable workspaces and make it mandatory
10+
nameWriteGuard?: UmbNameWriteGuardManager;
811
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
2+
import { UmbGuardManagerBase, type UmbGuardRule } from '@umbraco-cms/backoffice/utils';
3+
4+
export class UmbNameWriteGuardManager extends UmbGuardManagerBase {
5+
public isPermittedForName(): Observable<boolean> {
6+
return this._rules.asObservablePart((rules) => this.#resolvePermission(rules));
7+
}
8+
9+
#resolvePermission(rules: Array<UmbGuardRule>): boolean {
10+
if (rules.some((rule) => rule.permitted === false)) {
11+
return false;
12+
}
13+
14+
if (rules.some((rule) => rule.permitted === true)) {
15+
return true;
16+
}
17+
18+
return this._fallback;
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,17 @@
11
import { html, customElement } from '@umbraco-cms/backoffice/external/lit';
22
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
3-
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
43

5-
const elementName = 'umb-data-type-folder-workspace-editor';
6-
@customElement(elementName)
4+
@customElement('umb-data-type-folder-workspace-editor')
75
export class UmbDataTypeFolderWorkspaceEditorElement extends UmbLitElement {
86
override render() {
9-
return html`<umb-workspace-editor>
10-
<umb-workspace-header-name-editable slot="header"></umb-workspace-header-name-editable>
11-
</umb-workspace-editor>`;
7+
return html`<umb-folder-workspace-editor></umb-folder-workspace-editor>`;
128
}
13-
14-
static override styles = [UmbTextStyles];
159
}
1610

1711
export { UmbDataTypeFolderWorkspaceEditorElement as element };
1812

1913
declare global {
2014
interface HTMLElementTagNameMap {
21-
[elementName]: UmbDataTypeFolderWorkspaceEditorElement;
15+
['umb-data-type-folder-workspace-editor']: UmbDataTypeFolderWorkspaceEditorElement;
2216
}
2317
}
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,17 @@
11
import { html, customElement } from '@umbraco-cms/backoffice/external/lit';
22
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
3-
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
43

5-
const elementName = 'umb-document-blueprint-folder-workspace-editor';
6-
@customElement(elementName)
4+
@customElement('umb-document-blueprint-folder-workspace-editor')
75
export class UmbDocumentBlueprintFolderWorkspaceEditorElement extends UmbLitElement {
86
override render() {
9-
return html`<umb-workspace-editor>
10-
<umb-workspace-header-name-editable slot="header"></umb-workspace-header-name-editable>
11-
</umb-workspace-editor>`;
7+
return html`<umb-folder-workspace-editor> </umb-folder-workspace-editor>`;
128
}
13-
14-
static override styles = [UmbTextStyles];
159
}
1610

1711
export { UmbDocumentBlueprintFolderWorkspaceEditorElement as element };
1812

1913
declare global {
2014
interface HTMLElementTagNameMap {
21-
[elementName]: UmbDocumentBlueprintFolderWorkspaceEditorElement;
15+
['umb-document-blueprint-folder-workspace-editor']: UmbDocumentBlueprintFolderWorkspaceEditorElement;
2216
}
2317
}
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,17 @@
11
import { html, customElement } from '@umbraco-cms/backoffice/external/lit';
22
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
3-
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
43

5-
const elementName = 'umb-document-type-folder-workspace-editor';
6-
@customElement(elementName)
4+
@customElement('umb-document-type-folder-workspace-editor')
75
export class UmbDocumentTypeFolderWorkspaceEditorElement extends UmbLitElement {
86
override render() {
9-
return html`<umb-workspace-editor>
10-
<umb-workspace-header-name-editable slot="header"></umb-workspace-header-name-editable>
11-
</umb-workspace-editor>`;
7+
return html`<umb-folder-workspace-editor></umb-folder-workspace-editor>`;
128
}
13-
14-
static override styles = [UmbTextStyles];
159
}
1610

1711
export { UmbDocumentTypeFolderWorkspaceEditorElement as element };
1812

1913
declare global {
2014
interface HTMLElementTagNameMap {
21-
[elementName]: UmbDocumentTypeFolderWorkspaceEditorElement;
15+
['umb-document-type-folder-workspace-editor']: UmbDocumentTypeFolderWorkspaceEditorElement;
2216
}
2317
}
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,17 @@
11
import { html, customElement } from '@umbraco-cms/backoffice/external/lit';
22
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
3-
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
43

5-
const elementName = 'umb-media-type-folder-workspace-editor';
6-
@customElement(elementName)
4+
@customElement('umb-media-type-folder-workspace-editor')
75
export class UmbMediaTypeFolderWorkspaceEditorElement extends UmbLitElement {
86
override render() {
9-
return html`<umb-workspace-editor>
10-
<umb-workspace-header-name-editable slot="header"></umb-workspace-header-name-editable>
11-
</umb-workspace-editor>`;
7+
return html`<umb-folder-workspace-editor></umb-folder-workspace-editor>`;
128
}
13-
14-
static override styles = [UmbTextStyles];
159
}
1610

1711
export { UmbMediaTypeFolderWorkspaceEditorElement as element };
1812

1913
declare global {
2014
interface HTMLElementTagNameMap {
21-
[elementName]: UmbMediaTypeFolderWorkspaceEditorElement;
15+
['umb-media-type-folder-workspace-editor']: UmbMediaTypeFolderWorkspaceEditorElement;
2216
}
2317
}
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,30 @@
11
import { UMB_PARTIAL_VIEW_FOLDER_WORKSPACE_CONTEXT } from './partial-view-folder-workspace.context-token.js';
2-
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
2+
import { html, customElement } from '@umbraco-cms/backoffice/external/lit';
33
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
4-
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
54

6-
const elementName = 'umb-partial-view-folder-workspace-editor';
7-
@customElement(elementName)
5+
@customElement('umb-partial-view-folder-workspace-editor')
86
export class UmbPartialViewFolderWorkspaceEditorElement extends UmbLitElement {
9-
@state()
10-
private _name = '';
11-
12-
#workspaceContext?: typeof UMB_PARTIAL_VIEW_FOLDER_WORKSPACE_CONTEXT.TYPE;
13-
147
constructor() {
158
super();
169

1710
this.consumeContext(UMB_PARTIAL_VIEW_FOLDER_WORKSPACE_CONTEXT, (workspaceContext) => {
18-
this.#workspaceContext = workspaceContext;
19-
this.#observeName();
11+
workspaceContext?.nameWriteGuard.addRule({
12+
unique: 'UMB_SERVER_PREVENT_FILE_SYSTEM_FOLDER_RENAME',
13+
permitted: false,
14+
message: 'It is not possible to change the name of a Partial View folder.',
15+
});
2016
});
2117
}
2218

23-
#observeName() {
24-
if (!this.#workspaceContext) return;
25-
this.observe(
26-
this.#workspaceContext.name,
27-
(name) => {
28-
if (name !== this._name) {
29-
this._name = name ?? '';
30-
}
31-
},
32-
'observeName',
33-
);
34-
}
35-
3619
override render() {
37-
return html`<umb-workspace-editor headline=${this._name}> </umb-workspace-editor>`;
20+
return html`<umb-folder-workspace-editor></umb-folder-workspace-editor>`;
3821
}
39-
40-
static override styles = [UmbTextStyles, css``];
4122
}
4223

4324
export { UmbPartialViewFolderWorkspaceEditorElement as element };
4425

4526
declare global {
4627
interface HTMLElementTagNameMap {
47-
[elementName]: UmbPartialViewFolderWorkspaceEditorElement;
28+
['umb-partial-view-folder-workspace-editor']: UmbPartialViewFolderWorkspaceEditorElement;
4829
}
4930
}
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,30 @@
11
import { UMB_SCRIPT_FOLDER_WORKSPACE_CONTEXT } from './script-folder-workspace.context-token.js';
2-
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
2+
import { html, customElement } from '@umbraco-cms/backoffice/external/lit';
33
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
4-
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
54

6-
const elementName = 'umb-script-folder-workspace-editor';
7-
@customElement(elementName)
5+
@customElement('umb-script-folder-workspace-editor')
86
export class UmbScriptFolderWorkspaceEditorElement extends UmbLitElement {
9-
@state()
10-
private _name = '';
11-
12-
#workspaceContext?: typeof UMB_SCRIPT_FOLDER_WORKSPACE_CONTEXT.TYPE;
13-
147
constructor() {
158
super();
169

1710
this.consumeContext(UMB_SCRIPT_FOLDER_WORKSPACE_CONTEXT, (workspaceContext) => {
18-
this.#workspaceContext = workspaceContext;
19-
this.#observeName();
11+
workspaceContext?.nameWriteGuard.addRule({
12+
unique: 'UMB_SERVER_PREVENT_FILE_SYSTEM_FOLDER_RENAME',
13+
permitted: false,
14+
message: 'It is not possible to change the name of a script folder.',
15+
});
2016
});
2117
}
2218

23-
#observeName() {
24-
if (!this.#workspaceContext) return;
25-
this.observe(
26-
this.#workspaceContext.name,
27-
(name) => {
28-
if (name !== this._name) {
29-
this._name = name ?? '';
30-
}
31-
},
32-
'observeName',
33-
);
34-
}
35-
3619
override render() {
37-
return html`<umb-workspace-editor headline=${this._name}> </umb-workspace-editor>`;
20+
return html`<umb-folder-workspace-editor></umb-folder-workspace-editor>`;
3821
}
39-
40-
static override styles = [UmbTextStyles, css``];
4122
}
4223

4324
export { UmbScriptFolderWorkspaceEditorElement as element };
4425

4526
declare global {
4627
interface HTMLElementTagNameMap {
47-
[elementName]: UmbScriptFolderWorkspaceEditorElement;
28+
['umb-script-folder-workspace-editor']: UmbScriptFolderWorkspaceEditorElement;
4829
}
4930
}

0 commit comments

Comments
 (0)