Skip to content
This repository was archived by the owner on Nov 6, 2025. It is now read-only.

Commit 5ad8fe3

Browse files
authored
Feature: Document Workspace Info Link State (#2497)
Adds document link state to the workspace info links component.
1 parent bef2d31 commit 5ad8fe3

File tree

1 file changed

+100
-56
lines changed

1 file changed

+100
-56
lines changed

src/packages/documents/documents/workspace/views/info/document-workspace-view-info-links.element.ts

Lines changed: 100 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
11
import { UmbDocumentUrlRepository } from '../../../repository/url/document-url.repository.js';
22
import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../document-workspace.context-token.js';
3-
import type { UmbDocumentUrlModel } from '../../../repository/url/types.js';
4-
import { css, customElement, html, nothing, repeat, state, when } from '@umbraco-cms/backoffice/external/lit';
3+
import type { UmbDocumentVariantOptionModel } from '../../../types.js';
4+
import { css, customElement, html, map, nothing, state, when } from '@umbraco-cms/backoffice/external/lit';
55
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
66
import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/entity-action';
7-
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
87
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
8+
import { observeMultiple } from '@umbraco-cms/backoffice/observable-api';
9+
import { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/backend-api';
910

1011
@customElement('umb-document-workspace-view-info-links')
1112
export class UmbDocumentWorkspaceViewInfoLinksElement extends UmbLitElement {
1213
#documentUrlRepository = new UmbDocumentUrlRepository(this);
1314

14-
#workspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE;
15+
@state()
16+
private _isNew = false;
17+
18+
@state()
19+
private _unique?: string;
1520

1621
@state()
17-
private _invariantCulture = 'en-US';
22+
private _variantOptions?: Array<UmbDocumentVariantOptionModel>;
1823

1924
@state()
20-
private _items?: Array<UmbDocumentUrlModel>;
25+
private _lookup: Record<string, string> = {};
2126

2227
constructor() {
2328
super();
@@ -29,96 +34,135 @@ export class UmbDocumentWorkspaceViewInfoLinksElement extends UmbLitElement {
2934
});
3035

3136
this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (context) => {
32-
this.#workspaceContext = context;
33-
this.#requestUrls();
37+
this.observe(
38+
observeMultiple([context.isNew, context.unique, context.variantOptions]),
39+
([isNew, unique, variantOptions]) => {
40+
this._isNew = isNew === true;
41+
this._unique = unique;
42+
this._variantOptions = variantOptions;
43+
this.#requestUrls();
44+
},
45+
);
3446
});
3547
}
3648

3749
async #requestUrls() {
38-
const unique = this.#workspaceContext?.getUnique();
39-
if (!unique) throw new Error('Document unique is required');
50+
if (this._isNew) return;
51+
52+
if (!this._unique) throw new Error('Document unique is required');
4053

41-
const { data } = await this.#documentUrlRepository.requestItems([unique]);
54+
const { data } = await this.#documentUrlRepository.requestItems([this._unique]);
4255

4356
if (data?.length) {
44-
this._items = data[0].urls;
57+
data[0].urls.forEach((item) => {
58+
if (item.culture && item.url) {
59+
this._lookup[item.culture] = item.url;
60+
}
61+
});
62+
this.requestUpdate('_lookup');
4563
}
4664
}
4765

48-
override render() {
49-
return html`
50-
<uui-box headline=${this.localize.term('general_links')} style="--uui-box-default-padding: 0;">
51-
<div id="link-section">
52-
${when(
53-
this._items?.length,
54-
() => this.#renderUrls(),
55-
() => this.#renderUnpublished(),
56-
)}
57-
</div>
58-
</uui-box>
59-
`;
66+
#getStateLocalizationKey(variantOption: UmbDocumentVariantOptionModel) {
67+
switch (variantOption.variant?.state) {
68+
case null:
69+
case undefined:
70+
case DocumentVariantStateModel.NOT_CREATED:
71+
return 'content_notCreated';
72+
case DocumentVariantStateModel.DRAFT:
73+
return 'content_itemNotPublished';
74+
case DocumentVariantStateModel.PUBLISHED:
75+
return 'content_routeErrorCannotRoute';
76+
default:
77+
return 'content_parentNotPublishedAnomaly';
78+
}
6079
}
6180

62-
#renderUrls() {
63-
if (!this._items) return nothing;
81+
override render() {
6482
return html`
65-
${repeat(
66-
this._items!,
67-
(item) => item.culture,
68-
(item) => html`
69-
<a href=${item.url ?? '#'} target="_blank" class="link-item">
70-
<span class="culture">${item.culture}</span>
71-
<span class="url">${item.url}</span>
72-
<uui-icon name="icon-out"></uui-icon>
73-
</a>
74-
`,
75-
)}
83+
<uui-box headline=${this.localize.term('general_links')}>
84+
${when(
85+
this._isNew,
86+
() => this.#renderNotCreated(),
87+
() => this.#renderUrls(),
88+
)}
89+
</uui-box>
7690
`;
7791
}
7892

79-
#renderUnpublished() {
93+
#renderNotCreated() {
8094
return html`
8195
<div class="link-item">
82-
<span class="culture">${this._invariantCulture}</span>
83-
<span class="url">
84-
<em><umb-localize key="content_parentNotPublishedAnomaly"></umb-localize></em>
96+
<span>
97+
<em><umb-localize key="content_notCreated"></umb-localize></em>
8598
</span>
8699
</div>
87100
`;
88101
}
89102

103+
#renderUrls() {
104+
if (!this._variantOptions?.length) return nothing;
105+
return map(this._variantOptions, (variantOption) => this.#renderUrl(variantOption));
106+
}
107+
108+
#renderUrl(variantOption: UmbDocumentVariantOptionModel) {
109+
const varies = !!variantOption.culture;
110+
const culture = varies ? variantOption.culture! : variantOption.language.unique;
111+
const url = this._lookup[culture];
112+
return when(
113+
url,
114+
() => html`
115+
<a class="link-item" href=${url} target="_blank">
116+
<span>
117+
<span class="culture">${varies ? culture : nothing}</span>
118+
<span>${url}</span>
119+
</span>
120+
<uui-icon name="icon-out"></uui-icon>
121+
</a>
122+
`,
123+
() => html`
124+
<div class="link-item">
125+
<span>
126+
${when(varies, () => html`<span class="culture">${culture}</span>`)}
127+
<em><umb-localize key=${this.#getStateLocalizationKey(variantOption)}></umb-localize></em>
128+
</span>
129+
</div>
130+
`,
131+
);
132+
}
133+
90134
static override styles = [
91-
UmbTextStyles,
92135
css`
93-
#link-section {
94-
display: flex;
95-
flex-direction: column;
96-
text-align: left;
136+
uui-box {
137+
--uui-box-default-padding: 0;
97138
}
98139
99140
.link-item {
100-
padding: var(--uui-size-space-4) var(--uui-size-space-6);
101-
display: grid;
102-
grid-template-columns: auto 1fr auto;
141+
display: flex;
142+
justify-content: space-between;
143+
align-items: center;
103144
gap: var(--uui-size-6);
104-
color: inherit;
105-
text-decoration: none;
145+
146+
padding: var(--uui-size-space-4) var(--uui-size-space-6);
106147
107148
&:is(a) {
108149
cursor: pointer;
150+
color: inherit;
151+
text-decoration: none;
109152
}
110153
111154
&:is(a):hover {
112155
background: var(--uui-color-divider);
113156
}
114157
115-
.culture {
116-
color: var(--uui-color-divider-emphasis);
158+
& > span {
159+
display: flex;
160+
align-items: center;
161+
gap: var(--uui-size-6);
117162
}
118163
119-
uui-icon {
120-
margin-right: var(--uui-size-space-2);
121-
vertical-align: middle;
164+
.culture {
165+
color: var(--uui-color-divider-emphasis);
122166
}
123167
}
124168
`,

0 commit comments

Comments
 (0)