workspace info (#546)
* info workspace w history * split history ui into list and nodes * line between histories * same folder * rollback button * round button * history logtype * longer list for mock * storybook & other sections of workspace info * rename elements --------- Co-authored-by: Lone Iversen <108085781+loivsen@users.noreply.github.com> Co-authored-by: Mads Rasmussen <madsr@hey.com>
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
import { css, html } from 'lit';
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
|
||||
@customElement('umb-history-item')
|
||||
export class UmbHistoryItemElement extends UmbLitElement {
|
||||
static styles = [
|
||||
UUITextStyles,
|
||||
css`
|
||||
:host {
|
||||
--avatar-size: calc(2em + 4px);
|
||||
display: block;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
gap: calc(2 * var(--uui-size-space-5));
|
||||
align-items: center;
|
||||
}
|
||||
.slots-wrapper {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
slot[name='actions'] {
|
||||
--uui-button-border-radius: 50px 50px 50px 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
--uui-button-height: calc(var(--uui-size-2) * 4);
|
||||
margin-right: var(--uui-size-2);
|
||||
}
|
||||
#actions-container {
|
||||
opacity: 0;
|
||||
transition: opacity 120ms;
|
||||
}
|
||||
:host(:hover) #actions-container {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
:host(:hover) #actions-container {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: var(--uui-size-space-5);
|
||||
}
|
||||
.user-info div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.detail {
|
||||
font-size: var(--uui-size-4);
|
||||
color: var(--uui-color-text-alt);
|
||||
line-height: 1;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@property({ type: String })
|
||||
src?: string;
|
||||
|
||||
@property({ type: String })
|
||||
name?: string;
|
||||
|
||||
@property({ type: String })
|
||||
detail?: string;
|
||||
|
||||
render() {
|
||||
return html`<div id="wrapper">
|
||||
<div class="user-info">
|
||||
<uui-avatar .name="${this.name ?? 'Unknown'}" ?src="${this.src}"></uui-avatar>
|
||||
<div>
|
||||
<span class="name">${this.name}</span>
|
||||
<span class="detail">${this.detail}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="slots-wrapper">
|
||||
<slot id="description"></slot>
|
||||
<slot id="actions-container" name="actions"></slot>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
export default UmbHistoryItemElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-history-item': UmbHistoryItemElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import { css, html } from 'lit';
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
|
||||
@customElement('umb-history-list')
|
||||
export class UmbHistoryListElement extends UmbLitElement {
|
||||
static styles = [
|
||||
UUITextStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
--avatar-size: calc(2em + 4px);
|
||||
}
|
||||
|
||||
::slotted(*) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
::slotted(*:not(:last-child)) {
|
||||
margin-bottom: calc(2 * var(--uui-size-space-3));
|
||||
}
|
||||
|
||||
::slotted(*:not(:last-child))::before {
|
||||
content: '';
|
||||
border: 1px solid var(--uui-color-border);
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: calc(1.5 * var(--avatar-size));
|
||||
top: var(--avatar-size);
|
||||
left: calc(-1px + var(--avatar-size) / 2);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
render() {
|
||||
return html`<div>
|
||||
<slot></slot>
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
export default UmbHistoryListElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-history-list': UmbHistoryListElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import './history-list.element';
|
||||
import './history-item.element';
|
||||
|
||||
import { Meta, Story } from '@storybook/web-components';
|
||||
import { html } from 'lit-html';
|
||||
|
||||
import type { UmbHistoryListElement } from './history-list.element';
|
||||
import type { UmbHistoryItemElement } from './history-item.element';
|
||||
|
||||
export default {
|
||||
title: 'Components/History UI',
|
||||
component: 'umb-history-list',
|
||||
id: 'umb-history-list',
|
||||
} as Meta;
|
||||
|
||||
export const AAAOverview: Story<UmbHistoryListElement> = () => html` <umb-history-list>
|
||||
<umb-history-item name="Name attribute" detail="Detail attribute">
|
||||
Default slot
|
||||
<uui-button slot="actions" label="action">Action slot</uui-button>
|
||||
</umb-history-item>
|
||||
<umb-history-item name="Name attribute" detail="Detail attribute">
|
||||
Default slot
|
||||
<uui-button slot="actions" label="action">Action slot</uui-button>
|
||||
</umb-history-item>
|
||||
<umb-history-item name="Name attribute" detail="Detail attribute">
|
||||
Default slot
|
||||
<uui-button slot="actions" label="action">Action slot</uui-button>
|
||||
</umb-history-item>
|
||||
</umb-history-list>`;
|
||||
AAAOverview.storyName = 'Overview';
|
||||
|
||||
export const Node: Story<UmbHistoryItemElement> = () => html`<umb-history-item
|
||||
name="Name attribute"
|
||||
detail="Detail attribute">
|
||||
Default slot
|
||||
<uui-button slot="actions" label="action">Action slot</uui-button>
|
||||
</umb-history-item>`;
|
||||
@@ -31,6 +31,10 @@ import './table/table.element';
|
||||
import './tree/tree.element';
|
||||
import './variantable-property/variantable-property.element';
|
||||
import './workspace/workspace-action-menu/workspace-action-menu.element';
|
||||
|
||||
import './history/history-list.element';
|
||||
import './history/history-item.element';
|
||||
|
||||
import './workspace/workspace-action/workspace-action.element';
|
||||
import './workspace/workspace-content/workspace-content.element';
|
||||
import './workspace/workspace-layout/workspace-layout.element';
|
||||
|
||||
@@ -1,26 +1,191 @@
|
||||
import { css, html } from 'lit';
|
||||
import { css, html, nothing } from 'lit';
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { UUIPaginationEvent } from '@umbraco-ui/uui';
|
||||
import { UmbWorkspaceEntityContextInterface } from '../../../workspace-context/workspace-entity-context.interface';
|
||||
import type { DocumentModel } from '@umbraco-cms/backend-api';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
|
||||
interface HistoryNode {
|
||||
userId?: number;
|
||||
userAvatars?: [];
|
||||
userName?: string;
|
||||
timestamp?: string;
|
||||
comment?: string;
|
||||
entityType?: string;
|
||||
logType?: HistoryLogType;
|
||||
nodeId?: string;
|
||||
parameters?: string;
|
||||
}
|
||||
|
||||
type HistoryLogType = 'Publish' | 'Save' | 'Unpublish' | 'ContentVersionEnableCleanup' | 'ContentVersionPreventCleanup';
|
||||
|
||||
@customElement('umb-workspace-view-content-info')
|
||||
export class UmbWorkspaceViewContentInfoElement extends UmbLitElement {
|
||||
static styles = [
|
||||
UUITextStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
display: grid;
|
||||
gap: var(--uui-size-layout-1);
|
||||
margin: var(--uui-size-layout-1);
|
||||
grid-template-columns: 1fr 350px;
|
||||
}
|
||||
|
||||
div.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--uui-size-layout-1);
|
||||
}
|
||||
|
||||
//General section
|
||||
|
||||
#general-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.general-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--uui-size-space-1);
|
||||
}
|
||||
|
||||
.general-item:not(:last-child) {
|
||||
margin-bottom: var(--uui-size-space-6);
|
||||
}
|
||||
|
||||
// Link section
|
||||
|
||||
#link-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.link-item {
|
||||
padding: var(--uui-size-space-4) var(--uui-size-space-6);
|
||||
display: grid;
|
||||
grid-template-columns: 75px 1fr;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.link-language {
|
||||
color: var(--uui-color-divider-emphasis);
|
||||
}
|
||||
|
||||
.link-content.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.link-item uui-icon {
|
||||
margin-right: var(--uui-size-space-2);
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.link-item.with-href {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.link-item.with-href:hover {
|
||||
background: var(--uui-color-divider);
|
||||
}
|
||||
|
||||
//History section
|
||||
|
||||
uui-tag uui-icon {
|
||||
margin-right: var(--uui-size-space-1);
|
||||
}
|
||||
|
||||
.log-type {
|
||||
display: flex;
|
||||
gap: var(--uui-size-space-2);
|
||||
}
|
||||
uui-pagination {
|
||||
display: inline-block;
|
||||
}
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: var(--uui-size-space-4);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@state()
|
||||
private _historyList: HistoryNode[] = [
|
||||
{
|
||||
userId: -1,
|
||||
userAvatars: [],
|
||||
userName: 'Lone Iversen',
|
||||
timestamp: 'December 5, 2022 2:59 PM',
|
||||
comment: undefined,
|
||||
entityType: 'Document',
|
||||
logType: 'Save',
|
||||
nodeId: '1058',
|
||||
parameters: undefined,
|
||||
},
|
||||
{
|
||||
userId: -1,
|
||||
userAvatars: [],
|
||||
userName: 'Lone Iversen',
|
||||
timestamp: 'December 5, 2022 2:59 PM',
|
||||
comment: undefined,
|
||||
entityType: 'Document',
|
||||
logType: 'Unpublish',
|
||||
nodeId: '1058',
|
||||
parameters: undefined,
|
||||
},
|
||||
{
|
||||
userId: -1,
|
||||
userAvatars: [],
|
||||
userName: 'Lone Iversen',
|
||||
timestamp: 'December 5, 2022 2:59 PM',
|
||||
comment: undefined,
|
||||
entityType: 'Document',
|
||||
logType: 'Publish',
|
||||
nodeId: '1058',
|
||||
parameters: undefined,
|
||||
},
|
||||
|
||||
{
|
||||
userId: -1,
|
||||
userAvatars: [],
|
||||
userName: 'Lone Iversen',
|
||||
timestamp: 'December 5, 2022 2:59 PM',
|
||||
comment: undefined,
|
||||
entityType: 'Document',
|
||||
logType: 'Save',
|
||||
nodeId: '1058',
|
||||
parameters: undefined,
|
||||
},
|
||||
|
||||
{
|
||||
userId: -1,
|
||||
userAvatars: [],
|
||||
userName: 'Lone Iversen',
|
||||
timestamp: 'December 5, 2022 2:59 PM',
|
||||
comment: undefined,
|
||||
entityType: 'Document',
|
||||
logType: 'Save',
|
||||
nodeId: '1058',
|
||||
parameters: undefined,
|
||||
},
|
||||
];
|
||||
|
||||
@state()
|
||||
private _total?: number;
|
||||
|
||||
@state()
|
||||
private _currentPage = 1;
|
||||
|
||||
@state()
|
||||
private _nodeName = '';
|
||||
|
||||
private _workspaceContext?: UmbWorkspaceEntityContextInterface<DocumentModel>;
|
||||
private itemsPerPage = 10;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -36,6 +201,7 @@ export class UmbWorkspaceViewContentInfoElement extends UmbLitElement {
|
||||
if (!this._workspaceContext) return;
|
||||
|
||||
this._nodeName = 'TBD, with variants this is not as simple.';
|
||||
|
||||
/*
|
||||
this.observe(this._workspaceContext.name, (name) => {
|
||||
this._nodeName = name || '';
|
||||
@@ -43,8 +209,123 @@ export class UmbWorkspaceViewContentInfoElement extends UmbLitElement {
|
||||
*/
|
||||
}
|
||||
|
||||
#onPageChange(event: UUIPaginationEvent) {
|
||||
if (this._currentPage === event.target.current) return;
|
||||
this._currentPage = event.target.current;
|
||||
//TODO: Run endpoint to get next history parts
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<div>Info Workspace View for ${this._nodeName}</div>`;
|
||||
return html`<div class="container">
|
||||
<uui-box headline="Links" style="--uui-box-default-padding: 0;"> ${this.#renderLinksSection()} </uui-box>
|
||||
<uui-box headline="History">
|
||||
<umb-history-list>
|
||||
${repeat(
|
||||
this._historyList,
|
||||
(item) => item.timestamp,
|
||||
(item) => this.#renderHistory(item)
|
||||
)}
|
||||
</umb-history-list>
|
||||
${this.#renderHistoryPagination()}
|
||||
</uui-box>
|
||||
</div>
|
||||
<div class="container">
|
||||
<uui-box headline="General" id="general-section">${this.#renderGeneralSection()}</uui-box>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
#renderLinksSection() {
|
||||
//repeat
|
||||
return html`<div id="link-section">
|
||||
<a href="http://google.com" target="_blank" class="link-item with-href">
|
||||
<span class="link-language">da-DK</span>
|
||||
<span class="link-content"> <uui-icon name="umb:out"></uui-icon>google.com </span>
|
||||
</a>
|
||||
<div class="link-item">
|
||||
<span class="link-language">en-EN</span>
|
||||
<span class="link-content italic"> This document is published but is not in the cache</span>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
#renderGeneralSection() {
|
||||
return html`
|
||||
<div class="general-item">
|
||||
<strong>Status</strong>
|
||||
<span><uui-tag color="positive" look="primary" label="Published">Published</uui-tag></span>
|
||||
</div>
|
||||
<div class="general-item">
|
||||
<strong>Created Date</strong>
|
||||
<span>...</span>
|
||||
</div>
|
||||
<div class="general-item">
|
||||
<strong>Document Type</strong>
|
||||
<span>document type picker?</span>
|
||||
</div>
|
||||
<div class="general-item">
|
||||
<strong>Template</strong>
|
||||
<span>template picker?</span>
|
||||
</div>
|
||||
<div class="general-item">
|
||||
<strong>Id</strong>
|
||||
<span>...</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderHistory(history: HistoryNode) {
|
||||
return html` <umb-history-item .name="${history.userName}" .detail="${history.timestamp}">
|
||||
<span class="log-type">${this.#renderTag(history.logType)} ${this.#renderTagDescription(history.logType)}</span>
|
||||
<uui-button label="Rollback" look="secondary" slot="actions">
|
||||
<uui-icon name="umb:undo"></uui-icon> Rollback
|
||||
</uui-button>
|
||||
</umb-history-item>`;
|
||||
}
|
||||
|
||||
#renderHistoryPagination() {
|
||||
if (!this._total) return nothing;
|
||||
|
||||
const totalPages = Math.ceil(this._total / this.itemsPerPage);
|
||||
|
||||
if (totalPages <= 1) return nothing;
|
||||
|
||||
return html`<div class="pagination">
|
||||
<uui-pagination .total=${totalPages} @change="${this.#onPageChange}"></uui-pagination>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
#renderTag(type?: HistoryLogType) {
|
||||
switch (type) {
|
||||
case 'Publish':
|
||||
return html`<uui-tag look="primary" color="positive" label="Publish">Publish</uui-tag>`;
|
||||
case 'Unpublish':
|
||||
return html`<uui-tag look="primary" color="warning" label="Unpublish">Unpublish</uui-tag>`;
|
||||
case 'Save':
|
||||
return html`<uui-tag look="primary" label="Save">Save</uui-tag>`;
|
||||
case 'ContentVersionEnableCleanup':
|
||||
return html`<uui-tag look="secondary" label="Content Version Enable Cleanup">Save</uui-tag>`;
|
||||
case 'ContentVersionPreventCleanup':
|
||||
return html`<uui-tag look="secondary" label="Content Version Prevent Cleanup">Save</uui-tag>`;
|
||||
default:
|
||||
return 'Could not detech log type';
|
||||
}
|
||||
}
|
||||
|
||||
#renderTagDescription(type?: HistoryLogType, params?: string) {
|
||||
switch (type) {
|
||||
case 'Publish':
|
||||
return html`Content published`;
|
||||
case 'Unpublish':
|
||||
return html`Content unpublished`;
|
||||
case 'Save':
|
||||
return html`Content saved`;
|
||||
case 'ContentVersionEnableCleanup':
|
||||
return html`Cleanup enabled for version: ${params}`;
|
||||
case 'ContentVersionPreventCleanup':
|
||||
return html`Cleanup disabled for version: ${params}`;
|
||||
default:
|
||||
return 'Could not detech log type';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user