Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { manifests as previewManifests } from './preview/manifests.js';
import { manifests as propertyEditorManifests } from './property-editors/manifests.js';
import { manifests as publishingManifests } from './publishing/manifests.js';
import { manifests as recycleBinManifests } from './recycle-bin/manifests.js';
import { manifests as redirectManagementManifests } from './redirect-management/manifests.js';
import { manifests as repositoryManifests } from './repository/manifests.js';
import { manifests as rollbackManifests } from './rollback/manifests.js';
import { manifests as searchProviderManifests } from './search/manifests.js';
Expand Down Expand Up @@ -40,6 +41,7 @@ export const manifests: Array<UmbExtensionManifest | UmbExtensionManifestKind> =
...propertyEditorManifests,
...publishingManifests,
...recycleBinManifests,
...redirectManagementManifests,
...repositoryManifests,
...rollbackManifests,
...searchProviderManifests,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../workspace/constants.js';
import {
css,
customElement,
html,
ifDefined,
Comment thread
Zeegaan marked this conversation as resolved.
nothing,
repeat,
state,
when,
} from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UmbEntityActionEvent } from '@umbraco-cms/backoffice/entity-action';
import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/entity-action';
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { debounce } from '@umbraco-cms/backoffice/utils';
import { tryExecute } from '@umbraco-cms/backoffice/resources';
import {
RedirectManagementService,
RedirectStatusModel,
type RedirectUrlResponseModel,
} from '@umbraco-cms/backoffice/external/backend-api';

@customElement('umb-document-redirect-management-workspace-info-app')
export class UmbDocumentRedirectManagementWorkspaceInfoAppElement extends UmbLitElement {
@state()
private _isNew = false;

@state()
private _unique?: string;

@state()
private _trackerEnabled = true;

@state()
private _loading = false;

@state()
private _redirects: Array<RedirectUrlResponseModel> = [];

#documentWorkspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE;
#eventContext?: typeof UMB_ACTION_EVENT_CONTEXT.TYPE;

constructor() {
super();

this.consumeContext(UMB_ACTION_EVENT_CONTEXT, (context) => {
this.#eventContext = context;

this.#eventContext?.removeEventListener(
UmbRequestReloadStructureForEntityEvent.TYPE,
this.#onReloadRequest as unknown as EventListener,
);

this.#eventContext?.addEventListener(
UmbRequestReloadStructureForEntityEvent.TYPE,
this.#onReloadRequest as unknown as EventListener,
);
});

this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (context) => {
this.#documentWorkspaceContext = context;

this.observe(
context?.isNew,
(isNew) => {
this._isNew = isNew === true;
},
'observeIsNew',
);

this.observe(
context?.unique,
(unique) => {
if (!unique || unique === this._unique) return;
this._unique = unique;
this.#requestRedirects();
},
'observeUnique',
);
});

this.#requestTrackerStatus();
}

async #requestTrackerStatus() {
const { data } = await tryExecute(this, RedirectManagementService.getRedirectManagementStatus());
if (data?.status) {
this._trackerEnabled = data.status === RedirectStatusModel.ENABLED;
}
}

async #requestRedirects() {
if (this._isNew) return;
if (!this._unique) return;

this._loading = true;

const { data } = await tryExecute(
this,
RedirectManagementService.getRedirectManagementById({ path: { id: this._unique } }),
);

this._redirects = data?.items ?? [];
this._loading = false;
}

#debounceRequestRedirects = debounce(() => this.#requestRedirects(), 50);

#onReloadRequest = (event: UmbEntityActionEvent) => {
if (event.getUnique() !== this.#documentWorkspaceContext?.getUnique()) return;
if (event.getEntityType() !== this.#documentWorkspaceContext.getEntityType()) return;
this.#debounceRequestRedirects();
};

#getTargetUrl(url: string | undefined) {
if (!url || url.length === 0) return url;
Comment thread
Zeegaan marked this conversation as resolved.
Outdated
if (url.includes('.') && !url.includes('//')) return '//' + url;
return url;
}

override render() {
if (!this._trackerEnabled) return nothing;
if (this._isNew) return nothing;
if (!this._loading && this._redirects.length === 0) return nothing;

return html`
<umb-workspace-info-app-layout headline="#redirectUrls_redirectUrlManagement">
<div id="content">
${when(
this._loading,
() => this.#renderLoading(),
() => this.#renderContent(),
)}
</div>
</umb-workspace-info-app-layout>
`;
}

#renderLoading() {
return html`<div id="loader-container"><uui-loader></uui-loader></div>`;
}

#renderContent() {
return html`
<umb-localize class="panel-information" key="redirectUrls_panelInformation">
The following URLs redirect to this content item:
</umb-localize>
${repeat(
this._redirects,
(redirect) => redirect.id,
(redirect) => this.#renderRedirect(redirect),
)}
`;
}

#renderRedirect(redirect: RedirectUrlResponseModel) {
return html`
<a
class="redirect-item"
href=${ifDefined(this.#getTargetUrl(redirect.originalUrl))}
target="_blank"
rel="noopener">
<span>
${redirect.culture ? html`<span class="culture">${redirect.culture}</span>` : nothing}
<span>${redirect.originalUrl}</span>
</span>
<uui-icon name="icon-out"></uui-icon>
</a>
`;
}

override disconnectedCallback(): void {
super.disconnectedCallback();

this.#eventContext?.removeEventListener(
UmbRequestReloadStructureForEntityEvent.TYPE,
this.#onReloadRequest as unknown as EventListener,
);
}

static override styles = [
UmbTextStyles,
css`
:host {
display: contents;
}

#content {
display: block;
padding: var(--uui-size-space-3) var(--uui-size-space-4);
}

#loader-container {
display: flex;
justify-content: center;
align-items: center;
padding: var(--uui-size-space-2);
}

.panel-information {
display: block;
margin: var(--uui-size-space-2);
}

.redirect-item {
display: flex;
justify-content: space-between;
align-items: center;
gap: var(--uui-size-6);
padding: var(--uui-size-space-4) var(--uui-size-space-5);
margin: 0 calc(var(--uui-size-space-4) * -1);
cursor: pointer;
color: inherit;
text-decoration: none;

&:hover {
background: var(--uui-color-divider);
}

& > span {
display: flex;
align-items: center;
gap: var(--uui-size-6);
}

.culture {
color: var(--uui-color-divider-emphasis);
}
}
`,
];
}

export default UmbDocumentRedirectManagementWorkspaceInfoAppElement;

declare global {
interface HTMLElementTagNameMap {
'umb-document-redirect-management-workspace-info-app': UmbDocumentRedirectManagementWorkspaceInfoAppElement;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { UMB_DOCUMENT_WORKSPACE_ALIAS } from '../../workspace/constants.js';
import {
UMB_WORKSPACE_CONDITION_ALIAS,
UMB_WORKSPACE_ENTITY_IS_NEW_CONDITION_ALIAS,
} from '@umbraco-cms/backoffice/workspace';

export const manifests: Array<UmbExtensionManifest> = [
{
type: 'workspaceInfoApp',
name: 'Document Redirect Management Workspace Info App',
alias: 'Umb.WorkspaceInfoApp.Document.RedirectManagement',
element: () => import('./document-redirect-management-workspace-info-app.element.js'),
weight: 85,
conditions: [
{
alias: UMB_WORKSPACE_CONDITION_ALIAS,
match: UMB_DOCUMENT_WORKSPACE_ALIAS,
},
{
alias: UMB_WORKSPACE_ENTITY_IS_NEW_CONDITION_ALIAS,
match: false,
},
],
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { manifests as infoAppManifests } from './info-app/manifests.js';

export const manifests: Array<UmbExtensionManifest> = [...infoAppManifests];
Loading