Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Document Workspace Info reload components #2492

Merged
merged 4 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -63,6 +63,7 @@ export class UmbHistoryItemElement extends UmbLitElement {
.user-info div {
display: flex;
flex-direction: column;
min-width: var(--uui-size-60);
}

.detail {
Expand Down
1 change: 1 addition & 0 deletions src/packages/documents/documents/repository/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export { UmbDocumentDetailRepository, UMB_DOCUMENT_DETAIL_REPOSITORY_ALIAS } from './detail/index.js';
export { UmbDocumentItemRepository, UMB_DOCUMENT_ITEM_REPOSITORY_ALIAS } from './item/index.js';
export { UmbDocumentPublishingRepository, UMB_DOCUMENT_PUBLISHING_REPOSITORY_ALIAS } from './publishing/index.js';
export { UmbDocumentUrlRepository, UMB_DOCUMENT_URL_REPOSITORY_ALIAS } from './url/index.js';
export { UmbDocumentPreviewRepository } from './preview/index.js';

export type { UmbDocumentItemModel } from './item/types.js';
8 changes: 7 additions & 1 deletion src/packages/documents/documents/repository/manifests.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { manifests as detailManifests } from './detail/manifests.js';
import { manifests as itemManifests } from './item/manifests.js';
import { manifests as publishingManifests } from './publishing/manifests.js';
import { manifests as urlManifests } from './url/manifests.js';

export const manifests: Array<UmbExtensionManifest> = [...detailManifests, ...itemManifests, ...publishingManifests];
export const manifests: Array<UmbExtensionManifest> = [
...detailManifests,
...itemManifests,
...publishingManifests,
...urlManifests,
];
2 changes: 2 additions & 0 deletions src/packages/documents/documents/repository/url/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const UMB_DOCUMENT_URL_REPOSITORY_ALIAS = 'Umb.Repository.Document.Url';
export const UMB_DOCUMENT_URL_STORE_ALIAS = 'Umb.Store.Document.Url';
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { UmbDocumentUrlsModel } from './types.js';
import { UMB_DOCUMENT_URL_STORE_CONTEXT } from './document-url.store.context-token.js';
import { UmbDocumentUrlServerDataSource } from './document-url.server.data-source.js';
import { UmbItemRepositoryBase } from '@umbraco-cms/backoffice/repository';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';

export class UmbDocumentUrlRepository extends UmbItemRepositoryBase<UmbDocumentUrlsModel> {
constructor(host: UmbControllerHost) {
super(host, UmbDocumentUrlServerDataSource, UMB_DOCUMENT_URL_STORE_CONTEXT);
}
}

export { UmbDocumentUrlRepository as api };
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { UmbDocumentUrlsModel } from './types.js';
import { DocumentService } from '@umbraco-cms/backoffice/external/backend-api';
import { UmbItemServerDataSourceBase } from '@umbraco-cms/backoffice/repository';
import type { DocumentUrlInfoResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';

/**
* A server data source for Document URLs
* @class UmbDocumentUrlServerDataSource
* @implements {DocumentTreeDataSource}
*/
export class UmbDocumentUrlServerDataSource extends UmbItemServerDataSourceBase<
DocumentUrlInfoResponseModel,
UmbDocumentUrlsModel
> {
/**
* Creates an instance of UmbDocumentUrlServerDataSource.
* @param {UmbControllerHost} host - The controller host for this controller to be appended to
* @memberof UmbDocumentUrlServerDataSource
*/
constructor(host: UmbControllerHost) {
super(host, { getItems, mapper });
}
}

/* eslint-disable local-rules/no-direct-api-import */
const getItems = (uniques: Array<string>) => DocumentService.getDocumentUrls({ id: uniques });

const mapper = (item: DocumentUrlInfoResponseModel): UmbDocumentUrlsModel => ({ unique: item.id, urls: item.urlInfos });
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import type UmbDocumentUrlStore from './document-url.store.js';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';

export const UMB_DOCUMENT_URL_STORE_CONTEXT = new UmbContextToken<UmbDocumentUrlStore>('UmbDocumentUrlStore');
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { UmbDocumentDetailModel } from '../../types.js';
import { UMB_DOCUMENT_URL_STORE_CONTEXT } from './document-url.store.context-token.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemStoreBase } from '@umbraco-cms/backoffice/store';

/**
* @class UmbDocumentUrlStore
* @augments {UmbStoreBase}
* @description - Data Store for Document URLs
*/

export class UmbDocumentUrlStore extends UmbItemStoreBase<UmbDocumentDetailModel> {
/**
* Creates an instance of UmbDocumentUrlStore.
* @param {UmbControllerHost} host - The controller host for this controller to be appended to
* @memberof UmbDocumentUrlStore
*/
constructor(host: UmbControllerHost) {
super(host, UMB_DOCUMENT_URL_STORE_CONTEXT.toString());
}
}

export default UmbDocumentUrlStore;
2 changes: 2 additions & 0 deletions src/packages/documents/documents/repository/url/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { UmbDocumentUrlRepository } from './document-url.repository.js';
export { UMB_DOCUMENT_URL_REPOSITORY_ALIAS } from './constants.js';
18 changes: 18 additions & 0 deletions src/packages/documents/documents/repository/url/manifests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { UMB_DOCUMENT_URL_REPOSITORY_ALIAS, UMB_DOCUMENT_URL_STORE_ALIAS } from './constants.js';
import type { ManifestItemStore, ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';

const urlRepository: ManifestRepository = {
type: 'repository',
alias: UMB_DOCUMENT_URL_REPOSITORY_ALIAS,
name: 'Document Url Repository',
api: () => import('./document-url.repository.js'),
};

const urlStore: ManifestItemStore = {
type: 'itemStore',
alias: UMB_DOCUMENT_URL_STORE_ALIAS,
name: 'Document Url Store',
api: () => import('./document-url.store.js'),
};

export const manifests = [urlRepository, urlStore];
9 changes: 9 additions & 0 deletions src/packages/documents/documents/repository/url/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export interface UmbDocumentUrlsModel {
unique: string;
urls: Array<UmbDocumentUrlModel>;
}

export interface UmbDocumentUrlModel {
culture?: string | null;
url?: string;
}
Original file line number Diff line number Diff line change
@@ -1,46 +1,65 @@
import type { UmbDocumentAuditLogModel } from '../../../audit-log/types.js';
import { UmbDocumentAuditLogRepository } from '../../../audit-log/index.js';
import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../../document-workspace.context-token.js';
import { TimeOptions, getDocumentHistoryTagStyleAndText } from './utils.js';
import { css, html, customElement, state, nothing, repeat } from '@umbraco-cms/backoffice/external/lit';
import { getDocumentHistoryTagStyleAndText, TimeOptions } from './utils.js';
import { css, customElement, html, nothing, repeat, state, when } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UmbPaginationManager } from '@umbraco-cms/backoffice/utils';
import type { UUIPaginationEvent } from '@umbraco-cms/backoffice/external/uui';
import type { UmbUserItemModel } from '@umbraco-cms/backoffice/user';
import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/entity-action';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { UmbUserItemRepository } from '@umbraco-cms/backoffice/user';
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
import type { ManifestEntityAction } from '@umbraco-cms/backoffice/entity-action';
import type { UmbUserItemModel } from '@umbraco-cms/backoffice/user';
import type { UUIPaginationEvent } from '@umbraco-cms/backoffice/external/uui';

@customElement('umb-document-workspace-view-info-history')
export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement {
@state()
_currentPageNumber = 1;
#allowedActions = new Set(['Umb.EntityAction.Document.Rollback']);

@state()
_totalPages = 1;

@state()
private _items: Array<UmbDocumentAuditLogModel> = [];

#workspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE;
#auditLogRepository = new UmbDocumentAuditLogRepository(this);

#pagination = new UmbPaginationManager();

#userItemRepository = new UmbUserItemRepository(this);

#userMap = new Map<string, UmbUserItemModel>();

#workspaceContext?: typeof UMB_DOCUMENT_WORKSPACE_CONTEXT.TYPE;

@state()
private _currentPageNumber = 1;

@state()
private _items: Array<UmbDocumentAuditLogModel> = [];

@state()
private _totalPages = 1;

constructor() {
super();

this.#pagination.setPageSize(10);
this.observe(this.#pagination.currentPage, (number) => (this._currentPageNumber = number));
this.observe(this.#pagination.totalPages, (number) => (this._totalPages = number));

this.consumeContext(UMB_ACTION_EVENT_CONTEXT, (context) => {
context.addEventListener(UmbRequestReloadStructureForEntityEvent.TYPE, () => {
this.#requestAuditLogs();
});
});

this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (instance) => {
this.#workspaceContext = instance;
this.#requestAuditLogs();
});
}

#onPageChange(event: UUIPaginationEvent) {
this.#pagination.setCurrentPageNumber(event.target?.current);
this.#requestAuditLogs();
}

async #requestAuditLogs() {
const unique = this.#workspaceContext?.getUnique();
if (!unique) throw new Error('Document unique is required');
Expand All @@ -58,11 +77,6 @@ export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement {
}
}

#onPageChange(event: UUIPaginationEvent) {
this.#pagination.setCurrentPageNumber(event.target?.current);
this.#requestAuditLogs();
}

async #requestAndCacheUserItems() {
const allUsers = this._items?.map((item) => item.user.unique).filter(Boolean) as string[];
const uniqueUsers = [...new Set(allUsers)];
Expand All @@ -83,90 +97,84 @@ export class UmbDocumentWorkspaceViewInfoHistoryElement extends UmbLitElement {
}

override render() {
return html`<uui-box>
<umb-localize slot="headline" key="general_history">History</umb-localize>
<umb-extension-with-api-slot
return html`
<uui-box headline=${this.localize.term('general_history')}>
<umb-extension-with-api-slot
slot="header-actions"
type="entityAction"
.filter=${(manifest: any) => manifest.alias === 'Umb.EntityAction.Document.Rollback'}></umb-extension-with-api-slot>
.filter=${(manifest: ManifestEntityAction) => this.#allowedActions.has(manifest.alias)}></umb-extension-with-api-slot>
</uui-button>
${this._items ? this.#renderHistory() : html`<uui-loader-circle></uui-loader-circle> `}
${when(
this._items,
() => this.#renderHistory(),
() => html`<div id="loader"><uui-loader></uui-loader></div>`,
)}
${this.#renderPagination()}
</uui-box> `;
</uui-box>
`;
}

#renderHistory() {
if (this._items && this._items.length) {
return html`
<umb-history-list>
${repeat(
this._items,
(item) => item.timestamp,
(item) => {
const { text, style } = getDocumentHistoryTagStyleAndText(item.logType);
const user = this.#userMap.get(item.user.unique);

return html`<umb-history-item
if (!this._items?.length) return html`${this.localize.term('content_noItemsToShow')}`;
return html`
<umb-history-list>
${repeat(
this._items,
(item) => item.timestamp,
(item) => {
const { text, style } = getDocumentHistoryTagStyleAndText(item.logType);
const user = this.#userMap.get(item.user.unique);

return html`
<umb-history-item
.name=${user?.name ?? 'Unknown'}
.detail=${this.localize.date(item.timestamp, TimeOptions)}>
<umb-user-avatar
slot="avatar"
.name=${user?.name}
.kind=${user?.kind}
.imgUrls=${user?.avatarUrls ?? []}></umb-user-avatar>

<span class="log-type">
.imgUrls=${user?.avatarUrls ?? []}>
</umb-user-avatar>
<div class="log-type">
<uui-tag look=${style.look} color=${style.color}>
${this.localize.term(text.label, item.parameters)}
</uui-tag>
${this.localize.term(text.desc, item.parameters)}
</span>
</umb-history-item>`;
},
)}
</umb-history-list>
`;
} else {
return html`${this.localize.term('content_noItemsToShow')}`;
}
<span>${this.localize.term(text.desc, item.parameters)}</span>
</div>
</umb-history-item>
`;
},
)}
</umb-history-list>
`;
}

#renderPagination() {
if (this._totalPages <= 1) return nothing;
return html`
${this._totalPages > 1
? html`
<uui-pagination
class="pagination"
.current=${this._currentPageNumber}
.total=${this._totalPages}
@change=${this.#onPageChange}></uui-pagination>
`
: nothing}
<uui-pagination
.current=${this._currentPageNumber}
.total=${this._totalPages}
@change=${this.#onPageChange}></uui-pagination>
`;
}

static override styles = [
UmbTextStyles,
css`
uui-loader-circle {
font-size: 2rem;
}

uui-tag uui-icon {
margin-right: var(--uui-size-space-1);
#loader {
display: flex;
justify-content: center;
}

.log-type {
flex-grow: 1;
gap: var(--uui-size-space-2);
display: grid;
grid-template-columns: var(--uui-size-40) auto;
gap: var(--uui-size-layout-1);
}

uui-pagination {
flex: 1;
display: inline-block;
}

.pagination {
display: flex;
justify-content: center;
margin-top: var(--uui-size-layout-1);
Expand Down
Loading
Loading