Merge pull request #628 from umbraco/feature/create-language

Feature/create language
This commit is contained in:
Jacob Overgaard
2023-04-03 11:19:01 +02:00
committed by GitHub
8 changed files with 80 additions and 23 deletions

View File

@@ -39,8 +39,17 @@ export class UmbResourceController extends UmbController {
*/
static toProblemDetailsModel(error: unknown): ProblemDetailsModel | undefined {
if (error instanceof ApiError) {
const errorDetails = error.body as ProblemDetailsModel;
return errorDetails;
try {
const errorDetails = (
typeof error.body === 'string' ? JSON.parse(error.body) : error.body
) as ProblemDetailsModel;
return errorDetails;
} catch {
return {
title: error.name,
detail: error.message,
};
}
} else if (error instanceof Error) {
return {
title: error.name,

View File

@@ -55,7 +55,6 @@ export class UmbLanguageServerDataSource
name: '',
isDefault: false,
isMandatory: false,
fallbackIsoCode: '',
isoCode: '',
};

View File

@@ -34,7 +34,9 @@ export class UmbLanguageRootTableDeleteColumnLayoutElement extends UmbLitElement
return html`
<umb-dropdown .open="${this._isOpen}" @close=${this.#onClose}>
<uui-button slot="trigger" compact @click=${this.#onClick}><uui-symbol-more></uui-symbol-more></uui-button>
<uui-button label="actions" slot="trigger" compact @click=${this.#onClick}>
<uui-symbol-more></uui-symbol-more>
</uui-button>
<umb-entity-action-list
slot="dropdown"
@executed=${this.#onActionExecuted}

View File

@@ -65,6 +65,7 @@ export class UmbLanguageRootWorkspaceElement extends UmbLitElement {
private _tableItems: Array<UmbTableItem> = [];
#languageRepository = new UmbLanguageRepository(this);
private _cultureNames = new Intl.DisplayNames('en', { type: 'language' });
connectedCallback() {
super.connectedCallback();
@@ -88,7 +89,7 @@ export class UmbLanguageRootWorkspaceElement extends UmbLitElement {
{
columnAlias: 'languageName',
value: {
name: language.name,
name: language.name ? language.name : this._cultureNames.of(language.isoCode ?? ''),
isoCode: language.isoCode,
},
},

View File

@@ -8,8 +8,8 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { LanguageResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UMB_ENTITY_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/context-api';
@customElement('umb-language-workspace-thingy')
export class UmbLanguageWorkspaceThingyElement extends UmbLitElement {
@customElement('umb-language-workspace-edit')
export class UmbLanguageWorkspaceEditElement extends UmbLitElement {
static styles = [
UUITextStyles,
css`
@@ -19,9 +19,23 @@ export class UmbLanguageWorkspaceThingyElement extends UmbLitElement {
gap: var(--uui-size-space-4);
width: 100%;
}
uui-input {
width: 100%;
}
strong {
display: flex;
align-items: center;
}
#footer {
padding: 0 var(--uui-size-layout-1);
}
uui-input:not(:focus) {
border: 1px solid transparent;
}
`,
];
@@ -30,6 +44,9 @@ export class UmbLanguageWorkspaceThingyElement extends UmbLitElement {
@state()
_language?: LanguageResponseModel;
@state()
_isNew = false;
constructor() {
super();
@@ -44,6 +61,9 @@ export class UmbLanguageWorkspaceThingyElement extends UmbLitElement {
this.observe(this.#workspaceContext.data, (data) => {
this._language = data;
});
this.observe(this.#workspaceContext.isNew, (isNew) => {
this._isNew = isNew;
});
}
#handleInput(event: UUIInputEvent) {
@@ -59,19 +79,28 @@ export class UmbLanguageWorkspaceThingyElement extends UmbLitElement {
render() {
return html`<umb-workspace-layout alias="Umb.Workspace.Language">
<div id="header" slot="header">
<uui-button href="/section/settings/workspace/language-root" compact>
<uui-button label="Navigate back" href="section/settings/workspace/language-root" compact>
<uui-icon name="umb:arrow-left"></uui-icon>
</uui-button>
<uui-input value=${ifDefined(this._language?.name)} @input="${this.#handleInput}"></uui-input>
${this._isNew
? html`<strong>Add language</strong>`
: html`<uui-input
label="Language name"
value=${ifDefined(this._language?.name)}
@input="${this.#handleInput}"></uui-input>`}
</div>
<div slot="footer" id="footer">
<a href="section/settings/workspace/language-root">Languages</a> /
${this._isNew ? 'Create' : this._language?.name}
</div>
</umb-workspace-layout>`;
}
}
export default UmbLanguageWorkspaceThingyElement;
export default UmbLanguageWorkspaceEditElement;
declare global {
interface HTMLElementTagNameMap {
'umb-language-workspace-thingy': UmbLanguageWorkspaceThingyElement;
'umb-language-workspace-edit': UmbLanguageWorkspaceEditElement;
}
}

View File

@@ -6,24 +6,33 @@ import { UmbLanguageWorkspaceContext } from './language-workspace.context';
import { UmbRouterSlotInitEvent } from '@umbraco-cms/internal/router';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import './language-workspace-edit.element';
@customElement('umb-language-workspace')
export class UmbLanguageWorkspaceElement extends UmbLitElement {
static styles = [UUITextStyles, css``];
#languageWorkspaceContext = new UmbLanguageWorkspaceContext(this);
#element = document.createElement('umb-language-workspace-edit');
#routerPath? = '';
// TODO: add create route
@state()
_routes = [
{
path: 'edit/:isoCode',
component: () => import('./language-workspace-edit.element'),
component: () => this.#element,
setup: (component: HTMLElement, info: IRoutingInfo) => {
this.#languageWorkspaceContext.load(info.match.params.isoCode);
},
},
{
path: 'create',
component: () => this.#element,
setup: async () => {
this.#languageWorkspaceContext.createScaffold();
},
},
];
render() {

View File

@@ -4,8 +4,8 @@ import { css, html, nothing } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { UmbLanguageWorkspaceContext } from '../../language-workspace.context';
import UmbInputCultureSelectElement from '../../../../../../shared/components/input-culture-select/input-culture-select.element';
import UmbInputLanguagePickerElement from '../../../../../../shared/components/input-language-picker/input-language-picker.element';
import { UmbInputCultureSelectElement } from '../../../../../../shared/components/input-culture-select/input-culture-select.element';
import { UmbInputLanguagePickerElement } from '../../../../../../shared/components/input-language-picker/input-language-picker.element';
import { UmbChangeEvent } from '@umbraco-cms/backoffice/events';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { LanguageResponseModel } from '@umbraco-cms/backoffice/backend-api';
@@ -98,6 +98,11 @@ export class UmbLanguageDetailsWorkspaceViewElement extends UmbLitElement {
const isoCode = target.value.toString();
const cultureName = target.selectedCultureName;
// If there is no cultureName, it was probably an unknown event that triggered the change event, so ignore it.
if (!cultureName) {
return;
}
if (!isoCode) {
// If the isoCode is empty, we reset the value to the original value.
// Provides a way better UX
@@ -143,15 +148,13 @@ export class UmbLanguageDetailsWorkspaceViewElement extends UmbLitElement {
}
render() {
if (!this._language) return nothing;
return html`
<uui-box>
<umb-workspace-property-layout label="Language">
<div slot="editor">
<!-- TODO: disable already created cultures in the select -->
<umb-input-culture-select
value=${ifDefined(this._language.isoCode)}
value=${ifDefined(this._language?.isoCode)}
@change=${this.#handleCultureChange}
?readonly=${this._isNew === false}></umb-input-culture-select>
@@ -163,14 +166,15 @@ export class UmbLanguageDetailsWorkspaceViewElement extends UmbLitElement {
</umb-workspace-property-layout>
<umb-workspace-property-layout label="ISO Code">
<div slot="editor">${this._language.isoCode}</div>
<div slot="editor">${this._language?.isoCode}</div>
</umb-workspace-property-layout>
<umb-workspace-property-layout label="Settings">
<div slot="editor">
<uui-toggle
label="Default language"
?disabled=${this._isDefaultLanguage}
?checked=${this._language.isDefault || false}
?checked=${this._language?.isDefault || false}
@change=${this.#handleDefaultChange}>
<div>
<b>Default language</b>
@@ -178,14 +182,17 @@ export class UmbLanguageDetailsWorkspaceViewElement extends UmbLitElement {
</div>
</uui-toggle>
<!-- TODO: we need a UUI component for this -->
${this._language.isDefault !== this._isDefaultLanguage
${this._language?.isDefault && this._language?.isDefault !== this._isDefaultLanguage
? html`<div id="default-language-warning">
Switching default language may result in default content missing.
</div>`
: nothing}
<hr />
<uui-toggle ?checked=${this._language.isMandatory || false} @change=${this.#handleMandatoryChange}>
<uui-toggle
label="Mandatory language"
?checked=${this._language?.isMandatory || false}
@change=${this.#handleMandatoryChange}>
<div>
<b>Mandatory language</b>
<div>Properties on this language have to be filled out before the node can be published.</div>
@@ -198,7 +205,7 @@ export class UmbLanguageDetailsWorkspaceViewElement extends UmbLitElement {
label="Fallback language"
description="To allow multi-lingual content to fall back to another language if not present in the requested language, select it here.">
<umb-input-language-picker
value=${ifDefined(this._language.fallbackIsoCode === null ? undefined : this._language.fallbackIsoCode)}
value=${ifDefined(this._language?.fallbackIsoCode === null ? undefined : this._language?.fallbackIsoCode)}
slot="editor"
max="1"
@change=${this.#handleFallbackChange}

View File

@@ -19,6 +19,7 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
* @element umb-workspace-layout
* @description
* @slot icon - Slot for icon
* @slot header - Slot for workspace header
* @slot name - Slot for name
* @slot footer - Slot for workspace footer
* @slot actions - Slot for workspace footer actions