Merge pull request #890 from umbraco/feature/dictionary-update
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbDictionaryData } from '../data/dictionary.data.js';
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
import {
|
||||
ImportDictionaryRequestModel,
|
||||
DictionaryOverviewResponseModel,
|
||||
@@ -48,7 +49,7 @@ const overviewData: Array<DictionaryOverviewResponseModel> = [
|
||||
|
||||
// TODO: add schema
|
||||
export const handlers = [
|
||||
rest.get('/umbraco/management/api/v1/dictionary/:id', (req, res, ctx) => {
|
||||
rest.get(umbracoPath('/dictionary/:id'), (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
@@ -56,7 +57,7 @@ export const handlers = [
|
||||
return res(ctx.status(200), ctx.json(dictionary));
|
||||
}),
|
||||
|
||||
rest.get('/umbraco/management/api/v1/dictionary', (req, res, ctx) => {
|
||||
rest.get(umbracoPath('/dictionary'), (req, res, ctx) => {
|
||||
const skip = req.url.searchParams.get('skip');
|
||||
const take = req.url.searchParams.get('take');
|
||||
if (!skip || !take) return;
|
||||
@@ -74,25 +75,16 @@ export const handlers = [
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
|
||||
rest.post('/umbraco/management/api/v1/dictionary', async (req, res, ctx) => {
|
||||
rest.post(umbracoPath('/dictionary'), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
|
||||
if (!data) return;
|
||||
|
||||
data.icon = 'umb:book-alt';
|
||||
data.hasChildren = false;
|
||||
data.type = 'dictionary-item';
|
||||
data.translations = [
|
||||
{
|
||||
isoCode: 'en-US',
|
||||
translation: '',
|
||||
},
|
||||
{
|
||||
isoCode: 'fr',
|
||||
translation: '',
|
||||
},
|
||||
];
|
||||
|
||||
const value = umbDictionaryData.save(data.id, data);
|
||||
const value = umbDictionaryData.insert(data);
|
||||
|
||||
const createdResult = {
|
||||
value,
|
||||
@@ -102,7 +94,7 @@ export const handlers = [
|
||||
return res(ctx.status(200), ctx.json(createdResult));
|
||||
}),
|
||||
|
||||
rest.patch('/umbraco/management/api/v1/dictionary/:id', async (req, res, ctx) => {
|
||||
rest.patch(umbracoPath('/dictionary/:id'), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
if (!data) return;
|
||||
|
||||
@@ -115,7 +107,19 @@ export const handlers = [
|
||||
return res(ctx.status(200), ctx.json(saved));
|
||||
}),
|
||||
|
||||
rest.get('/umbraco/management/api/v1/tree/dictionary/root', (req, res, ctx) => {
|
||||
rest.put(umbracoPath('/dictionary/:id'), async (req, res, ctx) => {
|
||||
const data = await req.json();
|
||||
if (!data) return;
|
||||
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
const saved = umbDictionaryData.save(id, data);
|
||||
|
||||
return res(ctx.status(200), ctx.json(saved));
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath('/tree/dictionary/root'), (req, res, ctx) => {
|
||||
const items = umbDictionaryData.getTreeRoot();
|
||||
const response = {
|
||||
total: items.length,
|
||||
@@ -124,7 +128,7 @@ export const handlers = [
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
|
||||
rest.get('/umbraco/management/api/v1/tree/dictionary/children', (req, res, ctx) => {
|
||||
rest.get(umbracoPath('/tree/dictionary/children'), (req, res, ctx) => {
|
||||
const parentId = req.url.searchParams.get('parentId');
|
||||
if (!parentId) return;
|
||||
|
||||
@@ -138,7 +142,7 @@ export const handlers = [
|
||||
return res(ctx.status(200), ctx.json(response));
|
||||
}),
|
||||
|
||||
rest.get('/umbraco/management/api/v1/tree/dictionary/item', (req, res, ctx) => {
|
||||
rest.get(umbracoPath('/tree/dictionary/item'), (req, res, ctx) => {
|
||||
const ids = req.url.searchParams.getAll('id');
|
||||
if (!ids) return;
|
||||
|
||||
@@ -147,7 +151,7 @@ export const handlers = [
|
||||
return res(ctx.status(200), ctx.json(items));
|
||||
}),
|
||||
|
||||
rest.delete('/umbraco/management/api/v1/dictionary/:id', (req, res, ctx) => {
|
||||
rest.delete(umbracoPath('/dictionary/:id'), (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
@@ -157,7 +161,7 @@ export const handlers = [
|
||||
}),
|
||||
|
||||
// TODO => handle properly, querystring breaks handler
|
||||
rest.get('/umbraco/management/api/v1/dictionary/:id/export', (req, res, ctx) => {
|
||||
rest.get(umbracoPath('/dictionary/:id/export'), (req, res, ctx) => {
|
||||
const id = req.params.id as string;
|
||||
if (!id) return;
|
||||
|
||||
@@ -170,13 +174,13 @@ export const handlers = [
|
||||
return res(ctx.status(200));
|
||||
}),
|
||||
|
||||
rest.post('/umbraco/management/api/v1/dictionary/upload', async (req, res, ctx) => {
|
||||
rest.post(umbracoPath('/dictionary/upload'), async (req, res, ctx) => {
|
||||
if (!req.arrayBuffer()) return;
|
||||
|
||||
return res(ctx.status(200), ctx.json(uploadResponse));
|
||||
}),
|
||||
|
||||
rest.post('/umbraco/management/api/v1/dictionary/import', async (req, res, ctx) => {
|
||||
rest.post(umbracoPath('/dictionary/import'), async (req, res, ctx) => {
|
||||
const file = req.url.searchParams.get('file');
|
||||
|
||||
if (!file || !importResponse.id) return;
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import { UmbDictionaryRepository } from '../../dictionary/repository/dictionary.repository.js';
|
||||
import { UmbTextStyles } from "@umbraco-cms/backoffice/style";
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { css, html, customElement, state, when } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbTableConfig, UmbTableColumn, UmbTableItem } from '@umbraco-cms/backoffice/components';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
import { DictionaryOverviewResponseModel, LanguageResponseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
import {
|
||||
UmbModalManagerContext,
|
||||
UMB_MODAL_MANAGER_CONTEXT_TOKEN,
|
||||
UMB_CREATE_DICTIONARY_MODAL,
|
||||
} from '@umbraco-cms/backoffice/modal';
|
||||
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
@customElement('umb-dashboard-translation-dictionary')
|
||||
export class UmbDashboardTranslationDictionaryElement extends UmbLitElement {
|
||||
@@ -25,8 +19,6 @@ export class UmbDashboardTranslationDictionaryElement extends UmbLitElement {
|
||||
|
||||
#repo!: UmbDictionaryRepository;
|
||||
|
||||
#modalContext!: UmbModalManagerContext;
|
||||
|
||||
#tableItems: Array<UmbTableItem> = [];
|
||||
|
||||
#tableColumns: Array<UmbTableColumn> = [];
|
||||
@@ -35,10 +27,6 @@ export class UmbDashboardTranslationDictionaryElement extends UmbLitElement {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
new UmbContextConsumerController(this, UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => {
|
||||
this.#modalContext = instance;
|
||||
});
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
@@ -66,7 +54,7 @@ export class UmbDashboardTranslationDictionaryElement extends UmbLitElement {
|
||||
#setTableColumns() {
|
||||
this.#tableColumns = [
|
||||
{
|
||||
name: 'Name',
|
||||
name: this.localize.term('general_name'),
|
||||
alias: 'name',
|
||||
},
|
||||
];
|
||||
@@ -92,7 +80,7 @@ export class UmbDashboardTranslationDictionaryElement extends UmbLitElement {
|
||||
columnAlias: 'name',
|
||||
value: html`<a
|
||||
style="font-weight:bold"
|
||||
href="/section/dictionary/workspace/dictionary-item/edit/${dictionary.id}">
|
||||
href="section/dictionary/workspace/dictionary-item/edit/${dictionary.id}">
|
||||
${dictionary.name}</a
|
||||
> `,
|
||||
},
|
||||
@@ -107,11 +95,11 @@ export class UmbDashboardTranslationDictionaryElement extends UmbLitElement {
|
||||
value: dictionary.translatedIsoCodes?.includes(l.isoCode)
|
||||
? html`<uui-icon
|
||||
name="check"
|
||||
title="Translation exists for ${l.name}"
|
||||
title="${this.localize.term('visuallyHiddenTexts_hasTranslation')} (${l.name})"
|
||||
style="color:var(--uui-color-positive-standalone);display:inline-block"></uui-icon>`
|
||||
: html`<uui-icon
|
||||
name="alert"
|
||||
title="Translation does not exist for ${l.name}"
|
||||
title="${this.localize.term('visuallyHiddenTexts_noTranslation')} (${l.name})"
|
||||
style="color:var(--uui-color-danger-standalone);display:inline-block"></uui-icon>`,
|
||||
});
|
||||
});
|
||||
@@ -123,41 +111,27 @@ export class UmbDashboardTranslationDictionaryElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
#filter(e: { target: HTMLInputElement }) {
|
||||
this._tableItemsFiltered = e.target.value
|
||||
? this.#tableItems.filter((t) => t.id.includes(e.target.value))
|
||||
const searchValue = e.target.value.toLocaleLowerCase();
|
||||
this._tableItemsFiltered = searchValue
|
||||
? this.#tableItems.filter((t) => t.id.toLocaleLowerCase().includes(searchValue))
|
||||
: this.#tableItems;
|
||||
}
|
||||
|
||||
async #create() {
|
||||
// TODO: what to do if modal service is not available?
|
||||
if (!this.#modalContext) return;
|
||||
if (!this.#repo) return;
|
||||
|
||||
const modalContext = this.#modalContext?.open(UMB_CREATE_DICTIONARY_MODAL, { parentId: null });
|
||||
|
||||
const { name, parentId } = await modalContext.onSubmit();
|
||||
if (!name || parentId === undefined) return;
|
||||
|
||||
const { data: url } = await this.#repo.create({ name, parentId });
|
||||
|
||||
if (!url) return;
|
||||
//TODO: Why do we need to extract the id like this?
|
||||
const id = url.substring(url.lastIndexOf('/') + 1);
|
||||
|
||||
history.pushState({}, '', `/section/dictionary/workspace/dictionary-item/edit/${id}`);
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<umb-body-layout header-transparent>
|
||||
<div id="header" slot="header">
|
||||
<uui-button type="button" look="outline" label="Create dictionary item" @click=${this.#create}
|
||||
>Create dictionary item</uui-button
|
||||
>
|
||||
<uui-button
|
||||
type="button"
|
||||
look="outline"
|
||||
label=${this.localize.term('dictionary_createNew')}
|
||||
href="section/dictionary/workspace/dictionary-item/create/null">
|
||||
${this.localize.term('dictionary_createNew')}
|
||||
</uui-button>
|
||||
<uui-input
|
||||
@keyup="${this.#filter}"
|
||||
placeholder="Type to filter..."
|
||||
label="Type to filter dictionary"
|
||||
placeholder=${this.localize.term('placeholders_filter')}
|
||||
label=${this.localize.term('placeholders_filter')}
|
||||
id="searchbar">
|
||||
<div slot="prepend">
|
||||
<uui-icon name="search" id="searchbar_icon"></uui-icon>
|
||||
@@ -166,11 +140,12 @@ export class UmbDashboardTranslationDictionaryElement extends UmbLitElement {
|
||||
</div>
|
||||
${when(
|
||||
this._tableItemsFiltered.length,
|
||||
() => html` <umb-table
|
||||
.config=${this._tableConfig}
|
||||
.columns=${this.#tableColumns}
|
||||
.items=${this._tableItemsFiltered}></umb-table>`,
|
||||
() => html`<umb-empty-state>There were no dictionary items found.</umb-empty-state>`
|
||||
() =>
|
||||
html` <umb-table
|
||||
.config=${this._tableConfig}
|
||||
.columns=${this.#tableColumns}
|
||||
.items=${this._tableItemsFiltered}></umb-table>`,
|
||||
() => html`<umb-empty-state>${this.localize.term('emptyStates_emptyDictionaryTree')}</umb-empty-state>`,
|
||||
)}
|
||||
</umb-body-layout>
|
||||
`;
|
||||
|
||||
@@ -114,7 +114,7 @@ export class UmbDictionaryDetailServerDataSource
|
||||
// TODO => parentId will be a guid param once #13786 is merged and API regenerated
|
||||
return await tryExecuteAndNotify(
|
||||
this.#host,
|
||||
DictionaryResource.postDictionaryImport({ requestBody: { temporaryFileId, parentId } })
|
||||
DictionaryResource.postDictionaryImport({ requestBody: { temporaryFileId, parentId } }),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ export class UmbDictionaryDetailServerDataSource
|
||||
this.#host,
|
||||
DictionaryResource.postDictionaryImport({
|
||||
requestBody: formData,
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,10 +38,13 @@ export class UmbDictionaryWorkspaceEditorElement extends UmbLitElement {
|
||||
return html`
|
||||
<umb-workspace-editor alias="Umb.Workspace.Dictionary">
|
||||
<div id="header" slot="header">
|
||||
<uui-button href="/section/dictionary/dashboard" label="Back to list" compact>
|
||||
<uui-button href="section/dictionary/dashboard" label=${this.localize.term('general_backToOverview')} compact>
|
||||
<uui-icon name="umb:arrow-left"></uui-icon>
|
||||
</uui-button>
|
||||
<uui-input .value=${this._name} @input="${this.#handleInput}" label="Dictionary name"></uui-input>
|
||||
<uui-input
|
||||
.value=${this._name ?? ''}
|
||||
@input="${this.#handleInput}"
|
||||
label="${this.localize.term('general_dictionary')} ${this.localize.term('general_name')}"></uui-input>
|
||||
</div>
|
||||
</umb-workspace-editor>
|
||||
`;
|
||||
|
||||
@@ -76,8 +76,16 @@ export class UmbDictionaryWorkspaceContext
|
||||
async save() {
|
||||
if (!this.#data.value) return;
|
||||
if (!this.#data.value.id) return;
|
||||
await this.repository.save(this.#data.value.id, this.#data.value);
|
||||
this.setIsNew(false);
|
||||
|
||||
if (this.getIsNew()) {
|
||||
await this.repository.create(this.#data.value);
|
||||
this.setIsNew(false);
|
||||
} else {
|
||||
await this.repository.save(this.#data.value.id, this.#data.value);
|
||||
}
|
||||
|
||||
const data = this.getData();
|
||||
if (data) this.saveComplete(data);
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
@@ -85,8 +93,10 @@ export class UmbDictionaryWorkspaceContext
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const UMB_DICTIONARY_WORKSPACE_CONTEXT = new UmbContextToken<UmbSaveableWorkspaceContextInterface, UmbDictionaryWorkspaceContext>(
|
||||
export const UMB_DICTIONARY_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbSaveableWorkspaceContextInterface,
|
||||
UmbDictionaryWorkspaceContext
|
||||
>(
|
||||
'UmbWorkspaceContext',
|
||||
(context): context is UmbDictionaryWorkspaceContext => context.getEntityType?.() === 'dictionary-item'
|
||||
(context): context is UmbDictionaryWorkspaceContext => context.getEntityType?.() === 'dictionary-item',
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { UmbDictionaryWorkspaceContext } from './dictionary-workspace.context.js';
|
||||
import { UmbDictionaryWorkspaceEditorElement } from './dictionary-workspace-editor.element.js';
|
||||
import { UmbTextStyles } from "@umbraco-cms/backoffice/style";
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type { UmbRoute } from '@umbraco-cms/backoffice/router';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
@@ -20,6 +20,14 @@ export class UmbWorkspaceDictionaryElement extends UmbLitElement {
|
||||
this.#workspaceContext.load(id);
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'create/:parentId',
|
||||
component: () => this.#element,
|
||||
setup: (_component, info) => {
|
||||
const parentId = info.match.params.parentId === 'null' ? null : info.match.params.parentId;
|
||||
this.#workspaceContext.create(parentId);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
render() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { UMB_DICTIONARY_WORKSPACE_CONTEXT } from '../../dictionary-workspace.context.js';
|
||||
import { UmbDictionaryRepository } from '../../../repository/dictionary.repository.js';
|
||||
import { UUITextareaElement, UUITextareaEvent } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { css, html, customElement, state, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { css, html, customElement, state, repeat, ifDefined, unsafeHTML } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
import { DictionaryItemResponseModel, LanguageResponseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
@customElement('umb-workspace-view-dictionary-editor')
|
||||
@@ -62,12 +62,11 @@ export class UmbWorkspaceViewDictionaryEditorElement extends UmbLitElement {
|
||||
render() {
|
||||
return html`
|
||||
<uui-box>
|
||||
<p>Edit the different language versions for the dictionary item '<em>${this._dictionary?.name}</em>' below.</p>
|
||||
|
||||
${unsafeHTML(this.localize.term('dictionaryItem_description', this._dictionary?.name || 'unnamed'))}
|
||||
${repeat(
|
||||
this._languages,
|
||||
(item) => item.isoCode,
|
||||
(item) => this.#renderTranslation(item)
|
||||
(item) => this.#renderTranslation(item),
|
||||
)}
|
||||
</uui-box>
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user