Skip to content

Commit 8be39e7

Browse files
leekelleheriOvergaard
authored andcommitted
Refactored "Save and Preview" button
to extend `UmbWorkspaceActionElement`. This did mean exposing certain methods/properties to be overridable.
1 parent 32b7c89 commit 8be39e7

File tree

2 files changed

+49
-166
lines changed

2 files changed

+49
-166
lines changed

src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-action/default/workspace-action.element.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type {
22
ManifestWorkspaceAction,
33
ManifestWorkspaceActionMenuItem,
44
MetaWorkspaceActionDefaultKind,
5+
UmbWorkspaceActionArgs,
56
UmbWorkspaceActionDefaultKind,
67
} from '../../../types.js';
78
import { customElement, html, property, state, when } from '@umbraco-cms/backoffice/external/lit';
@@ -10,6 +11,7 @@ import { UmbActionExecutedEvent } from '@umbraco-cms/backoffice/event';
1011
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
1112
import { UmbExtensionsElementAndApiInitializer } from '@umbraco-cms/backoffice/extension-api';
1213
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
14+
import type { UmbAction } from '@umbraco-cms/backoffice/action';
1315
import type { UmbExtensionElementAndApiInitializer } from '@umbraco-cms/backoffice/extension-api';
1416
import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui';
1517

@@ -20,7 +22,7 @@ export class UmbWorkspaceActionElement<
2022
> extends UmbLitElement {
2123
#manifest?: ManifestWorkspaceAction<MetaType>;
2224
#api?: ApiType;
23-
#extensionsController?: UmbExtensionsElementAndApiInitializer<
25+
protected _extensionsController?: UmbExtensionsElementAndApiInitializer<
2426
ManifestWorkspaceActionMenuItem,
2527
'workspaceActionMenuItem',
2628
ManifestWorkspaceActionMenuItem
@@ -59,6 +61,10 @@ export class UmbWorkspaceActionElement<
5961
return this.#api;
6062
}
6163

64+
protected _actionApi?: UmbAction<UmbWorkspaceActionArgs<MetaType>>;
65+
66+
protected _buttonLabel?: string;
67+
6268
@state()
6369
private _buttonState?: UUIButtonState;
6470

@@ -72,7 +78,7 @@ export class UmbWorkspaceActionElement<
7278
private _isDisabled = false;
7379

7480
@state()
75-
private _items: Array<UmbExtensionElementAndApiInitializer<ManifestWorkspaceActionMenuItem>> = [];
81+
protected _items: Array<UmbExtensionElementAndApiInitializer<ManifestWorkspaceActionMenuItem>> = [];
7682

7783
#buttonStateResetTimeoutId: number | null = null;
7884

@@ -97,7 +103,7 @@ export class UmbWorkspaceActionElement<
97103
}
98104
}
99105

100-
this.#observeExtensions(Array.from(aliases));
106+
this.observeExtensions(Array.from(aliases));
101107
}
102108

103109
async #onClick(event: MouseEvent) {
@@ -111,8 +117,9 @@ export class UmbWorkspaceActionElement<
111117
}
112118

113119
try {
114-
if (!this.#api) throw new Error('No api defined');
115-
await this.#api.execute();
120+
const api = this._actionApi ?? this.#api;
121+
if (!api) throw new Error('No api defined');
122+
await api.execute();
116123
this._buttonState = 'success';
117124
this.#initButtonStateReset();
118125
} catch (reason) {
@@ -153,9 +160,9 @@ export class UmbWorkspaceActionElement<
153160
}
154161
}
155162

156-
#observeExtensions(aliases: string[]): void {
157-
this.#extensionsController?.destroy();
158-
this.#extensionsController = new UmbExtensionsElementAndApiInitializer<
163+
protected observeExtensions(aliases: string[]): void {
164+
this._extensionsController?.destroy();
165+
this._extensionsController = new UmbExtensionsElementAndApiInitializer<
159166
ManifestWorkspaceActionMenuItem,
160167
'workspaceActionMenuItem',
161168
ManifestWorkspaceActionMenuItem
@@ -165,17 +172,15 @@ export class UmbWorkspaceActionElement<
165172
'workspaceActionMenuItem',
166173
(manifest) => [{ meta: manifest.meta }],
167174
(action) => stringOrStringArrayIntersects(action.forWorkspaceActions, aliases),
168-
(extensionControllers) => {
169-
this._items = extensionControllers;
175+
(actions) => {
176+
this._items = actions;
170177
},
171178
undefined, // We can leave the alias to undefined, as we destroy this our selfs.
172179
);
173180
}
174181

175182
#renderButton() {
176-
const label = this.#manifest?.meta.label
177-
? this.localize.string(this.#manifest.meta.label)
178-
: (this.#manifest?.name ?? '');
183+
const label = this.localize.string(this._buttonLabel || this.#manifest?.meta.label || this.#manifest?.name || '');
179184
return html`
180185
<uui-button
181186
data-mark="workspace-action:${this.#manifest?.alias}"

src/Umbraco.Web.UI.Client/src/packages/documents/documents/preview/workspace-action/save-and-preview-workspace-action.element.ts

Lines changed: 31 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,163 +1,41 @@
1-
import type { ManifestPreviewOption, MetaPreviewOption } from '../preview-option/preview-option.extension.js';
2-
import type { UmbPreviewOptionActionBase } from '../preview-option/preview-option-action-base.controller.js';
3-
import { customElement, html, property, state, when } from '@umbraco-cms/backoffice/external/lit';
4-
import { UmbActionExecutedEvent } from '@umbraco-cms/backoffice/event';
5-
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
1+
import { customElement } from '@umbraco-cms/backoffice/external/lit';
62
import { createExtensionApi, UmbExtensionsElementAndApiInitializer } from '@umbraco-cms/backoffice/extension-api';
7-
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
8-
import type { UmbWorkspaceAction } from '@umbraco-cms/backoffice/workspace';
9-
import type { UmbExtensionElementAndApiInitializer } from '@umbraco-cms/backoffice/extension-api';
10-
import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui';
3+
import { stringOrStringArrayIntersects } from '@umbraco-cms/backoffice/utils';
4+
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
5+
import { UmbWorkspaceActionElement } from '@umbraco-cms/backoffice/workspace';
6+
import type { ManifestWorkspaceActionMenuItem } from '@umbraco-cms/backoffice/workspace';
117

128
@customElement('umb-save-and-preview-workspace-action')
13-
export class UmbSaveAndPreviewWorkspaceActionElement extends UmbLitElement {
14-
#buttonStateResetTimeoutId: number | null = null;
15-
16-
#extensionsController?: UmbExtensionsElementAndApiInitializer<
17-
ManifestPreviewOption,
18-
'previewOption',
19-
ManifestPreviewOption
20-
>;
21-
22-
@property({ type: Object, attribute: false })
23-
public set manifest(value: ManifestPreviewOption | undefined) {
24-
if (!value) return;
25-
const oldValue = this.#manifest;
26-
if (oldValue !== value) {
27-
this.#manifest = value;
28-
this.#observeExtensions();
29-
}
30-
}
31-
public get manifest() {
32-
return this.#manifest;
33-
}
34-
#manifest?: ManifestPreviewOption;
35-
36-
@property({ attribute: false })
37-
public set api(api: UmbWorkspaceAction | undefined) {
38-
this.#api = api;
39-
this.#observeIsDisabled();
40-
}
41-
public get api(): UmbWorkspaceAction | undefined {
42-
return this.#api;
43-
}
44-
#api?: UmbWorkspaceAction;
45-
46-
@state()
47-
private _buttonState?: UUIButtonState;
48-
49-
@state()
50-
private _isDisabled = false;
51-
52-
@state()
53-
private _actions: Array<UmbExtensionElementAndApiInitializer<ManifestPreviewOption>> = [];
54-
55-
@state()
56-
private _firstActionManifest?: ManifestPreviewOption;
57-
58-
@state()
59-
private _firstActionApi?: UmbPreviewOptionActionBase<MetaPreviewOption>;
60-
61-
async #onClick() {
62-
this._buttonState = 'waiting';
63-
64-
try {
65-
if (!this._firstActionApi) throw new Error('No api defined');
66-
await this._firstActionApi.execute().catch(() => {});
67-
this._buttonState = 'success';
68-
} catch (reason) {
69-
if (reason) {
70-
console.warn(reason);
71-
}
72-
this._buttonState = 'failed';
73-
}
74-
75-
this.#initButtonStateReset();
76-
this.dispatchEvent(new UmbActionExecutedEvent());
77-
}
78-
79-
#observeIsDisabled() {
80-
this.observe(
81-
this.#api?.isDisabled,
82-
(isDisabled) => {
83-
this._isDisabled = isDisabled || false;
84-
},
85-
'isDisabledObserver',
86-
);
87-
}
88-
89-
#initButtonStateReset() {
90-
this.#clearButtonStateResetTimeout();
91-
this.#buttonStateResetTimeoutId = window.setTimeout(() => {
92-
this._buttonState = undefined;
93-
}, 2000);
94-
}
95-
96-
#clearButtonStateResetTimeout() {
97-
if (this.#buttonStateResetTimeoutId !== null) {
98-
clearTimeout(this.#buttonStateResetTimeoutId);
99-
this.#buttonStateResetTimeoutId = null;
100-
}
101-
}
102-
103-
#observeExtensions(): void {
104-
this.#extensionsController?.destroy();
105-
this.#extensionsController = new UmbExtensionsElementAndApiInitializer<
106-
ManifestPreviewOption,
107-
'previewOption',
108-
ManifestPreviewOption
109-
>(this, umbExtensionsRegistry, 'previewOption', [], undefined, async (actions) => {
110-
const firstAction = actions.shift();
111-
112-
if (firstAction) {
113-
this._firstActionManifest = firstAction.manifest;
114-
this._firstActionApi = await createExtensionApi(this, firstAction.manifest, []);
115-
if (this._firstActionApi) {
116-
(this._firstActionApi as any).manifest = this._firstActionManifest;
9+
export class UmbSaveAndPreviewWorkspaceActionElement extends UmbWorkspaceActionElement {
10+
override observeExtensions(aliases: string[]) {
11+
this._extensionsController?.destroy();
12+
this._extensionsController = new UmbExtensionsElementAndApiInitializer<
13+
ManifestWorkspaceActionMenuItem,
14+
'workspaceActionMenuItem',
15+
ManifestWorkspaceActionMenuItem
16+
>(
17+
this,
18+
umbExtensionsRegistry,
19+
'workspaceActionMenuItem',
20+
(manifest) => [{ meta: manifest.meta }],
21+
(action) => stringOrStringArrayIntersects(action.forWorkspaceActions, aliases),
22+
async (actions) => {
23+
const firstAction = actions.shift();
24+
25+
if (firstAction) {
26+
this._buttonLabel = (firstAction.manifest.meta as any).label;
27+
const api = await createExtensionApi(this, firstAction.manifest, []);
28+
if (api) {
29+
(api as any).manifest = firstAction.manifest;
30+
this._actionApi = api;
31+
}
11732
}
118-
}
11933

120-
this._actions = actions;
121-
});
122-
}
123-
124-
#renderButton() {
125-
const label = this._firstActionManifest?.meta.label || this.#manifest?.meta.label || this.#manifest?.name;
126-
return html`
127-
<uui-button
128-
data-mark="workspace-action:${this.#manifest?.alias}"
129-
color=${this.#manifest?.meta.color ?? 'default'}
130-
look=${this.#manifest?.meta.look ?? 'default'}
131-
label=${this.localize.string(label)}
132-
.disabled=${this._isDisabled}
133-
.state=${this._buttonState}
134-
@click=${this.#onClick}></uui-button>
135-
`;
136-
}
137-
138-
#renderActionMenu() {
139-
// TODO: [LK] FIXME: The `any` type casting here needs to be resolved with a proper type.
140-
return html`
141-
<umb-workspace-action-menu
142-
color=${this.#manifest?.meta.color ?? 'default'}
143-
look=${this.#manifest?.meta.look ?? 'default'}
144-
.items=${this._actions as any}></umb-workspace-action-menu>
145-
`;
146-
}
147-
148-
override render() {
149-
if (!this._firstActionManifest || !this._actions.length) return;
150-
return when(
151-
this._actions.length,
152-
() => html`<uui-button-group>${this.#renderButton()}${this.#renderActionMenu()}</uui-button-group>`,
153-
() => this.#renderButton(),
34+
this._items = actions;
35+
},
36+
undefined, // We can leave the alias to undefined, as we destroy this our selfs.
15437
);
15538
}
156-
157-
override disconnectedCallback() {
158-
super.disconnectedCallback();
159-
this.#clearButtonStateResetTimeout();
160-
}
16139
}
16240

16341
export default UmbSaveAndPreviewWorkspaceActionElement;

0 commit comments

Comments
 (0)