This commit is contained in:
Lone Iversen
2022-11-21 16:31:43 +01:00
parent 88bcb7356b
commit c43a5b45f6
5 changed files with 259 additions and 5 deletions

View File

@@ -1,15 +1,155 @@
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
import { css, html, LitElement } from 'lit';
import { customElement } from 'lit/decorators.js';
import { css, html, LitElement, nothing } from 'lit';
import { state, customElement } from 'lit/decorators.js';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { UUIButtonState } from '@umbraco-ui/uui';
import { UmbContextConsumerMixin } from '@umbraco-cms/context-api';
import { UmbNotificationService, UmbNotificationDefaultData } from '@umbraco-cms/services';
import {
ApiError,
CreatedResult,
ModelsBuilder,
ModelsBuilderResource,
ProblemDetails,
} from '@umbraco-cms/backend-api';
import 'src/core/utils/errorbox';
@customElement('umb-dashboard-models-builder')
export class UmbDashboardModelsBuilderElement extends LitElement {
static styles = [UUITextStyles, css``];
export class UmbDashboardModelsBuilderElement extends UmbContextConsumerMixin(LitElement) {
static styles = [
UUITextStyles,
css`
.headline {
display: flex;
justify-content: space-between;
align-items: center;
}
p {
margin-block-start: 0;
margin-block-end: var(--uui-size-space-4);
}
.models-description p {
padding-bottom: var(--uui-size-space-1);
margin-bottom: var(--uui-size-space-1);
}
.models-description ul {
list-style-type: square;
margin: 0;
padding-left: var(--uui-size-layout-1);
}
.error {
padding-top: var(--uui-size-space-5);
font-weight: bold;
color: var(--uui-color-danger);
}
`,
];
private _notificationService?: UmbNotificationService;
@state()
private _modelsBuilder?: ModelsBuilder;
@state()
private _createdResult?: CreatedResult;
@state()
private _buttonStateBuild: UUIButtonState = undefined;
@state()
private _buttonStateReload: UUIButtonState = undefined;
private async _getDashboardData() {
try {
const modelsBuilder = await ModelsBuilderResource.getModelsBuilderDashboard();
this._modelsBuilder = modelsBuilder;
return true;
} catch (e) {
if (e instanceof ApiError) {
const error = e as ProblemDetails;
const data: UmbNotificationDefaultData = {
message: error.message ?? 'Something went wrong',
};
this._notificationService?.peek('danger', { data });
}
return false;
}
}
private async _onGenerateModels() {
this._buttonStateBuild = 'waiting';
const status = await this._postGenerateModels();
this._buttonStateBuild = status ? 'success' : 'failed';
}
private async _postGenerateModels() {
try {
const createdResult = await ModelsBuilderResource.postModelsBuilderBuild();
this._createdResult = createdResult;
return true;
} catch (e) {
if (e instanceof ApiError) {
const error = e as ProblemDetails;
const data: UmbNotificationDefaultData = {
message: error.message ?? 'Model generation failed',
};
this._notificationService?.peek('danger', { data });
}
return false;
}
}
constructor() {
super();
this._getDashboardData();
this.consumeAllContexts(['umbNotificationService'], (instances) => {
this._notificationService = instances['umbNotificationService'];
});
}
private async _onDashboardReload() {
this._buttonStateReload = 'waiting';
const status = await this._getDashboardData();
this._buttonStateReload = status ? 'success' : 'failed';
}
render() {
return html`
<uui-box>
<h1>Models Builder</h1>
<div class="headline" slot="headline">
<strong>Models Builder</strong>
<uui-button .state="${this._buttonStateReload}" look="secondary" @click="${this._onDashboardReload}">
Reload
</uui-button>
</div>
<p>Version: ${this._modelsBuilder?.version}</p>
<div class="models-description">
<p>${unsafeHTML(this._modelsBuilder?.modelsNamespace)}</p>
</div>
${this._modelsBuilder?.outOfDateModels === true
? html`<p>Models are <strong>out of date</strong></p>`
: nothing}
${this._modelsBuilder?.canGenerate === true
? html` <uui-button
.state="${this._buttonStateBuild}"
look="primary"
label="Generate models"
@click="${this._onGenerateModels}">
Generate models
</uui-button>`
: nothing}
${this._modelsBuilder?.lastError
? html`<p class="error">Last generation failed with the following error:</p>
<uui-error-box>${this._modelsBuilder.lastError}</uui-error-box>`
: nothing}
</uui-box>
`;
}

View File

@@ -12,6 +12,7 @@ import { handlers as telemetryHandlers } from './domains/telemetry.handlers';
import { handlers as usersHandlers } from './domains/users.handlers';
import { handlers as userGroupsHandlers } from './domains/user-groups.handlers';
import { handlers as examineManagementHandlers } from './domains/examine-management.handlers';
import { handlers as modelsBuilderHandlers } from './domains/modelsbuilder.handlers';
const handlers = [
serverHandlers.serverVersionHandler,
@@ -28,6 +29,7 @@ const handlers = [
...usersHandlers,
...userGroupsHandlers,
...examineManagementHandlers,
...modelsBuilderHandlers,
];
switch (import.meta.env.VITE_UMBRACO_INSTALL_STATUS) {

View File

@@ -0,0 +1,50 @@
import { rest } from 'msw';
import { umbracoPath } from '@umbraco-cms/utils';
import { CreatedResult, ModelsBuilder, OutOfDateStatus } from '@umbraco-cms/backend-api';
export const handlers = [
rest.post(umbracoPath('/models-builder/build'), 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),
ctx.json<CreatedResult>({})
);
}),
rest.get(umbracoPath('/models-builder/dashboard'), async (_req, res, ctx) => {
return res(
ctx.status(200),
ctx.json<ModelsBuilder>({
mode: undefined,
canGenerate: true,
outOfDateModels: true,
lastError: `[plugin:vite:import-analysis] Missing "./directives/unsafe-htl.js" export in "lit" package
C:/Users/Umbraco/Documents/Umbraco.CMS.Backoffice/src/backoffice/dashboards/models-builder/dashboard-models-builder.element.ts
at bail (file:///C:/Users/Umbraco/Documents/Umbraco.CMS.Backoffice/node_modules/vite/dist/node/chunks/dep-67e7f8ab.js:32675:8)
at resolve (file:///C:/Users/Umbraco/Documents/Umbraco.CMS.Backoffice/node_modules/vite/dist/node/chunks/dep-67e7f8ab.js:32752:10)
at resolveExports (file:///C:/Users/Umbraco/Documents/Umbraco.CMS.Backoffice/node_modules/vite/dist/node/chunks/dep-67e7f8ab.js:34128:12)
at resolveDeepImport (file:///C:/Users/Umbraco/Documents/Umbraco.CMS.Backoffice/node_modules/vite/dist/node/chunks/dep-67e7f8ab.js:34146:31)
at tryNodeResolve (file:///C:/Users/Umbraco/Documents/Umbraco.CMS.Backoffice/node_modules/vite/dist/node/chunks/dep-67e7f8ab.js:33838:20)
at Context.resolveId (file:///C:/Users/Umbraco/Documents/Umbraco.CMS.Backoffice/node_modules/vite/dist/node/chunks/dep-67e7f8ab.js:33598:28)
at async Object.resolveId (file:///C:/Users/Umbraco/Documents/Umbraco.CMS.Backoffice/node_modules/vite/dist/node/chunks/dep-67e7f8ab.js:40156:32)
at async TransformContext.resolve (file:///C:/Users/Umbraco/Documents/Umbraco.CMS.Backoffice/node_modules/vite/dist/node/chunks/dep-67e7f8ab.js:39921:23)
at async normalizeUrl (file:///C:/Users/Umbraco/Documents/Umbraco.CMS.Backoffice/node_modules/vite/dist/node/chunks/dep-67e7f8ab.js:36831:34)
at async TransformContext.transform (file:///C:/Users/Umbraco/Documents/Umbraco.CMS.Backoffice/node_modules/vit`,
version: '13.0.0',
modelsNamespace:
"<p>ModelsBuilder is enabled, with the following configuration:</p><ul><li>The <strong>models mode</strong> is 'InMemoryAuto'. Strongly typed models are re-generated on startup and anytime schema changes (i.e. Content Type) are made. No recompilation necessary but the generated models are not available to code outside of Razor.</li><li>Models namespace is Umbraco.Cms.Web.Common.PublishedModels.</li><li>Tracking of <strong>out-of-date models</strong> is not enabled.</li></ul>",
trackingOutOfDateModels: true,
})
);
}),
rest.get(umbracoPath('/models-builder/status'), async (_req, res, ctx) => {
return res(
// Respond with a 200 status code
ctx.status(200),
ctx.json<OutOfDateStatus>({})
);
}),
];

View File

@@ -11,6 +11,7 @@ import { handlers as telemetryHandlers } from './domains/telemetry.handlers';
import { handlers as treeHandlers } from './domains/entity.handlers';
import { handlers as examineManagementHandlers } from './domains/examine-management.handlers';
import { handlers as modelsBuilderHandlers } from './domains/modelsbuilder.handlers';
export const handlers = [
serverHandlers.serverRunningHandler,
@@ -27,4 +28,5 @@ export const handlers = [
...publishedStatusHandlers,
...treeHandlers,
...examineManagementHandlers,
...modelsBuilderHandlers,
];

View File

@@ -0,0 +1,60 @@
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
import { css, html, LitElement } from 'lit';
import { customElement } from 'lit/decorators.js';
/**
* A simple styled box for showing code-based error messages.
* max-height is 500px
*
* @slot the message
*
*/
@customElement('uui-error-box')
export class UUIErrorBox extends LitElement {
static styles = [
UUITextStyles,
css`
:host {
display: block;
font-family: monospace;
}
#container {
border: 2px solid var(--uui-color-divider-emphasis);
color: var(--uui-color-text-alt);
background-color: var(--uui-color-divider-standalone);
padding: var(--uui-size-space-2);
border-radius: var(--uui-border-radius);
line-height: var(--uui-size-10);
}
:host uui-scroll-container {
max-height: 500px;
}
pre {
display: inline-block;
overflow-wrap: break-word;
word-wrap: break-word;
word-break: break-all;
line-break: strict;
hyphens: none;
-webkit-hyphens: none;
-moz-hyphens: none;
}
`,
];
render() {
return html`<div id="container">
<uui-scroll-container>
<pre><slot></slot></pre>
</uui-scroll-container>
</div> `;
}
}
declare global {
interface HTMLElementTagNameMap {
'uui-error-box': UUIErrorBox;
}
}