Merge pull request #195 from umbraco/feature/published-dashboard

Feature/published dashboard
This commit is contained in:
Jacob Overgaard
2022-10-07 12:26:58 +02:00
committed by GitHub
7 changed files with 214 additions and 15 deletions

View File

@@ -194,6 +194,35 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetails'
/published-cache/rebuild:
post:
operationId: PublishedCacheRebuild
parameters: []
responses:
'201':
description: 201 response
'400':
description: 400 response
content:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetails'
/published-cache/collect:
get:
operationId: PublishedCacheCollect
responses:
'200':
description: 200 response
content:
application/json:
schema:
type: string
default:
description: default response
content:
application/json:
schema:
$ref: '#/components/schemas/ProblemDetails'
/server/status:
get:
operationId: GetStatus

View File

@@ -37,6 +37,12 @@ export interface paths {
"/published-cache/reload": {
post: operations["PublishedCacheReload"];
};
"/published-cache/rebuild": {
post: operations["PublishedCacheRebuild"];
};
"/published-cache/collect": {
get: operations["PublishedCacheCollect"];
};
"/server/status": {
get: operations["GetStatus"];
};
@@ -575,6 +581,35 @@ export interface operations {
};
};
};
PublishedCacheRebuild: {
parameters: {};
responses: {
/** 201 response */
201: unknown;
/** 400 response */
400: {
content: {
"application/json": components["schemas"]["ProblemDetails"];
};
};
};
};
PublishedCacheCollect: {
responses: {
/** 200 response */
200: {
content: {
"application/json": string;
};
};
/** default response */
default: {
content: {
"application/json": components["schemas"]["ProblemDetails"];
};
};
};
};
GetStatus: {
responses: {
/** 200 response */

View File

@@ -3,8 +3,14 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
import { css, html, LitElement } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { getPublishedCacheStatus, postPublishedCacheReload } from '../../../core/api/fetcher';
import {
getPublishedCacheStatus,
postPublishedCacheReload,
postPublishedCacheRebuild,
getPublishedCacheCollect,
} from '../../../core/api/fetcher';
import { UmbContextConsumerMixin } from '../../../core/context';
import { UmbModalService } from '../../../core/services/modal';
import { UmbNotificationService } from '../../../core/services/notification';
import { UmbNotificationDefaultData } from '../../../core/services/notification/layouts/default';
@@ -28,7 +34,17 @@ export class UmbDashboardPublishedStatusElement extends UmbContextConsumerMixin(
@state()
private _buttonState: UUIButtonState = undefined;
@state()
private _buttonStateReload: UUIButtonState = undefined;
@state()
private _buttonStateRebuild: UUIButtonState = undefined;
@state()
private _buttonStateCollect: UUIButtonState = undefined;
private _notificationService?: UmbNotificationService;
private _modalService?: UmbModalService;
constructor() {
super();
@@ -36,14 +52,18 @@ export class UmbDashboardPublishedStatusElement extends UmbContextConsumerMixin(
this.consumeContext('umbNotificationService', (notificationService: UmbNotificationService) => {
this._notificationService = notificationService;
});
this.consumeContext('umbModalService', (modalService: UmbModalService) => {
this._modalService = modalService;
});
}
connectedCallback() {
super.connectedCallback();
this._getPublishedStatus();
}
// Refresh
private async _getPublishedStatus() {
try {
const { data } = await getPublishedCacheStatus({});
@@ -56,14 +76,23 @@ export class UmbDashboardPublishedStatusElement extends UmbContextConsumerMixin(
}
}
}
private async _onRefreshCacheHandler() {
this._buttonState = 'waiting';
await this._getPublishedStatus();
this._buttonState = 'success';
}
//Reload
private async _reloadMemoryCache() {
this._buttonStateReload = 'waiting';
this._buttonState = 'waiting';
try {
await postPublishedCacheReload({});
this._buttonStateReload = 'success';
this._getPublishedStatus();
this._buttonState = 'success';
} catch (e) {
this._buttonStateReload = 'failed';
this._buttonState = 'failed';
if (e instanceof postPublishedCacheReload.Error) {
const error = e.getActualType();
@@ -72,17 +101,62 @@ export class UmbDashboardPublishedStatusElement extends UmbContextConsumerMixin(
}
}
}
private async _onReloadCacheHandler() {
await undefined;
const modalHandler = this._modalService?.confirm({
headline: 'Reload',
content: html` Trigger a in-memory and local file cache reload on all servers. `,
color: 'danger',
confirmLabel: 'Continue',
});
modalHandler?.onClose().then(({ confirmed }: any) => {
if (confirmed) this._reloadMemoryCache();
});
}
// Rebuild
private async _rebuildDatabaseCache() {
this._buttonStateRebuild = 'waiting';
try {
await postPublishedCacheRebuild({});
this._buttonStateRebuild = 'success';
} catch (e) {
this._buttonStateRebuild = 'failed';
if (e instanceof postPublishedCacheRebuild.Error) {
const error = e.getActualType();
const data: UmbNotificationDefaultData = { message: error.data.detail ?? 'Something went wrong' };
this._notificationService?.peek('danger', { data });
}
}
}
private async _onRebuildCacheHandler() {
await undefined;
const modalHandler = this._modalService?.confirm({
headline: 'Rebuild',
content: html` Rebuild content in cmsContentNu database table. Expensive.`,
color: 'danger',
confirmLabel: 'Continue',
});
modalHandler?.onClose().then(({ confirmed }: any) => {
if (confirmed) this._rebuildDatabaseCache();
});
}
//Collect
private async _cacheCollect() {
try {
await getPublishedCacheCollect({});
this._buttonStateCollect = 'success';
} catch (e) {
this._buttonStateCollect = 'failed';
if (e instanceof getPublishedCacheCollect.Error) {
const error = e.getActualType();
const data: UmbNotificationDefaultData = { message: error.data.detail ?? 'Something went wrong' };
this._notificationService?.peek('danger', { data });
}
}
}
private async _onSnapshotCacheHandler() {
await undefined;
this._buttonStateCollect = 'waiting';
await this._cacheCollect();
}
render() {
@@ -106,7 +180,12 @@ export class UmbDashboardPublishedStatusElement extends UmbContextConsumerMixin(
been properly refreshed, after some events triggered—which would indicate a minor Umbraco issue. (note:
triggers the reload on all servers in an LB environment).
</p>
<uui-button type="button" look="primary" color="danger" @click=${this._onReloadCacheHandler}
<uui-button
type="button"
look="primary"
color="danger"
@click=${this._onReloadCacheHandler}
.state=${this._buttonStateReload}
>Reload Memory Cache</uui-button
>
</uui-box>
@@ -117,7 +196,12 @@ export class UmbDashboardPublishedStatusElement extends UmbContextConsumerMixin(
expensive. Use it when reloading is not enough, and you think that the database cache has not been properly
generated—which would indicate some critical Umbraco issue.
</p>
<uui-button type="button" look="primary" color="danger" @click=${this._onRebuildCacheHandler}
<uui-button
type="button"
look="primary"
color="danger"
@click=${this._onRebuildCacheHandler}
.state=${this._buttonStateRebuild}
>Rebuild Database Cache</uui-button
>
</uui-box>
@@ -127,7 +211,12 @@ export class UmbDashboardPublishedStatusElement extends UmbContextConsumerMixin(
This button lets you trigger a NuCache snapshots collection (after running a fullCLR GC). Unless you know what
that means, you probably do not need to use it.
</p>
<uui-button type="button" look="primary" color="danger" @click=${this._onSnapshotCacheHandler}
<uui-button
type="button"
look="primary"
color="danger"
@click=${this._onSnapshotCacheHandler}
.state=${this._buttonStateCollect}
>Snapshot Internal Cache</uui-button
>
</uui-box>

View File

@@ -25,16 +25,17 @@ export class UmbSectionDashboards extends UmbContextConsumerMixin(LitElement) {
height: 70px;
}
#scroll-container {
height: calc(100vh - 70px - 60px); // TODO: This is a temporary fix to get scrolling to work
// changed it so the height is correct but the fix is still not ideal. the 70px and 60px are the height of the blue top bar and the dashboard menu. Need a better solution still.
}
#router-slot {
width: 100%;
box-sizing: border-box;
padding: var(--uui-size-space-5);
display: block;
}
#scroll-container {
height: 500px; // TODO: This is a temporary fix to get scrolling to work
}
`,
];

View File

@@ -38,4 +38,6 @@ export const getPropertyEditorConfig = fetcher
.create();
export const getPublishedCacheStatus = fetcher.path('/published-cache/status').method('get').create();
export const postPublishedCacheReload = fetcher.path('/published-cache/reload').method('post').create();
export const postPublishedCacheRebuild = fetcher.path('/published-cache/rebuild').method('post').create();
export const getPublishedCacheCollect = fetcher.path('/published-cache/collect').method('get').create();

View File

@@ -18,7 +18,23 @@ export const handlers = [
return res(
// Respond with a 200 status code
ctx.status(201)
ctx.status(200)
);
}),
rest.post(umbracoPath('/published-cache/rebuild'), async (_req, res, ctx) => {
await new Promise((resolve) => setTimeout(resolve, (Math.random() + 1) * 1000)); // simulate a delay of 1-2 seconds
return res(
// Respond with a 200 status code
ctx.status(200)
);
}),
rest.get(umbracoPath('/published-cache/collect'), (_req, res, ctx) => {
return res(
// Respond with a 200 status code
ctx.status(200)
);
}),
];

View File

@@ -28,3 +28,30 @@ export class PublishedCacheReload {
@response({ status: 400 })
badRequest(@body body: ProblemDetails) {}
}
@endpoint({
method: 'POST',
path: '/published-cache/rebuild',
})
export class PublishedCacheRebuild {
@request
request() {}
@response({ status: 201 })
success() {}
@response({ status: 400 })
badRequest(@body body: ProblemDetails) {}
}
@endpoint({
method: 'GET',
path: '/published-cache/collect',
})
export class PublishedCacheCollect {
@response({ status: 200 })
success(@body body: string) {}
@defaultResponse
default(@body body: ProblemDetails) {}
}