@umbraco-cms/backoffice 18.2.1 → 18.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cms/packages/core/backend-api/types.gen.d.ts +2 -0
- package/dist-cms/packages/media/imaging/components/media-thumbnail.element.d.ts +1 -0
- package/dist-cms/packages/media/imaging/components/media-thumbnail.element.js +29 -4
- package/dist-cms/packages/media/imaging/imaging.server.data.js +2 -1
- package/dist-cms/packages/media/imaging/types.d.ts +5 -0
- package/dist-cms/packages/media/imaging/types.js +1 -1
- package/dist-cms/packages/media/media/url/info-app/media-link.function.d.ts +14 -0
- package/dist-cms/packages/media/media/url/info-app/media-link.function.js +33 -0
- package/dist-cms/packages/media/media/url/info-app/media-links-workspace-info-app.element.js +18 -12
- package/dist-cms/packages/media/media/url/repository/media-url.server.data-source.d.ts +1 -5
- package/dist-cms/packages/media/media/url/repository/media-url.server.data-source.js +10 -1
- package/dist-cms/packages/multi-url-picker/components/input-multi-url/input-multi-url.element.js +1 -1
- package/dist-cms/packages/preview/context/preview.context.js +15 -1
- package/dist-cms/packages/preview/controllers/preview-session-renewal.controller.d.ts +35 -0
- package/dist-cms/packages/preview/controllers/preview-session-renewal.controller.js +49 -0
- package/dist-cms/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -8929,6 +8929,7 @@ export type GetImagingResizeUrlsData = {
|
|
|
8929
8929
|
path?: never;
|
|
8930
8930
|
query?: {
|
|
8931
8931
|
id?: Array<string>;
|
|
8932
|
+
dataTypeId?: string;
|
|
8932
8933
|
height?: number;
|
|
8933
8934
|
width?: number;
|
|
8934
8935
|
mode?: ImageCropModeModel;
|
|
@@ -10215,6 +10216,7 @@ export type GetMediaUrlsData = {
|
|
|
10215
10216
|
path?: never;
|
|
10216
10217
|
query?: {
|
|
10217
10218
|
id?: Array<string>;
|
|
10219
|
+
dataTypeId?: string;
|
|
10218
10220
|
};
|
|
10219
10221
|
url: '/umbraco/management/api/v1/media/urls';
|
|
10220
10222
|
};
|
|
@@ -56,6 +56,7 @@ export declare class UmbMediaThumbnailElement extends UmbLitElement {
|
|
|
56
56
|
externalLoading: boolean;
|
|
57
57
|
private _isLoading;
|
|
58
58
|
private _thumbnailUrl;
|
|
59
|
+
constructor();
|
|
59
60
|
render(): import("lit-html").TemplateResult<1>;
|
|
60
61
|
connectedCallback(): void;
|
|
61
62
|
disconnectedCallback(): void;
|
|
@@ -11,6 +11,7 @@ import { UmbLitElement } from '../../../core/lit-element/index.js';
|
|
|
11
11
|
import { UmbTextStyles } from '../../../core/style/index.js';
|
|
12
12
|
import { UMB_ACTION_EVENT_CONTEXT } from '../../../core/action/index.js';
|
|
13
13
|
import { UmbEntityUpdatedEvent } from '../../../core/entity-action/index.js';
|
|
14
|
+
import { UMB_PROPERTY_TYPE_BASED_PROPERTY_CONTEXT } from '../../../content/content/index.js';
|
|
14
15
|
/**
|
|
15
16
|
* Displays a thumbnail for a media item, with optional server-side cropping and transparency support.
|
|
16
17
|
* This is the recommended component for rendering media images in the backoffice.
|
|
@@ -20,8 +21,14 @@ import { UmbEntityUpdatedEvent } from '../../../core/entity-action/index.js';
|
|
|
20
21
|
* @csspart img - The underlying `<img>` element.
|
|
21
22
|
*/
|
|
22
23
|
let UmbMediaThumbnailElement = class UmbMediaThumbnailElement extends UmbLitElement {
|
|
24
|
+
#imagingRepository;
|
|
25
|
+
#intersectionObserver;
|
|
26
|
+
#actionEventContext;
|
|
27
|
+
#dataTypeUnique;
|
|
28
|
+
#hasRequestedThumbnail;
|
|
29
|
+
#latestRequest;
|
|
23
30
|
constructor() {
|
|
24
|
-
super(
|
|
31
|
+
super();
|
|
25
32
|
/**
|
|
26
33
|
* The width of the thumbnail in pixels.
|
|
27
34
|
* @default 300
|
|
@@ -59,15 +66,27 @@ let UmbMediaThumbnailElement = class UmbMediaThumbnailElement extends UmbLitElem
|
|
|
59
66
|
this._isLoading = false;
|
|
60
67
|
this._thumbnailUrl = '';
|
|
61
68
|
this.#imagingRepository = new UmbImagingRepository(this);
|
|
69
|
+
this.#hasRequestedThumbnail = false;
|
|
70
|
+
this.#latestRequest = 0;
|
|
62
71
|
this.#onEntityUpdated = (event) => {
|
|
63
72
|
if (event.getUnique() === this.unique) {
|
|
64
73
|
this.#generateThumbnailUrl();
|
|
65
74
|
}
|
|
66
75
|
};
|
|
76
|
+
// A picker configured to ignore user start nodes may reference media outside them,
|
|
77
|
+
// which the server only resolves when told which data type the request originates from.
|
|
78
|
+
this.consumeContext(UMB_PROPERTY_TYPE_BASED_PROPERTY_CONTEXT, (context) => {
|
|
79
|
+
this.observe(context?.dataType, (dataType) => {
|
|
80
|
+
// The context is also lost when the element disconnects, which needs no new request.
|
|
81
|
+
if (!dataType?.unique)
|
|
82
|
+
return;
|
|
83
|
+
this.#dataTypeUnique = dataType.unique;
|
|
84
|
+
if (this.#hasRequestedThumbnail) {
|
|
85
|
+
this.#generateThumbnailUrl();
|
|
86
|
+
}
|
|
87
|
+
}, '_observeDataType');
|
|
88
|
+
});
|
|
67
89
|
}
|
|
68
|
-
#imagingRepository;
|
|
69
|
-
#intersectionObserver;
|
|
70
|
-
#actionEventContext;
|
|
71
90
|
render() {
|
|
72
91
|
return when(this.externalLoading || this._isLoading, () => this.#renderLoading(), () => this.#renderThumbnail());
|
|
73
92
|
}
|
|
@@ -126,12 +145,18 @@ let UmbMediaThumbnailElement = class UmbMediaThumbnailElement extends UmbLitElem
|
|
|
126
145
|
if (!this.unique)
|
|
127
146
|
return;
|
|
128
147
|
this._isLoading = true;
|
|
148
|
+
this.#hasRequestedThumbnail = true;
|
|
149
|
+
const request = ++this.#latestRequest;
|
|
129
150
|
const { data } = await this.#imagingRepository.requestResizedItems([this.unique], {
|
|
130
151
|
height: this.height,
|
|
131
152
|
width: this.width,
|
|
132
153
|
mode: this.mode,
|
|
133
154
|
format: this.format,
|
|
155
|
+
dataTypeUnique: this.#dataTypeUnique,
|
|
134
156
|
});
|
|
157
|
+
// A newer request (for example after the data type resolved) supersedes this one.
|
|
158
|
+
if (request !== this.#latestRequest)
|
|
159
|
+
return;
|
|
135
160
|
this._thumbnailUrl = data?.[0]?.url ?? '';
|
|
136
161
|
this._isLoading = false;
|
|
137
162
|
}
|
|
@@ -23,7 +23,8 @@ export class UmbImagingServerDataSource {
|
|
|
23
23
|
async getItems(uniques, imagingModel) {
|
|
24
24
|
if (!uniques.length)
|
|
25
25
|
throw new Error('Uniques are missing');
|
|
26
|
-
const {
|
|
26
|
+
const { dataTypeUnique, ...resizeModel } = imagingModel ?? {};
|
|
27
|
+
const { data, error } = await tryExecute(this.#host, ImagingService.getImagingResizeUrls({ query: { id: uniques, ...resizeModel, dataTypeId: dataTypeUnique } }));
|
|
27
28
|
if (data) {
|
|
28
29
|
const items = data.map((item) => this.#mapper(item));
|
|
29
30
|
return { data: items };
|
|
@@ -5,6 +5,11 @@ export interface UmbImagingResizeModel {
|
|
|
5
5
|
width?: number;
|
|
6
6
|
mode?: UmbImagingCropMode;
|
|
7
7
|
format?: string;
|
|
8
|
+
/**
|
|
9
|
+
* The unique of the data type the request originates from, such as a media picker.
|
|
10
|
+
* Media outside the user's start nodes is only resolved when this data type ignores user start nodes.
|
|
11
|
+
*/
|
|
12
|
+
dataTypeUnique?: string;
|
|
8
13
|
}
|
|
9
14
|
/**
|
|
10
15
|
* Generates a cache key from an imaging resize configuration.
|
|
@@ -7,5 +7,5 @@ export { UmbImagingCropMode };
|
|
|
7
7
|
* @returns {string} The cache key
|
|
8
8
|
*/
|
|
9
9
|
export function generateImagingCacheKey(model) {
|
|
10
|
-
return model ? `${model.width}x${model.height};${model.mode};${model.format}` : 'generic';
|
|
10
|
+
return model ? `${model.width}x${model.height};${model.mode};${model.format};${model.dataTypeUnique}` : 'generic';
|
|
11
11
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the URL if it can be offered as a link, i.e. it resolves to an http or https location.
|
|
3
|
+
* @param {string | undefined} url - The media URL.
|
|
4
|
+
* @param {string} base - The base used to resolve relative URLs.
|
|
5
|
+
* @returns {string | undefined} The URL, or undefined if it must not be rendered as a link.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getLinkableMediaUrl(url: string | undefined, base?: string): string | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Renders an image preview on a checkerboard background into the given document.
|
|
10
|
+
* The image is referenced through an `<img>` element, so scripts embedded in an SVG do not run.
|
|
11
|
+
* @param {Document} document - The document to render into.
|
|
12
|
+
* @param {string} imageUrl - The URL of the image.
|
|
13
|
+
*/
|
|
14
|
+
export declare function renderImagePreview(document: Document, imageUrl: string): void;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the URL if it can be offered as a link, i.e. it resolves to an http or https location.
|
|
3
|
+
* @param {string | undefined} url - The media URL.
|
|
4
|
+
* @param {string} base - The base used to resolve relative URLs.
|
|
5
|
+
* @returns {string | undefined} The URL, or undefined if it must not be rendered as a link.
|
|
6
|
+
*/
|
|
7
|
+
export function getLinkableMediaUrl(url, base = window.location.href) {
|
|
8
|
+
if (!url)
|
|
9
|
+
return undefined;
|
|
10
|
+
try {
|
|
11
|
+
const { protocol } = new URL(url, base);
|
|
12
|
+
return protocol === 'http:' || protocol === 'https:' ? url : undefined;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Renders an image preview on a checkerboard background into the given document.
|
|
20
|
+
* The image is referenced through an `<img>` element, so scripts embedded in an SVG do not run.
|
|
21
|
+
* @param {Document} document - The document to render into.
|
|
22
|
+
* @param {string} imageUrl - The URL of the image.
|
|
23
|
+
*/
|
|
24
|
+
export function renderImagePreview(document, imageUrl) {
|
|
25
|
+
const body = document.body ?? document.documentElement.appendChild(document.createElement('body'));
|
|
26
|
+
body.style.backgroundImage =
|
|
27
|
+
'linear-gradient(45deg, #ccc 25%, transparent 25%), linear-gradient(135deg, #ccc 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #ccc 75%), linear-gradient(135deg, transparent 75%, #ccc 75%)';
|
|
28
|
+
body.style.backgroundSize = '30px 30px';
|
|
29
|
+
body.style.backgroundPosition = '0 0, 15px 0, 15px -15px, 0px 15px';
|
|
30
|
+
const image = document.createElement('img');
|
|
31
|
+
image.src = imageUrl;
|
|
32
|
+
body.replaceChildren(image);
|
|
33
|
+
}
|
package/dist-cms/packages/media/media/url/info-app/media-links-workspace-info-app.element.js
CHANGED
|
@@ -6,11 +6,12 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
6
6
|
};
|
|
7
7
|
import { UmbMediaUrlRepository } from '../repository/index.js';
|
|
8
8
|
import { UMB_MEDIA_WORKSPACE_CONTEXT } from '../../workspace/constants.js';
|
|
9
|
+
import { getLinkableMediaUrl, renderImagePreview } from './media-link.function.js';
|
|
9
10
|
import { css, customElement, html, nothing, repeat, state, when } from '../../../../../external/lit/index.js';
|
|
10
11
|
import { UmbLitElement } from '../../../../core/lit-element/index.js';
|
|
11
12
|
import { UmbRequestReloadStructureForEntityEvent } from '../../../../core/entity-action/index.js';
|
|
12
13
|
import { observeMultiple } from '../../../../../libs/observable-api/index.js';
|
|
13
|
-
import { debounce
|
|
14
|
+
import { debounce } from '../../../../core/utils/index.js';
|
|
14
15
|
let UmbMediaLinksWorkspaceInfoAppElement = class UmbMediaLinksWorkspaceInfoAppElement extends UmbLitElement {
|
|
15
16
|
#mediaUrlRepository;
|
|
16
17
|
#urls;
|
|
@@ -80,14 +81,11 @@ let UmbMediaLinksWorkspaceInfoAppElement = class UmbMediaLinksWorkspaceInfoAppEl
|
|
|
80
81
|
const popup = window.open('', '_blank');
|
|
81
82
|
if (!popup)
|
|
82
83
|
return;
|
|
83
|
-
|
|
84
|
-
<body style="background-image: linear-gradient(45deg, #ccc 25%, transparent 25%), linear-gradient(135deg, #ccc 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #ccc 75%), linear-gradient(135deg, transparent 75%, #ccc 75%); background-size:30px 30px; background-position:0 0, 15px 0, 15px -15px, 0px 15px;">
|
|
85
|
-
<img src="${imagePath}"/>
|
|
86
|
-
<script>history.pushState(null, null, "${sanitizeHTML(window.location.href)}");</script>
|
|
87
|
-
</body>`;
|
|
84
|
+
// Re-opening the document gives it this document's URL, without which the popup cannot push a history state for it.
|
|
88
85
|
popup.document.open();
|
|
89
|
-
popup.document.write(html);
|
|
90
86
|
popup.document.close();
|
|
87
|
+
renderImagePreview(popup.document, imagePath);
|
|
88
|
+
popup.history.pushState(null, '', window.location.href);
|
|
91
89
|
}
|
|
92
90
|
#renderContent() {
|
|
93
91
|
if (this._links.length) {
|
|
@@ -106,19 +104,27 @@ let UmbMediaLinksWorkspaceInfoAppElement = class UmbMediaLinksWorkspaceInfoAppEl
|
|
|
106
104
|
#renderLinkItem(item) {
|
|
107
105
|
if (!item.url)
|
|
108
106
|
return nothing;
|
|
109
|
-
const
|
|
110
|
-
if (
|
|
107
|
+
const url = getLinkableMediaUrl(item.url);
|
|
108
|
+
if (!url) {
|
|
111
109
|
return html `
|
|
112
|
-
<
|
|
110
|
+
<div class="link-item">
|
|
113
111
|
<span class="link-content">${item.url}</span>
|
|
112
|
+
</div>
|
|
113
|
+
`;
|
|
114
|
+
}
|
|
115
|
+
const ext = url.split(/[#?]/)[0].split('.').pop()?.trim().toLowerCase();
|
|
116
|
+
if (ext === 'svg') {
|
|
117
|
+
return html `
|
|
118
|
+
<a href="#" target="_blank" class="link-item with-href" @click=${() => this.#openSvg(url)}>
|
|
119
|
+
<span class="link-content">${url}</span>
|
|
114
120
|
<uui-icon name="icon-out"></uui-icon>
|
|
115
121
|
</a>
|
|
116
122
|
`;
|
|
117
123
|
}
|
|
118
124
|
else {
|
|
119
125
|
return html `
|
|
120
|
-
<a href=${
|
|
121
|
-
<span class="link-content">${
|
|
126
|
+
<a href=${url} target="_blank" class="link-item with-href">
|
|
127
|
+
<span class="link-content">${url}</span>
|
|
122
128
|
<uui-icon name="icon-out"></uui-icon>
|
|
123
129
|
</a>
|
|
124
130
|
`;
|
|
@@ -8,11 +8,7 @@ import { UmbItemServerDataSourceBase } from '../../../../core/repository/index.j
|
|
|
8
8
|
* @augments {UmbItemServerDataSourceBase}
|
|
9
9
|
*/
|
|
10
10
|
export declare class UmbMediaUrlServerDataSource extends UmbItemServerDataSourceBase<MediaUrlInfoResponseModel, UmbMediaUrlModel> {
|
|
11
|
-
|
|
12
|
-
* Creates an instance of UmbMediaUrlServerDataSource.
|
|
13
|
-
* @param {UmbControllerHost} host - The controller host for this controller to be appended to
|
|
14
|
-
* @memberof UmbMediaUrlServerDataSource
|
|
15
|
-
*/
|
|
11
|
+
#private;
|
|
16
12
|
constructor(host: UmbControllerHost);
|
|
17
13
|
getItems(uniques: Array<string>): Promise<{
|
|
18
14
|
data: UmbMediaUrlModel[] | undefined;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { UmbItemDataApiGetRequestController } from '../../../../core/entity-item/index.js';
|
|
2
2
|
import { MediaService } from '../../../../core/backend-api/index.js';
|
|
3
3
|
import { UmbItemServerDataSourceBase } from '../../../../core/repository/index.js';
|
|
4
|
+
import { UMB_PROPERTY_TYPE_BASED_PROPERTY_CONTEXT } from '../../../../content/content/index.js';
|
|
4
5
|
/**
|
|
5
6
|
* A server data source for Media Urls
|
|
6
7
|
* @class UmbMediaUrlServerDataSource
|
|
@@ -12,17 +13,25 @@ export class UmbMediaUrlServerDataSource extends UmbItemServerDataSourceBase {
|
|
|
12
13
|
* @param {UmbControllerHost} host - The controller host for this controller to be appended to
|
|
13
14
|
* @memberof UmbMediaUrlServerDataSource
|
|
14
15
|
*/
|
|
16
|
+
#dataTypeUnique;
|
|
15
17
|
constructor(host) {
|
|
16
18
|
super(host, {
|
|
17
19
|
mapper,
|
|
18
20
|
});
|
|
21
|
+
// A picker configured to ignore user start nodes may reference media outside them,
|
|
22
|
+
// which the server only resolves when told which data type the request originates from.
|
|
23
|
+
this.consumeContext(UMB_PROPERTY_TYPE_BASED_PROPERTY_CONTEXT, (context) => {
|
|
24
|
+
this.observe(context?.dataType, (dataType) => {
|
|
25
|
+
this.#dataTypeUnique = dataType?.unique;
|
|
26
|
+
}, '_observeDataType');
|
|
27
|
+
});
|
|
19
28
|
}
|
|
20
29
|
async getItems(uniques) {
|
|
21
30
|
if (!uniques)
|
|
22
31
|
throw new Error('Uniques are missing');
|
|
23
32
|
const itemRequestManager = new UmbItemDataApiGetRequestController(this, {
|
|
24
33
|
// eslint-disable-next-line local-rules/no-direct-api-import
|
|
25
|
-
api: (args) => MediaService.getMediaUrls({ query: { id: args.uniques } }),
|
|
34
|
+
api: (args) => MediaService.getMediaUrls({ query: { id: args.uniques, dataTypeId: this.#dataTypeUnique } }),
|
|
26
35
|
uniques,
|
|
27
36
|
});
|
|
28
37
|
const { data, error } = await itemRequestManager.request();
|
package/dist-cms/packages/multi-url-picker/components/input-multi-url/input-multi-url.element.js
CHANGED
|
@@ -237,7 +237,7 @@ let UmbInputMultiUrlElement = class UmbInputMultiUrlElement extends UmbFormContr
|
|
|
237
237
|
}
|
|
238
238
|
async #getUrlForMedia(unique) {
|
|
239
239
|
const { data } = await this.#mediaUrlRepository.requestItems([unique]);
|
|
240
|
-
return data?.[0]
|
|
240
|
+
return data?.[0]?.url ?? '';
|
|
241
241
|
}
|
|
242
242
|
async #getNameForDocument(unique) {
|
|
243
243
|
const { data } = await this.#documentItemRepository.requestItems([unique]);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { attachLinkInterceptor } from '../utils/index.js';
|
|
2
2
|
import { UmbPreviewRepository } from '../repository/index.js';
|
|
3
|
+
import { UmbPreviewSessionRenewalController } from '../controllers/preview-session-renewal.controller.js';
|
|
3
4
|
import { UMB_PREVIEW_CONTEXT } from './preview.context-token.js';
|
|
4
5
|
import { HubConnectionBuilder, HttpTransportType } from '../../../external/signalr/index.js';
|
|
5
6
|
import { UmbBooleanState, UmbStringState } from '../../../libs/observable-api/index.js';
|
|
@@ -17,6 +18,7 @@ export class UmbPreviewContext extends UmbContextBase {
|
|
|
17
18
|
#serverContext;
|
|
18
19
|
#serverUrl;
|
|
19
20
|
#previewRepository;
|
|
21
|
+
#previewSessionRenewal;
|
|
20
22
|
#localize;
|
|
21
23
|
#culture;
|
|
22
24
|
#iframeReady;
|
|
@@ -28,6 +30,7 @@ export class UmbPreviewContext extends UmbContextBase {
|
|
|
28
30
|
this.#currentArgs = {};
|
|
29
31
|
this.#serverUrl = '';
|
|
30
32
|
this.#previewRepository = new UmbPreviewRepository(this);
|
|
33
|
+
this.#previewSessionRenewal = new UmbPreviewSessionRenewalController(this, this.#previewRepository);
|
|
31
34
|
this.#localize = new UmbLocalizationController(this);
|
|
32
35
|
this.#culture = new UmbStringState(undefined);
|
|
33
36
|
this.culture = this.#culture.asObservable();
|
|
@@ -63,6 +66,9 @@ export class UmbPreviewContext extends UmbContextBase {
|
|
|
63
66
|
this.consumeContext(UMB_AUTH_CONTEXT, (authContext) => {
|
|
64
67
|
this.#authContext = authContext;
|
|
65
68
|
this.#initHubConnection();
|
|
69
|
+
if (authContext) {
|
|
70
|
+
this.#previewSessionRenewal.observeSession(authContext.session$, () => this.#getPreviewSessionArgs());
|
|
71
|
+
}
|
|
66
72
|
});
|
|
67
73
|
this.consumeContext(UMB_NOTIFICATION_CONTEXT, (notificationContext) => {
|
|
68
74
|
this.#notificationContext = notificationContext;
|
|
@@ -97,8 +103,9 @@ export class UmbPreviewContext extends UmbContextBase {
|
|
|
97
103
|
hubOptions.transport = HttpTransportType.WebSockets;
|
|
98
104
|
}
|
|
99
105
|
this.#connection = new HubConnectionBuilder().withUrl(previewHubUrl, hubOptions).build();
|
|
100
|
-
this.#connection.on('refreshed', (payload) => {
|
|
106
|
+
this.#connection.on('refreshed', async (payload) => {
|
|
101
107
|
if (payload === this.#unique.getValue()) {
|
|
108
|
+
await this.#previewSessionRenewal.renew(this.#getPreviewSessionArgs());
|
|
102
109
|
this.#setPreviewUrl({ rnd: Math.random() });
|
|
103
110
|
}
|
|
104
111
|
});
|
|
@@ -123,6 +130,13 @@ export class UmbPreviewContext extends UmbContextBase {
|
|
|
123
130
|
});
|
|
124
131
|
}
|
|
125
132
|
}
|
|
133
|
+
#getPreviewSessionArgs() {
|
|
134
|
+
return {
|
|
135
|
+
unique: this.#unique.getValue(),
|
|
136
|
+
culture: this.#culture.getValue(),
|
|
137
|
+
segment: this.#segment.getValue(),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
126
140
|
async #getPublishedUrl() {
|
|
127
141
|
const unique = this.#unique.getValue();
|
|
128
142
|
if (!unique)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { UmbPreviewRepository } from '../repository/preview.repository.js';
|
|
2
|
+
import { UmbControllerBase } from '../../../libs/class-api/index.js';
|
|
3
|
+
import type { Observable } from '../../../external/rxjs/index.js';
|
|
4
|
+
import type { UmbControllerHost } from '../../../libs/controller-api/index.js';
|
|
5
|
+
export interface UmbPreviewSessionRenewalArgs {
|
|
6
|
+
unique?: string;
|
|
7
|
+
culture?: string;
|
|
8
|
+
segment?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Keeps the website preview session alive for as long as the back-office session is, by asking the server to
|
|
12
|
+
* renew it whenever the back-office session is renewed.
|
|
13
|
+
*/
|
|
14
|
+
export declare class UmbPreviewSessionRenewalController extends UmbControllerBase {
|
|
15
|
+
#private;
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new {@link UmbPreviewSessionRenewalController}.
|
|
18
|
+
* @param {UmbControllerHost} host - The controller host.
|
|
19
|
+
* @param {UmbPreviewRepository} [previewRepository] - Optional repository override; defaults to a new
|
|
20
|
+
* {@link UmbPreviewRepository}. Intended for testing.
|
|
21
|
+
*/
|
|
22
|
+
constructor(host: UmbControllerHost, previewRepository?: UmbPreviewRepository);
|
|
23
|
+
/**
|
|
24
|
+
* Renews the preview session each time the given back-office session emits a live session.
|
|
25
|
+
* @param {Observable<unknown>} session - The back-office session; emits a falsy value when there is no session.
|
|
26
|
+
* @param {() => UmbPreviewSessionRenewalArgs} getArgs - Provides the document currently being previewed.
|
|
27
|
+
*/
|
|
28
|
+
observeSession(session: Observable<unknown>, getArgs: () => UmbPreviewSessionRenewalArgs): void;
|
|
29
|
+
/**
|
|
30
|
+
* Renews the preview session for the given document.
|
|
31
|
+
* @param {UmbPreviewSessionRenewalArgs} args - The document currently being previewed.
|
|
32
|
+
* @returns {Promise<void>} Resolves once the renewal has completed or failed.
|
|
33
|
+
*/
|
|
34
|
+
renew(args: UmbPreviewSessionRenewalArgs): Promise<void>;
|
|
35
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { UmbPreviewRepository } from '../repository/preview.repository.js';
|
|
2
|
+
import { UmbControllerBase } from '../../../libs/class-api/index.js';
|
|
3
|
+
// The preview app always previews through the built-in document URL provider, whose preview URL is internal
|
|
4
|
+
// and so (re)starts the preview session on the server.
|
|
5
|
+
const UMB_PREVIEW_SESSION_URL_PROVIDER_ALIAS = 'umbDocumentUrlProvider';
|
|
6
|
+
/**
|
|
7
|
+
* Keeps the website preview session alive for as long as the back-office session is, by asking the server to
|
|
8
|
+
* renew it whenever the back-office session is renewed.
|
|
9
|
+
*/
|
|
10
|
+
export class UmbPreviewSessionRenewalController extends UmbControllerBase {
|
|
11
|
+
#previewRepository;
|
|
12
|
+
/**
|
|
13
|
+
* Creates a new {@link UmbPreviewSessionRenewalController}.
|
|
14
|
+
* @param {UmbControllerHost} host - The controller host.
|
|
15
|
+
* @param {UmbPreviewRepository} [previewRepository] - Optional repository override; defaults to a new
|
|
16
|
+
* {@link UmbPreviewRepository}. Intended for testing.
|
|
17
|
+
*/
|
|
18
|
+
constructor(host, previewRepository) {
|
|
19
|
+
super(host);
|
|
20
|
+
this.#previewRepository = previewRepository ?? new UmbPreviewRepository(this);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Renews the preview session each time the given back-office session emits a live session.
|
|
24
|
+
* @param {Observable<unknown>} session - The back-office session; emits a falsy value when there is no session.
|
|
25
|
+
* @param {() => UmbPreviewSessionRenewalArgs} getArgs - Provides the document currently being previewed.
|
|
26
|
+
*/
|
|
27
|
+
observeSession(session, getArgs) {
|
|
28
|
+
this.observe(session, (value) => {
|
|
29
|
+
if (value) {
|
|
30
|
+
this.renew(getArgs());
|
|
31
|
+
}
|
|
32
|
+
}, '_observePreviewSession');
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Renews the preview session for the given document.
|
|
36
|
+
* @param {UmbPreviewSessionRenewalArgs} args - The document currently being previewed.
|
|
37
|
+
* @returns {Promise<void>} Resolves once the renewal has completed or failed.
|
|
38
|
+
*/
|
|
39
|
+
async renew(args) {
|
|
40
|
+
if (!args.unique)
|
|
41
|
+
return;
|
|
42
|
+
try {
|
|
43
|
+
await this.#previewRepository.getPreviewUrl(args.unique, UMB_PREVIEW_SESSION_URL_PROVIDER_ALIAS, args.culture, args.segment);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// The preview carries on with its current session until that expires.
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|