web/admin: reworked sync status card (#13625) * reworked sync status * update imports * add story and fix import * format --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io> Co-authored-by: Jens L. <jens@goauthentik.io>
This commit is contained in:
committed by
GitHub
parent
28cc75af29
commit
1a727b9ea0
@ -94,7 +94,7 @@ export class ApplicationEntitlementsPage extends Table<ApplicationEntitlement> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderExpanded(item: ApplicationEntitlement): TemplateResult {
|
renderExpanded(item: ApplicationEntitlement): TemplateResult {
|
||||||
return html` <td></td>
|
return html`<td></td>
|
||||||
<td role="cell" colspan="4">
|
<td role="cell" colspan="4">
|
||||||
<div class="pf-c-table__expandable-row-content">
|
<div class="pf-c-table__expandable-row-content">
|
||||||
<div class="pf-c-content">
|
<div class="pf-c-content">
|
||||||
|
|||||||
@ -7,10 +7,10 @@ import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
|||||||
import "@goauthentik/components/events/ObjectChangelog";
|
import "@goauthentik/components/events/ObjectChangelog";
|
||||||
import { AKElement } from "@goauthentik/elements/Base";
|
import { AKElement } from "@goauthentik/elements/Base";
|
||||||
import "@goauthentik/elements/Markdown";
|
import "@goauthentik/elements/Markdown";
|
||||||
import "@goauthentik/elements/SyncStatusCard";
|
|
||||||
import "@goauthentik/elements/Tabs";
|
import "@goauthentik/elements/Tabs";
|
||||||
import "@goauthentik/elements/buttons/ActionButton";
|
import "@goauthentik/elements/buttons/ActionButton";
|
||||||
import "@goauthentik/elements/buttons/ModalButton";
|
import "@goauthentik/elements/buttons/ModalButton";
|
||||||
|
import "@goauthentik/elements/sync/SyncStatusCard";
|
||||||
|
|
||||||
import { msg } from "@lit/localize";
|
import { msg } from "@lit/localize";
|
||||||
import { CSSResult, PropertyValues, TemplateResult, html } from "lit";
|
import { CSSResult, PropertyValues, TemplateResult, html } from "lit";
|
||||||
|
|||||||
@ -9,10 +9,10 @@ import "@goauthentik/components/events/ObjectChangelog";
|
|||||||
import MDSCIMProvider from "@goauthentik/docs/add-secure-apps/providers/scim/index.md";
|
import MDSCIMProvider from "@goauthentik/docs/add-secure-apps/providers/scim/index.md";
|
||||||
import { AKElement } from "@goauthentik/elements/Base";
|
import { AKElement } from "@goauthentik/elements/Base";
|
||||||
import "@goauthentik/elements/Markdown";
|
import "@goauthentik/elements/Markdown";
|
||||||
import "@goauthentik/elements/SyncStatusCard";
|
|
||||||
import "@goauthentik/elements/Tabs";
|
import "@goauthentik/elements/Tabs";
|
||||||
import "@goauthentik/elements/buttons/ActionButton";
|
import "@goauthentik/elements/buttons/ActionButton";
|
||||||
import "@goauthentik/elements/buttons/ModalButton";
|
import "@goauthentik/elements/buttons/ModalButton";
|
||||||
|
import "@goauthentik/elements/sync/SyncStatusCard";
|
||||||
|
|
||||||
import { msg } from "@lit/localize";
|
import { msg } from "@lit/localize";
|
||||||
import { CSSResult, PropertyValues, TemplateResult, html } from "lit";
|
import { CSSResult, PropertyValues, TemplateResult, html } from "lit";
|
||||||
|
|||||||
@ -8,11 +8,11 @@ import MDSourceKerberosBrowser from "@goauthentik/docs/users-sources/sources/pro
|
|||||||
import { AKElement } from "@goauthentik/elements/Base";
|
import { AKElement } from "@goauthentik/elements/Base";
|
||||||
import "@goauthentik/elements/CodeMirror";
|
import "@goauthentik/elements/CodeMirror";
|
||||||
import "@goauthentik/elements/Markdown";
|
import "@goauthentik/elements/Markdown";
|
||||||
import "@goauthentik/elements/SyncStatusCard";
|
|
||||||
import "@goauthentik/elements/Tabs";
|
import "@goauthentik/elements/Tabs";
|
||||||
import "@goauthentik/elements/buttons/ActionButton";
|
import "@goauthentik/elements/buttons/ActionButton";
|
||||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||||
import "@goauthentik/elements/forms/ModalForm";
|
import "@goauthentik/elements/forms/ModalForm";
|
||||||
|
import "@goauthentik/elements/sync/SyncStatusCard";
|
||||||
|
|
||||||
import { msg } from "@lit/localize";
|
import { msg } from "@lit/localize";
|
||||||
import { CSSResult, TemplateResult, html } from "lit";
|
import { CSSResult, TemplateResult, html } from "lit";
|
||||||
|
|||||||
@ -6,11 +6,11 @@ import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
|||||||
import "@goauthentik/components/events/ObjectChangelog";
|
import "@goauthentik/components/events/ObjectChangelog";
|
||||||
import { AKElement } from "@goauthentik/elements/Base";
|
import { AKElement } from "@goauthentik/elements/Base";
|
||||||
import "@goauthentik/elements/CodeMirror";
|
import "@goauthentik/elements/CodeMirror";
|
||||||
import "@goauthentik/elements/SyncStatusCard";
|
|
||||||
import "@goauthentik/elements/Tabs";
|
import "@goauthentik/elements/Tabs";
|
||||||
import "@goauthentik/elements/buttons/ActionButton";
|
import "@goauthentik/elements/buttons/ActionButton";
|
||||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||||
import "@goauthentik/elements/forms/ModalForm";
|
import "@goauthentik/elements/forms/ModalForm";
|
||||||
|
import "@goauthentik/elements/sync/SyncStatusCard";
|
||||||
|
|
||||||
import { msg } from "@lit/localize";
|
import { msg } from "@lit/localize";
|
||||||
import { CSSResult, TemplateResult, html } from "lit";
|
import { CSSResult, TemplateResult, html } from "lit";
|
||||||
|
|||||||
157
web/src/elements/sync/SyncStatusCard.stories.ts
Normal file
157
web/src/elements/sync/SyncStatusCard.stories.ts
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
import type { Meta, StoryObj } from "@storybook/web-components";
|
||||||
|
|
||||||
|
import { html } from "lit";
|
||||||
|
|
||||||
|
import { LogLevelEnum, SyncStatus, SystemTaskStatusEnum } from "@goauthentik/api";
|
||||||
|
|
||||||
|
import "./SyncStatusCard";
|
||||||
|
|
||||||
|
const metadata: Meta<SyncStatus> = {
|
||||||
|
title: "Elements/<ak-sync-status-card>",
|
||||||
|
component: "ak-sync-status-card",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default metadata;
|
||||||
|
|
||||||
|
export const Running: StoryObj = {
|
||||||
|
args: {
|
||||||
|
status: {
|
||||||
|
isRunning: true,
|
||||||
|
tasks: [],
|
||||||
|
} as SyncStatus,
|
||||||
|
},
|
||||||
|
// @ts-ignore
|
||||||
|
render: ({ status }: SyncStatus) => {
|
||||||
|
return html` <div style="background-color: #f0f0f0; padding: 1rem;">
|
||||||
|
<ak-sync-status-card
|
||||||
|
.fetch=${async () => {
|
||||||
|
return status;
|
||||||
|
}}
|
||||||
|
></ak-sync-status-card>
|
||||||
|
</div>`;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SingleTask: StoryObj = {
|
||||||
|
args: {
|
||||||
|
status: {
|
||||||
|
isRunning: false,
|
||||||
|
tasks: [
|
||||||
|
{
|
||||||
|
uuid: "9ff42169-8249-4b67-ae3d-e455d822de2b",
|
||||||
|
name: "Single task",
|
||||||
|
fullName: "foo:bar:baz",
|
||||||
|
status: SystemTaskStatusEnum.Successful,
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
logger: "foo",
|
||||||
|
event: "bar",
|
||||||
|
attributes: {
|
||||||
|
foo: "bar",
|
||||||
|
},
|
||||||
|
timestamp: new Date(),
|
||||||
|
logLevel: LogLevelEnum.Info,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
description: "foo",
|
||||||
|
startTimestamp: new Date(),
|
||||||
|
finishTimestamp: new Date(),
|
||||||
|
duration: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as SyncStatus,
|
||||||
|
},
|
||||||
|
// @ts-ignore
|
||||||
|
render: ({ status }: SyncStatus) => {
|
||||||
|
return html` <div style="background-color: #f0f0f0; padding: 1rem;">
|
||||||
|
<ak-sync-status-card
|
||||||
|
.fetch=${async () => {
|
||||||
|
return status;
|
||||||
|
}}
|
||||||
|
></ak-sync-status-card>
|
||||||
|
</div>`;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MultipleTasks: StoryObj = {
|
||||||
|
args: {
|
||||||
|
status: {
|
||||||
|
isRunning: false,
|
||||||
|
tasks: [
|
||||||
|
{
|
||||||
|
uuid: "9ff42169-8249-4b67-ae3d-e455d822de2b",
|
||||||
|
name: "Single task",
|
||||||
|
fullName: "foo:bar:baz",
|
||||||
|
status: SystemTaskStatusEnum.Successful,
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
logger: "foo",
|
||||||
|
event: "bar",
|
||||||
|
attributes: {
|
||||||
|
foo: "bar",
|
||||||
|
},
|
||||||
|
timestamp: new Date(),
|
||||||
|
logLevel: LogLevelEnum.Info,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
description: "foo",
|
||||||
|
startTimestamp: new Date(),
|
||||||
|
finishTimestamp: new Date(),
|
||||||
|
duration: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: "9ff42169-8249-4b67-ae3d-e455d822de2b",
|
||||||
|
name: "Single task",
|
||||||
|
fullName: "foo:bar:baz",
|
||||||
|
status: SystemTaskStatusEnum.Successful,
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
logger: "foo",
|
||||||
|
event: "bar",
|
||||||
|
attributes: {
|
||||||
|
foo: "bar",
|
||||||
|
},
|
||||||
|
timestamp: new Date(),
|
||||||
|
logLevel: LogLevelEnum.Info,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
description: "foo",
|
||||||
|
startTimestamp: new Date(),
|
||||||
|
finishTimestamp: new Date(),
|
||||||
|
duration: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
uuid: "9ff42169-8249-4b67-ae3d-e455d822de2b",
|
||||||
|
name: "Single task",
|
||||||
|
fullName: "foo:bar:baz",
|
||||||
|
status: SystemTaskStatusEnum.Successful,
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
logger: "foo",
|
||||||
|
event: "bar",
|
||||||
|
attributes: {
|
||||||
|
foo: "bar",
|
||||||
|
},
|
||||||
|
timestamp: new Date(),
|
||||||
|
logLevel: LogLevelEnum.Info,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
description: "foo",
|
||||||
|
startTimestamp: new Date(),
|
||||||
|
finishTimestamp: new Date(),
|
||||||
|
duration: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as SyncStatus,
|
||||||
|
},
|
||||||
|
// @ts-ignore
|
||||||
|
render: ({ status }: SyncStatus) => {
|
||||||
|
return html` <div style="background-color: #f0f0f0; padding: 1rem;">
|
||||||
|
<ak-sync-status-card
|
||||||
|
.fetch=${async () => {
|
||||||
|
return status;
|
||||||
|
}}
|
||||||
|
></ak-sync-status-card>
|
||||||
|
</div>`;
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -3,17 +3,92 @@ import { getRelativeTime } from "@goauthentik/common/utils";
|
|||||||
import "@goauthentik/components/ak-status-label";
|
import "@goauthentik/components/ak-status-label";
|
||||||
import { AKElement } from "@goauthentik/elements/Base";
|
import { AKElement } from "@goauthentik/elements/Base";
|
||||||
import "@goauthentik/elements/EmptyState";
|
import "@goauthentik/elements/EmptyState";
|
||||||
|
import "@goauthentik/elements/buttons/ActionButton";
|
||||||
import "@goauthentik/elements/events/LogViewer";
|
import "@goauthentik/elements/events/LogViewer";
|
||||||
|
import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table";
|
||||||
|
|
||||||
import { msg, str } from "@lit/localize";
|
import { msg } from "@lit/localize";
|
||||||
import { CSSResult, TemplateResult, html, nothing } from "lit";
|
import { CSSResult, TemplateResult, css, html } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators.js";
|
import { customElement, property, state } from "lit/decorators.js";
|
||||||
|
|
||||||
import PFCard from "@patternfly/patternfly/components/Card/card.css";
|
import PFCard from "@patternfly/patternfly/components/Card/card.css";
|
||||||
|
import PFTable from "@patternfly/patternfly/components/Table/table.css";
|
||||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||||
|
|
||||||
import { SyncStatus, SystemTask, SystemTaskStatusEnum } from "@goauthentik/api";
|
import { SyncStatus, SystemTask, SystemTaskStatusEnum } from "@goauthentik/api";
|
||||||
|
|
||||||
|
@customElement("ak-sync-status-table")
|
||||||
|
export class SyncStatusTable extends Table<SystemTask> {
|
||||||
|
@property({ attribute: false })
|
||||||
|
tasks: SystemTask[] = [];
|
||||||
|
|
||||||
|
expandable = true;
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return super.styles.concat(css`
|
||||||
|
code:not(:last-of-type)::after {
|
||||||
|
content: "-";
|
||||||
|
margin: 0 0.25rem;
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async apiEndpoint(): Promise<PaginatedResponse<SystemTask>> {
|
||||||
|
return {
|
||||||
|
pagination: {
|
||||||
|
next: 0,
|
||||||
|
previous: 0,
|
||||||
|
count: this.tasks.length,
|
||||||
|
current: 1,
|
||||||
|
totalPages: 1,
|
||||||
|
startIndex: 0,
|
||||||
|
endIndex: this.tasks.length,
|
||||||
|
},
|
||||||
|
results: this.tasks,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
columns(): TableColumn[] {
|
||||||
|
return [
|
||||||
|
new TableColumn(msg("Task")),
|
||||||
|
new TableColumn(msg("Status")),
|
||||||
|
new TableColumn(msg("Finished")),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
row(item: SystemTask): TemplateResult[] {
|
||||||
|
const nameParts = item.fullName.split(":");
|
||||||
|
nameParts.shift();
|
||||||
|
return [
|
||||||
|
html`<div>${item.name}</div>
|
||||||
|
<small>${nameParts.map((part) => html`<code>${part}</code>`)}</small>`,
|
||||||
|
html`<ak-status-label
|
||||||
|
?good=${item.status === SystemTaskStatusEnum.Successful}
|
||||||
|
good-label=${msg("Finished successfully")}
|
||||||
|
bad-label=${msg("Finished with errors")}
|
||||||
|
></ak-status-label>`,
|
||||||
|
html`<div>${getRelativeTime(item.finishTimestamp)}</div>
|
||||||
|
<small>${item.finishTimestamp.toLocaleString()}</small>`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
renderExpanded(item: SystemTask): TemplateResult {
|
||||||
|
return html`<td role="cell" colspan="4">
|
||||||
|
<div class="pf-c-table__expandable-row-content">
|
||||||
|
<ak-log-viewer .logs=${item?.messages}></ak-log-viewer>
|
||||||
|
</div>
|
||||||
|
</td>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderToolbarContainer() {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTablePagination() {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@customElement("ak-sync-status-card")
|
@customElement("ak-sync-status-card")
|
||||||
export class SyncStatusCard extends AKElement {
|
export class SyncStatusCard extends AKElement {
|
||||||
@state()
|
@state()
|
||||||
@ -29,7 +104,7 @@ export class SyncStatusCard extends AKElement {
|
|||||||
triggerSync!: () => Promise<unknown>;
|
triggerSync!: () => Promise<unknown>;
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [PFBase, PFCard];
|
return [PFBase, PFCard, PFTable];
|
||||||
}
|
}
|
||||||
|
|
||||||
firstUpdated() {
|
firstUpdated() {
|
||||||
@ -40,25 +115,6 @@ export class SyncStatusCard extends AKElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSyncTask(task: SystemTask): TemplateResult {
|
|
||||||
return html`<li>
|
|
||||||
${(this.syncState?.tasks || []).length > 1 ? html`<span>${task.name}</span>` : nothing}
|
|
||||||
<span
|
|
||||||
><ak-status-label
|
|
||||||
?good=${task.status === SystemTaskStatusEnum.Successful}
|
|
||||||
good-label=${msg("Finished successfully")}
|
|
||||||
bad-label=${msg("Finished with errors")}
|
|
||||||
></ak-status-label
|
|
||||||
></span>
|
|
||||||
<span
|
|
||||||
>${msg(
|
|
||||||
str`Finished ${getRelativeTime(task.finishTimestamp)} (${task.finishTimestamp.toLocaleString()})`,
|
|
||||||
)}</span
|
|
||||||
>
|
|
||||||
<ak-log-viewer .logs=${task?.messages}></ak-log-viewer>
|
|
||||||
</li> `;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderSyncStatus(): TemplateResult {
|
renderSyncStatus(): TemplateResult {
|
||||||
if (this.loading) {
|
if (this.loading) {
|
||||||
return html`<ak-empty-state ?loading=${true}></ak-empty-state>`;
|
return html`<ak-empty-state ?loading=${true}></ak-empty-state>`;
|
||||||
@ -72,13 +128,7 @@ export class SyncStatusCard extends AKElement {
|
|||||||
if (this.syncState.tasks.length < 1) {
|
if (this.syncState.tasks.length < 1) {
|
||||||
return html`${msg("Not synced yet.")}`;
|
return html`${msg("Not synced yet.")}`;
|
||||||
}
|
}
|
||||||
return html`
|
return html`<ak-sync-status-table .tasks=${this.syncState.tasks}></ak-sync-status-table>`;
|
||||||
<ul class="pf-c-list">
|
|
||||||
${this.syncState.tasks.map((task) => {
|
|
||||||
return this.renderSyncTask(task);
|
|
||||||
})}
|
|
||||||
</ul>
|
|
||||||
`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): TemplateResult {
|
render(): TemplateResult {
|
||||||
@ -120,6 +170,7 @@ export class SyncStatusCard extends AKElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
|
"ak-sync-status-table": SyncStatusTable;
|
||||||
"ak-sync-status-card": SyncStatusCard;
|
"ak-sync-status-card": SyncStatusCard;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user