Merge pull request #1780 from umbraco/bugfix/examine-dashboard-status-and-modals
Bugfix: examine dashboard status and modals
This commit is contained in:
@@ -588,7 +588,7 @@ export default {
|
||||
examineManagement: {
|
||||
configuredSearchers: 'Konfigurerede søgere',
|
||||
configuredSearchersDescription:
|
||||
'Viser egenskaber og værktøjer til enhver konfigureret søger (dvs. som en\n multi-indekssøger)\n ',
|
||||
'Viser egenskaber og værktøjer til enhver konfigureret søger (dvs. som en multi-indekssøger)',
|
||||
fieldValues: 'Feltværdier',
|
||||
healthStatus: 'Sundhedstilstand',
|
||||
healthStatusDescription: 'Indeksets sundhedstilstand, og hvis det kan læses',
|
||||
@@ -597,10 +597,10 @@ export default {
|
||||
indexInfoDescription: 'Viser indeksets egenskaber',
|
||||
manageIndexes: 'Administrer Examine indekserne',
|
||||
manageIndexesDescription:
|
||||
'Giver dig mulighed for at se detaljerne for hvert indeks og giver nogle\n værktøjer til styring af indeksørerne\n ',
|
||||
'Giver dig mulighed for at se detaljerne for hvert indeks og giver nogle værktøjer til styring af indeksørerne',
|
||||
rebuildIndex: 'Genopbyg indeks',
|
||||
rebuildIndexWarning:
|
||||
'\n Dette vil medføre, at indekset genopbygges.<br />\n Afhængigt af hvor meget indhold der er på dit website, kan det tage et stykke tid.<br />\n Det anbefales ikke at genopbygge et indeks i perioder med høj websitetrafik eller når redaktører redigerer indhold.\n ',
|
||||
'Dette vil medføre, at indekset genopbygges.<br /> Afhængigt af hvor meget indhold der er på dit website, kan det tage et stykke tid.<br /> Det anbefales ikke at genopbygge et indeks i perioder med høj websitetrafik eller når redaktører redigerer indhold.',
|
||||
searchers: 'Søgere',
|
||||
searchDescription: 'Søg i indekset og se resultaterne',
|
||||
tools: 'Værktøjer',
|
||||
@@ -608,7 +608,7 @@ export default {
|
||||
fields: 'felter',
|
||||
indexCannotRead: 'Indexet skal bygges igen, for at kunne læses',
|
||||
processIsTakingLonger:
|
||||
'Processen tager længere tid end forventet. Kontrollér Umbraco loggen for at se om\n der er sket fejl under operationen\n ',
|
||||
'Processen tager længere tid end forventet. Kontrollér Umbraco loggen for at se om der er sket fejl under operationen',
|
||||
indexCannotRebuild: 'Dette index kan ikke genbygges for det ikke har nogen',
|
||||
iIndexPopulator: 'IIndexPopulator',
|
||||
contentInIndex: 'Content in index',
|
||||
|
||||
@@ -597,7 +597,7 @@ export default {
|
||||
examineManagement: {
|
||||
configuredSearchers: 'Configured Searchers',
|
||||
configuredSearchersDescription:
|
||||
'Shows properties and tools for any configured Searcher (i.e. such as a\n multi-index searcher)\n ',
|
||||
'Shows properties and tools for any configured Searcher (i.e. such as a multi-index searcher)',
|
||||
fieldValues: 'Field values',
|
||||
healthStatus: 'Health status',
|
||||
healthStatusDescription: 'The health status of the index and if it can be read',
|
||||
@@ -607,10 +607,10 @@ export default {
|
||||
indexInfoDescription: 'Lists the properties of the index',
|
||||
manageIndexes: "Manage Examine's indexes",
|
||||
manageIndexesDescription:
|
||||
'Allows you to view the details of each index and provides some tools for\n managing the indexes\n ',
|
||||
'Allows you to view the details of each index and provides some tools for managing the indexes',
|
||||
rebuildIndex: 'Rebuild index',
|
||||
rebuildIndexWarning:
|
||||
'\n This will cause the index to be rebuilt.<br />\n Depending on how much content there is in your site this could take a while.<br />\n It is not recommended to rebuild an index during times of high website traffic or when editors are editing content.\n ',
|
||||
'This will cause the index to be rebuilt.<br /> Depending on how much content there is in your site this could take a while.<br /> It is not recommended to rebuild an index during times of high website traffic or when editors are editing content.',
|
||||
searchers: 'Searchers',
|
||||
searchDescription: 'Search the index and view the results',
|
||||
tools: 'Tools',
|
||||
@@ -618,7 +618,7 @@ export default {
|
||||
fields: 'fields',
|
||||
indexCannotRead: 'The index cannot be read and will need to be rebuilt',
|
||||
processIsTakingLonger:
|
||||
'The process is taking longer than expected, check the Umbraco log to see if there\n have been any errors during this operation\n ',
|
||||
'The process is taking longer than expected, check the Umbraco log to see if there have been any errors during this operation',
|
||||
indexCannotRebuild: 'This index cannot be rebuilt because it has no assigned',
|
||||
iIndexPopulator: 'IIndexPopulator',
|
||||
},
|
||||
|
||||
@@ -979,6 +979,11 @@ export enum HealthStatusModel {
|
||||
REBUILDING = 'Rebuilding'
|
||||
}
|
||||
|
||||
export type HealthStatusResponseModel = {
|
||||
status: HealthStatusModel
|
||||
message?: string | null
|
||||
};
|
||||
|
||||
export type HelpPageResponseModel = {
|
||||
name?: string | null
|
||||
description?: string | null
|
||||
@@ -993,7 +998,7 @@ parent?: ReferenceByIdModel | null
|
||||
|
||||
export type IndexResponseModel = {
|
||||
name: string
|
||||
healthStatus: HealthStatusModel
|
||||
healthStatus: HealthStatusResponseModel
|
||||
canRebuild: boolean
|
||||
searcherName: string
|
||||
documentCount: number
|
||||
@@ -5236,15 +5241,15 @@ PostWebhook: {
|
||||
GetWebhookById: {
|
||||
id: string
|
||||
|
||||
};
|
||||
DeleteWebhookById: {
|
||||
id: string
|
||||
|
||||
};
|
||||
PutWebhookById: {
|
||||
id: string
|
||||
requestBody?: UpdateWebhookRequestModel
|
||||
|
||||
};
|
||||
DeleteWebhookById: {
|
||||
id: string
|
||||
|
||||
};
|
||||
GetWebhookEvents: {
|
||||
skip?: number
|
||||
@@ -5259,8 +5264,8 @@ take?: number
|
||||
,GetWebhook: PagedWebhookResponseModel
|
||||
,PostWebhook: string
|
||||
,GetWebhookById: WebhookResponseModel
|
||||
,PutWebhookById: string
|
||||
,DeleteWebhookById: string
|
||||
,PutWebhookById: string
|
||||
,GetWebhookEvents: PagedWebhookEventModel
|
||||
|
||||
}
|
||||
|
||||
@@ -9022,20 +9022,17 @@ take
|
||||
* @returns string Success
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static putWebhookById(data: WebhookData['payloads']['PutWebhookById']): CancelablePromise<WebhookData['responses']['PutWebhookById']> {
|
||||
public static deleteWebhookById(data: WebhookData['payloads']['DeleteWebhookById']): CancelablePromise<WebhookData['responses']['DeleteWebhookById']> {
|
||||
const {
|
||||
|
||||
id,
|
||||
requestBody
|
||||
id
|
||||
} = data;
|
||||
return __request(OpenAPI, {
|
||||
method: 'PUT',
|
||||
method: 'DELETE',
|
||||
url: '/umbraco/management/api/v1/webhook/{id}',
|
||||
path: {
|
||||
id
|
||||
},
|
||||
body: requestBody,
|
||||
mediaType: 'application/json',
|
||||
responseHeader: 'Umb-Notifications',
|
||||
errors: {
|
||||
400: `Bad Request`,
|
||||
@@ -9050,17 +9047,20 @@ requestBody
|
||||
* @returns string Success
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static deleteWebhookById(data: WebhookData['payloads']['DeleteWebhookById']): CancelablePromise<WebhookData['responses']['DeleteWebhookById']> {
|
||||
public static putWebhookById(data: WebhookData['payloads']['PutWebhookById']): CancelablePromise<WebhookData['responses']['PutWebhookById']> {
|
||||
const {
|
||||
|
||||
id
|
||||
id,
|
||||
requestBody
|
||||
} = data;
|
||||
return __request(OpenAPI, {
|
||||
method: 'DELETE',
|
||||
method: 'PUT',
|
||||
url: '/umbraco/management/api/v1/webhook/{id}',
|
||||
path: {
|
||||
id
|
||||
},
|
||||
body: requestBody,
|
||||
mediaType: 'application/json',
|
||||
responseHeader: 'Umb-Notifications',
|
||||
errors: {
|
||||
400: `Bad Request`,
|
||||
|
||||
@@ -20,7 +20,7 @@ export const Indexers: IndexResponseModel[] = [
|
||||
{
|
||||
name: 'ExternalIndex',
|
||||
canRebuild: true,
|
||||
healthStatus: HealthStatusModel.HEALTHY,
|
||||
healthStatus: { status: HealthStatusModel.HEALTHY },
|
||||
documentCount: 0,
|
||||
fieldCount: 0,
|
||||
searcherName: '',
|
||||
@@ -40,7 +40,7 @@ export const Indexers: IndexResponseModel[] = [
|
||||
{
|
||||
name: 'InternalIndex',
|
||||
canRebuild: true,
|
||||
healthStatus: HealthStatusModel.HEALTHY,
|
||||
healthStatus: { status: HealthStatusModel.HEALTHY },
|
||||
documentCount: 0,
|
||||
fieldCount: 0,
|
||||
searcherName: '',
|
||||
@@ -60,7 +60,7 @@ export const Indexers: IndexResponseModel[] = [
|
||||
{
|
||||
name: 'MemberIndex',
|
||||
canRebuild: true,
|
||||
healthStatus: HealthStatusModel.HEALTHY,
|
||||
healthStatus: { status: HealthStatusModel.HEALTHY },
|
||||
fieldCount: 0,
|
||||
documentCount: 0,
|
||||
searcherName: '',
|
||||
|
||||
@@ -4,7 +4,6 @@ export * from './confirm-modal.token.js';
|
||||
export * from './debug-modal.token.js';
|
||||
export * from './embedded-media-modal.token.js';
|
||||
export * from './entity-user-permission-settings-modal.token.js';
|
||||
export * from './examine-fields-settings-modal.token.js';
|
||||
export * from './icon-picker-modal.token.js';
|
||||
export * from './item-picker-modal.token.js';
|
||||
export * from './link-picker-modal.token.js';
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from './modal/index.js';
|
||||
@@ -0,0 +1,5 @@
|
||||
import { manifests as modalManifests } from './modal/manifests.js';
|
||||
|
||||
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const manifests: Array<ManifestTypes> = [...modalManifests];
|
||||
@@ -0,0 +1,76 @@
|
||||
import type {
|
||||
UmbExamineFieldsSettingsModalData,
|
||||
UmbExamineFieldsSettingsModalValue,
|
||||
UmbExamineFieldSettingsType,
|
||||
} from './examine-fields-settings-modal.token.js';
|
||||
import { html, css, customElement } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
@customElement('umb-examine-fields-settings-modal')
|
||||
export class UmbExamineFieldsSettingsModalElement extends UmbModalBaseElement<
|
||||
UmbExamineFieldsSettingsModalData,
|
||||
UmbExamineFieldsSettingsModalValue
|
||||
> {
|
||||
render() {
|
||||
return html`<umb-body-layout headline=${this.localize.term('examineManagement_fields')}>
|
||||
<uui-scroll-container id="field-settings"> ${this.#renderFields()} </uui-scroll-container>
|
||||
<div slot="actions">
|
||||
<uui-button
|
||||
look="primary"
|
||||
label=${this.localize.term('general_close')}
|
||||
@click="${this._submitModal}"></uui-button>
|
||||
</div>
|
||||
</umb-body-layout>`;
|
||||
}
|
||||
|
||||
#setExposed(fieldSetting: UmbExamineFieldSettingsType) {
|
||||
const newField: UmbExamineFieldSettingsType = { ...fieldSetting, exposed: !fieldSetting.exposed };
|
||||
|
||||
const updatedFields =
|
||||
this.modalContext?.getValue().fields.map((field) => {
|
||||
if (field.name === fieldSetting.name) return newField;
|
||||
else return field;
|
||||
}) ?? [];
|
||||
|
||||
this.modalContext?.updateValue({ fields: updatedFields });
|
||||
}
|
||||
|
||||
#renderFields() {
|
||||
if (!this.value.fields.length) return;
|
||||
return html`<span>
|
||||
${Object.values(this.value.fields).map((field) => {
|
||||
return html`<uui-toggle
|
||||
name="${field.name}"
|
||||
label="${field.name}"
|
||||
.checked="${field.exposed}"
|
||||
@change="${() => this.#setExposed(field)}"></uui-toggle>
|
||||
<br />`;
|
||||
})}
|
||||
</span>`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
:host {
|
||||
display: relative;
|
||||
}
|
||||
|
||||
uui-scroll-container {
|
||||
overflow-y: scroll;
|
||||
max-height: 100%;
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export default UmbExamineFieldsSettingsModalElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-examine-fields-settings-modal': UmbExamineFieldsSettingsModalElement;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,20 @@
|
||||
import { UmbModalToken } from './modal-token.js';
|
||||
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
export type UmbExamineFieldsSettingsModalData = never;
|
||||
|
||||
type FieldSettingsType = {
|
||||
export type UmbExamineFieldSettingsType = {
|
||||
name: string;
|
||||
exposed: boolean;
|
||||
};
|
||||
|
||||
export type UmbExamineFieldsSettingsModalValue = {
|
||||
fields: Array<FieldSettingsType>;
|
||||
fields: Array<UmbExamineFieldSettingsType>;
|
||||
};
|
||||
|
||||
export const UMB_EXAMINE_FIELDS_SETTINGS_MODAL = new UmbModalToken<
|
||||
UmbExamineFieldsSettingsModalData,
|
||||
UmbExamineFieldsSettingsModalValue
|
||||
>('Umb.Modal.ExamineFieldsSettings', {
|
||||
>('Umb.Modal.Examine.FieldsSettings', {
|
||||
modal: {
|
||||
type: 'sidebar',
|
||||
size: 'small',
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './examine-fields-settings-modal.element.js';
|
||||
export * from './examine-fields-settings-modal.token.js';
|
||||
@@ -1,11 +1,15 @@
|
||||
import type {
|
||||
UmbExamineFieldsViewerModalData,
|
||||
UmbExamineFieldsViewerModalValue,
|
||||
} from './examine-fields-viewer-modal.token.js';
|
||||
import { html, css, nothing, customElement } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
|
||||
import type { SearchResultResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
|
||||
@customElement('umb-modal-element-fields-viewer')
|
||||
export class UmbModalElementFieldsViewerElement extends UmbModalBaseElement<
|
||||
SearchResultResponseModel & { name: string }
|
||||
@customElement('umb-examine-fields-viewer-modal')
|
||||
export class UmbExamineFieldsViewerModalElement extends UmbModalBaseElement<
|
||||
UmbExamineFieldsViewerModalData,
|
||||
UmbExamineFieldsViewerModalValue
|
||||
> {
|
||||
private _handleClose() {
|
||||
this.modalContext?.reject();
|
||||
@@ -15,7 +19,7 @@ export class UmbModalElementFieldsViewerElement extends UmbModalBaseElement<
|
||||
if (!this.data) return nothing;
|
||||
|
||||
return html`
|
||||
<uui-dialog-layout class="uui-text" headline="${this.data.name}">
|
||||
<umb-body-layout headline="${this.data?.name}">
|
||||
<uui-scroll-container id="field-viewer">
|
||||
<span>
|
||||
<uui-table>
|
||||
@@ -23,7 +27,7 @@ export class UmbModalElementFieldsViewerElement extends UmbModalBaseElement<
|
||||
<uui-table-head-cell> Field </uui-table-head-cell>
|
||||
<uui-table-head-cell> Value </uui-table-head-cell>
|
||||
</uui-table-head>
|
||||
${Object.values(this.data.fields ?? []).map((cell) => {
|
||||
${Object.values(this.data.searchResult.fields ?? []).map((cell) => {
|
||||
return html`<uui-table-row>
|
||||
<uui-table-cell> ${cell.name} </uui-table-cell>
|
||||
<uui-table-cell> ${cell.values?.join(', ')} </uui-table-cell>
|
||||
@@ -32,10 +36,13 @@ export class UmbModalElementFieldsViewerElement extends UmbModalBaseElement<
|
||||
</uui-table>
|
||||
</span>
|
||||
</uui-scroll-container>
|
||||
<div>
|
||||
<uui-button look="primary" @click="${this._handleClose}">Close</uui-button>
|
||||
<div slot="actions">
|
||||
<uui-button
|
||||
look="primary"
|
||||
label=${this.localize.term('general_close')}
|
||||
@click=${this._rejectModal}></uui-button>
|
||||
</div>
|
||||
</uui-dialog-layout>
|
||||
</umb-body-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -45,11 +52,6 @@ export class UmbModalElementFieldsViewerElement extends UmbModalBaseElement<
|
||||
:host {
|
||||
display: relative;
|
||||
}
|
||||
uui-dialog-layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
span {
|
||||
display: block;
|
||||
@@ -57,22 +59,18 @@ export class UmbModalElementFieldsViewerElement extends UmbModalBaseElement<
|
||||
}
|
||||
|
||||
uui-scroll-container {
|
||||
line-height: 0;
|
||||
overflow-y: scroll;
|
||||
max-height: 100%;
|
||||
min-height: 0;
|
||||
}
|
||||
div {
|
||||
margin-top: var(--uui-size-space-5);
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
export default UmbExamineFieldsViewerModalElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-modal-element-fields-viewer': UmbModalElementFieldsViewerElement;
|
||||
'umb-examine-fields-viewer-modal': UmbExamineFieldsViewerModalElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import type { SearchResultResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
export type UmbExamineFieldsViewerModalData = {
|
||||
name: string;
|
||||
searchResult: SearchResultResponseModel;
|
||||
};
|
||||
|
||||
export type UmbExamineFieldsViewerModalValue = never;
|
||||
|
||||
export const UMB_EXAMINE_FIELDS_VIEWER_MODAL = new UmbModalToken<
|
||||
UmbExamineFieldsViewerModalData,
|
||||
UmbExamineFieldsViewerModalValue
|
||||
>('Umb.Modal.Examine.FieldsViewer', {
|
||||
modal: {
|
||||
type: 'sidebar',
|
||||
size: 'small',
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './examine-fields-viewer-modal.element.js';
|
||||
export * from './examine-fields-viewer-modal.token.js';
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './fields-settings/index.js';
|
||||
export * from './fields-viewer/index.js';
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { ManifestModal, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
const modals: Array<ManifestModal> = [
|
||||
{
|
||||
type: 'modal',
|
||||
alias: 'Umb.Modal.Examine.FieldsSettings',
|
||||
name: 'Examine Field Settings Modal',
|
||||
js: () => import('./fields-settings/examine-fields-settings-modal.element.js'),
|
||||
},
|
||||
{
|
||||
type: 'modal',
|
||||
alias: 'Umb.Modal.Examine.FieldsViewer',
|
||||
name: 'Examine Field Viewer Modal',
|
||||
js: () => import('./fields-viewer/examine-fields-viewer-modal.element.js'),
|
||||
},
|
||||
];
|
||||
|
||||
export const manifests: Array<ManifestTypes> = [...modals];
|
||||
@@ -1,81 +0,0 @@
|
||||
import { html, css, customElement } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import type {
|
||||
UmbExamineFieldsSettingsModalValue,
|
||||
UmbExamineFieldsSettingsModalData} from '@umbraco-cms/backoffice/modal';
|
||||
import {
|
||||
UmbModalBaseElement,
|
||||
} from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
@customElement('umb-examine-fields-settings-modal')
|
||||
export default class UmbExamineFieldsSettingsModalElement extends UmbModalBaseElement<
|
||||
UmbExamineFieldsSettingsModalData,
|
||||
UmbExamineFieldsSettingsModalValue
|
||||
> {
|
||||
render() {
|
||||
if (this.value.fields) {
|
||||
return html`
|
||||
<uui-dialog-layout headline="Show fields">
|
||||
<uui-scroll-container id="field-settings">
|
||||
<span>
|
||||
${Object.values(this.value.fields).map((field, index) => {
|
||||
return html`<uui-toggle
|
||||
name="${field.name}"
|
||||
label="${field.name}"
|
||||
.checked="${field.exposed}"
|
||||
@change="${() => {
|
||||
this.value.fields ? (this.value.fields[index].exposed = !field.exposed) : '';
|
||||
}}"></uui-toggle>
|
||||
<br />`;
|
||||
})}
|
||||
</span>
|
||||
</uui-scroll-container>
|
||||
<div>
|
||||
<uui-button look="primary" label="Close sidebar" @click="${this._submitModal}">Close</uui-button>
|
||||
</div>
|
||||
</uui-dialog-layout>
|
||||
`;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
static styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
:host {
|
||||
display: relative;
|
||||
}
|
||||
|
||||
uui-dialog-layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
background-color: var(--uui-color-surface);
|
||||
box-shadow: var(--uui-shadow-depth-1, 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24));
|
||||
border-radius: var(--uui-border-radius);
|
||||
padding: var(--uui-size-space-5);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
uui-scroll-container {
|
||||
overflow-y: scroll;
|
||||
max-height: 100%;
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
div {
|
||||
margin-top: var(--uui-size-space-5);
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-examine-fields-settings-modal': UmbExamineFieldsSettingsModalElement;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { css, html, nothing, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
|
||||
import type { IndexResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import type { HealthStatusResponseModel, IndexResponseModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { HealthStatusModel, IndexerService } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
|
||||
@@ -25,35 +25,51 @@ export class UmbDashboardExamineIndexElement extends UmbLitElement {
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this._getIndexData();
|
||||
this.#loadData();
|
||||
}
|
||||
|
||||
private async _getIndexData() {
|
||||
async #loadData() {
|
||||
this._indexData = await this.#getIndexData();
|
||||
|
||||
if (this._indexData?.healthStatus.status === HealthStatusModel.REBUILDING) {
|
||||
this._buttonState = 'waiting';
|
||||
this._continuousPolling();
|
||||
} else {
|
||||
this._loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
async #getIndexData() {
|
||||
const { data } = await tryExecuteAndNotify(
|
||||
this,
|
||||
IndexerService.getIndexerByIndexName({ indexName: this.indexName }),
|
||||
);
|
||||
this._indexData = data;
|
||||
return data;
|
||||
}
|
||||
|
||||
// TODO: Add continuous polling to update the status
|
||||
if (this._indexData?.healthStatus === HealthStatusModel.REBUILDING) {
|
||||
this._buttonState = 'waiting';
|
||||
private async _continuousPolling() {
|
||||
//Checking the server every 5 seconds to see if the index is still rebuilding.
|
||||
while (this._buttonState === 'waiting') {
|
||||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
||||
this._indexData = await this.#getIndexData();
|
||||
if (this._indexData?.healthStatus.status !== HealthStatusModel.REBUILDING) {
|
||||
this._buttonState = 'success';
|
||||
}
|
||||
}
|
||||
|
||||
this._loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
private async _onRebuildHandler() {
|
||||
await umbConfirmModal(this, {
|
||||
headline: `Rebuild ${this.indexName}`,
|
||||
content: html`
|
||||
This will cause the index to be rebuilt.<br />
|
||||
headline: `${this.localize.term('examineManagement_rebuildIndex')} ${this.indexName}`,
|
||||
content: html`<umb-localize key="examineManagement_rebuildIndexWarning"
|
||||
>This will cause the index to be rebuilt.<br />
|
||||
Depending on how much content there is in your site this could take a while.<br />
|
||||
It is not recommended to rebuild an index during times of high website traffic or when editors are editing
|
||||
content.
|
||||
`,
|
||||
content.</umb-localize
|
||||
> `,
|
||||
color: 'danger',
|
||||
confirmLabel: 'Rebuild',
|
||||
confirmLabel: this.localize.term('examineManagement_rebuildIndex'),
|
||||
});
|
||||
|
||||
this._rebuild();
|
||||
@@ -68,9 +84,22 @@ export class UmbDashboardExamineIndexElement extends UmbLitElement {
|
||||
this._buttonState = 'failed';
|
||||
return;
|
||||
}
|
||||
|
||||
this._buttonState = 'success';
|
||||
await this._getIndexData();
|
||||
await this.#loadData();
|
||||
}
|
||||
|
||||
#renderHealthStatus(healthStatus: HealthStatusResponseModel) {
|
||||
const msg = healthStatus.message ? healthStatus.message : healthStatus.status;
|
||||
switch (healthStatus.status) {
|
||||
case HealthStatusModel.HEALTHY:
|
||||
return html`<umb-icon name="icon-check color-green"></umb-icon>${msg}`;
|
||||
case HealthStatusModel.UNHEALTHY:
|
||||
return html`<umb-icon name="icon-error color-red"></umb-icon>${msg}`;
|
||||
case HealthStatusModel.REBUILDING:
|
||||
return html`<umb-icon name="icon-time color-yellow"></umb-icon>${msg}`;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -79,35 +108,33 @@ export class UmbDashboardExamineIndexElement extends UmbLitElement {
|
||||
return html`
|
||||
<uui-box headline="${this.indexName}">
|
||||
<p>
|
||||
<strong>Health Status</strong><br />
|
||||
The health status of the ${this.indexName} and if it can be read
|
||||
<strong><umb-localize key="examineManagement_healthStatus">Health Status</umb-localize></strong
|
||||
><br />
|
||||
<umb-localize key="examineManagement_healthStatusDescription"
|
||||
>The health status of the ${this.indexName} and if it can be read</umb-localize
|
||||
>
|
||||
</p>
|
||||
<div>
|
||||
<uui-icon-essentials>
|
||||
${
|
||||
this._indexData.healthStatus === HealthStatusModel.UNHEALTHY
|
||||
? html`<uui-icon name="wrong" class="danger"></uui-icon>`
|
||||
: html`<uui-icon name="check" class="positive"></uui-icon>`
|
||||
}
|
||||
</uui-icon>
|
||||
</uui-icon-essentials>
|
||||
${this._indexData.healthStatus}
|
||||
</div>
|
||||
<div id="health-status">${this.#renderHealthStatus(this._indexData.healthStatus)}</div>
|
||||
</uui-box>
|
||||
${this.renderIndexSearch()} ${this.renderPropertyList()} ${this.renderTools()}
|
||||
`;
|
||||
}
|
||||
|
||||
private renderIndexSearch() {
|
||||
if (!this._indexData || this._indexData.healthStatus !== HealthStatusModel.HEALTHY) return nothing;
|
||||
// Do we want to show the search while rebuilding?
|
||||
if (!this._indexData || this._indexData.healthStatus.status === HealthStatusModel.REBUILDING) return nothing;
|
||||
return html`<umb-dashboard-examine-searcher .searcherName="${this.indexName}"></umb-dashboard-examine-searcher>`;
|
||||
}
|
||||
|
||||
private renderPropertyList() {
|
||||
if (!this._indexData) return nothing;
|
||||
|
||||
return html`<uui-box headline="Index info">
|
||||
<p>Lists the properties of the ${this.indexName}</p>
|
||||
return html`<uui-box headline=${this.localize.term('examineManagement_indexInfo')}>
|
||||
<p>
|
||||
<umb-localize key="examineManagement_indexInfoDescription"
|
||||
>Lists the properties of the ${this.indexName}</umb-localize
|
||||
>
|
||||
</p>
|
||||
<uui-table class="info">
|
||||
<uui-table-row>
|
||||
<uui-table-cell style="width:0px; font-weight: bold;"> documentCount </uui-table-cell>
|
||||
@@ -130,23 +157,26 @@ export class UmbDashboardExamineIndexElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
private renderTools() {
|
||||
return html` <uui-box headline="Tools">
|
||||
<p>Tools to manage the ${this.indexName}</p>
|
||||
return html` <uui-box headline=${this.localize.term('examineManagement_tools')}>
|
||||
<p><umb-localize key="examineManagement_toolsDescription">Tools to manage the ${this.indexName}</umb-localize></p>
|
||||
<uui-button
|
||||
color="danger"
|
||||
look="primary"
|
||||
.state="${this._buttonState}"
|
||||
@click="${this._onRebuildHandler}"
|
||||
.disabled="${this._indexData?.canRebuild ? false : true}"
|
||||
label="Rebuild index">
|
||||
Rebuild
|
||||
</uui-button>
|
||||
label=${this.localize.term('examineManagement_rebuildIndex')}></uui-button>
|
||||
</uui-box>`;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
#health-status {
|
||||
display: flex;
|
||||
gap: var(--uui-size-6);
|
||||
}
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
@@ -190,13 +220,6 @@ export class UmbDashboardExamineIndexElement extends UmbLitElement {
|
||||
padding-right: var(--uui-size-space-5);
|
||||
}
|
||||
|
||||
.positive {
|
||||
color: var(--uui-color-positive);
|
||||
}
|
||||
.danger {
|
||||
color: var(--uui-color-danger);
|
||||
}
|
||||
|
||||
button {
|
||||
background: none;
|
||||
border: none;
|
||||
|
||||
@@ -40,19 +40,38 @@ export class UmbDashboardExamineOverviewElement extends UmbLitElement {
|
||||
this._loadingSearchers = false;
|
||||
}
|
||||
|
||||
#renderStatus(status: HealthStatusModel) {
|
||||
switch (status) {
|
||||
case HealthStatusModel.HEALTHY:
|
||||
return html`<umb-icon name="icon-check color-green"></umb-icon>`;
|
||||
case HealthStatusModel.UNHEALTHY:
|
||||
return html`<umb-icon name="icon-error color-red"></umb-icon>`;
|
||||
case HealthStatusModel.REBUILDING:
|
||||
return html`<umb-icon name="icon-time color-yellow"></umb-icon>`;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<uui-box headline="Indexers" class="overview">
|
||||
<uui-box headline=${this.localize.term('examineManagement_indexers')} class="overview">
|
||||
<p>
|
||||
<strong>Manage Examine's indexes</strong><br />
|
||||
Allows you to view the details of each index and provides some tools for managing the indexes
|
||||
<strong><umb-localize key="examineManagement_manageIndexes">Manage Examine's indexes</umb-localize></strong
|
||||
><br />
|
||||
<umb-localize key="examineManagement_manageIndexesDescription"
|
||||
>Allows you to view the details of each index and provides some tools for managing the indexes</umb-localize
|
||||
>
|
||||
</p>
|
||||
${this.renderIndexersList()}
|
||||
</uui-box>
|
||||
<uui-box headline="Searchers">
|
||||
<uui-box headline=${this.localize.term('examineManagement_searchers')}>
|
||||
<p>
|
||||
<strong>Configured Searchers</strong><br />
|
||||
Shows properties and tools for any configured Searcher (i.e. such as a multi-index searcher)
|
||||
<strong><umb-localize key="examineManagement_configuredSearchers">Configured Searchers</umb-localize></strong
|
||||
><br />
|
||||
<umb-localize key="examineManagement_configuredSearchersDescription"
|
||||
>Shows properties and tools for any configured Searcher (i.e. such as a multi-index searcher)</umb-localize
|
||||
>
|
||||
</p>
|
||||
${this.renderSearchersList()}
|
||||
</uui-box>
|
||||
@@ -66,16 +85,7 @@ export class UmbDashboardExamineOverviewElement extends UmbLitElement {
|
||||
${this._indexers.map((index) => {
|
||||
return html`
|
||||
<uui-table-row>
|
||||
<uui-table-cell style="width:0px">
|
||||
<uui-icon-essentials>
|
||||
${
|
||||
index.healthStatus === HealthStatusModel.UNHEALTHY
|
||||
? html`<uui-icon name="wrong" class="danger"></uui-icon>`
|
||||
: html`<uui-icon name="check" class="positive"></uui-icon>`
|
||||
}
|
||||
</uui-icon>
|
||||
</uui-icon-essentials>
|
||||
</uui-table-cell>
|
||||
<uui-table-cell style="width:0px"> ${this.#renderStatus(index.healthStatus.status)} </uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<a href="${window.location.href.replace(/\/+$/, '')}/index/${index.name}">${index.name}</a>
|
||||
</uui-table-cell>
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { UMB_EXAMINE_FIELDS_SETTINGS_MODAL, UMB_EXAMINE_FIELDS_VIEWER_MODAL } from '../modal/index.js';
|
||||
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
|
||||
import { css, html, nothing, customElement, state, query, property } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { UMB_MODAL_MANAGER_CONTEXT, UMB_EXAMINE_FIELDS_SETTINGS_MODAL } from '@umbraco-cms/backoffice/modal';
|
||||
import {
|
||||
UMB_MODAL_MANAGER_CONTEXT,
|
||||
UMB_WORKSPACE_MODAL,
|
||||
UmbModalRouteRegistrationController,
|
||||
} from '@umbraco-cms/backoffice/modal';
|
||||
import type { SearchResultResponseModel, FieldPresentationModel } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { SearcherService } from '@umbraco-cms/backoffice/external/backend-api';
|
||||
import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
|
||||
|
||||
import './modal-views/fields-viewer.element.js';
|
||||
import './modal-views/fields-settings-modal.element.js';
|
||||
|
||||
interface ExposedSearchResultField {
|
||||
name: string;
|
||||
exposed: boolean;
|
||||
@@ -31,15 +33,27 @@ export class UmbDashboardExamineSearcherElement extends UmbLitElement {
|
||||
@query('#search-input')
|
||||
private _searchInput!: HTMLInputElement;
|
||||
|
||||
private _onNameClick() {
|
||||
// TODO:
|
||||
alert('TODO: Open workspace for ' + this.searcherName);
|
||||
}
|
||||
@state()
|
||||
private _workspacePath = 'aa';
|
||||
|
||||
private _onKeyPress(e: KeyboardEvent) {
|
||||
e.key == 'Enter' ? this._onSearch() : undefined;
|
||||
}
|
||||
|
||||
#entityType = '';
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.addAdditionalPath(':entityType')
|
||||
.onSetup((routingInfo) => {
|
||||
return { data: { entityType: routingInfo.entityType, preset: {} } };
|
||||
})
|
||||
.observeRouteBuilder((routeBuilder) => {
|
||||
this._workspacePath = routeBuilder({ entityType: this.#entityType });
|
||||
});
|
||||
}
|
||||
|
||||
private async _onSearch() {
|
||||
if (!this._searchInput.value.length) return;
|
||||
this._searchLoading = true;
|
||||
@@ -86,36 +100,48 @@ export class UmbDashboardExamineSearcherElement extends UmbLitElement {
|
||||
const modalContext = modalManager.open(this, UMB_EXAMINE_FIELDS_SETTINGS_MODAL, {
|
||||
value: { fields: this._exposedFields ?? [] },
|
||||
});
|
||||
modalContext?.onSubmit().then((value) => {
|
||||
this._exposedFields = value.fields;
|
||||
});
|
||||
await modalContext.onSubmit().catch(() => undefined);
|
||||
|
||||
const value = modalContext.getValue();
|
||||
|
||||
this._exposedFields = value?.fields;
|
||||
}
|
||||
|
||||
async #onFieldViewClick(rowData: SearchResultResponseModel) {
|
||||
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
|
||||
modalManager.open(this, 'umb-modal-element-fields-viewer', {
|
||||
|
||||
const modalContext = modalManager.open(this, UMB_EXAMINE_FIELDS_VIEWER_MODAL, {
|
||||
modal: {
|
||||
type: 'sidebar',
|
||||
size: 'medium',
|
||||
},
|
||||
data: { ...rowData, name: this.getSearchResultNodeName(rowData) },
|
||||
data: { searchResult: rowData, name: this.getSearchResultNodeName(rowData) },
|
||||
});
|
||||
await modalContext.onSubmit().catch(() => undefined);
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<uui-box headline="Search">
|
||||
<p>Search the ${this.searcherName} and view the results</p>
|
||||
<uui-box headline=${this.localize.term('general_search')}>
|
||||
<p>
|
||||
<umb-localize key="examineManagement_searchDescription"
|
||||
>Search the ${this.searcherName} and view the results</umb-localize
|
||||
>
|
||||
</p>
|
||||
<div class="flex">
|
||||
<uui-input
|
||||
type="search"
|
||||
id="search-input"
|
||||
placeholder="Type to filter..."
|
||||
label="Type to filter"
|
||||
placeholder=${this.localize.term('placeholders_filter')}
|
||||
label=${this.localize.term('placeholders_filter')}
|
||||
@keypress=${this._onKeyPress}
|
||||
${umbFocus()}>
|
||||
</uui-input>
|
||||
<uui-button color="positive" look="primary" label="Search" @click="${this._onSearch}"> Search </uui-button>
|
||||
<uui-button
|
||||
color="positive"
|
||||
look="primary"
|
||||
label=${this.localize.term('general_search')}
|
||||
@click="${this._onSearch}"></uui-button>
|
||||
</div>
|
||||
${this.renderSearchResults()}
|
||||
</uui-box>
|
||||
@@ -128,28 +154,44 @@ export class UmbDashboardExamineSearcherElement extends UmbLitElement {
|
||||
return nodeNameField?.values?.join(', ') ?? '';
|
||||
}
|
||||
|
||||
#getEntityTypeFromIndexType(indexType: string) {
|
||||
switch (indexType) {
|
||||
case 'content':
|
||||
return 'document';
|
||||
default:
|
||||
return indexType;
|
||||
}
|
||||
}
|
||||
|
||||
private renderSearchResults() {
|
||||
if (this._searchLoading) return html`<uui-loader></uui-loader>`;
|
||||
if (!this._searchResults) return nothing;
|
||||
if (!this._searchResults.length) {
|
||||
return html`<p>No results found</p>`;
|
||||
return html`<p>${this.localize.term('examineManagement_noResults')}</p>`;
|
||||
}
|
||||
return html`<div class="table-container">
|
||||
<uui-scroll-container>
|
||||
<uui-table class="search">
|
||||
<uui-table-head>
|
||||
<uui-table-head-cell style="width:0">Score</uui-table-head-cell>
|
||||
<uui-table-head-cell style="width:0">Id</uui-table-head-cell>
|
||||
<uui-table-head-cell>Name</uui-table-head-cell>
|
||||
<uui-table-head-cell>Fields</uui-table-head-cell>
|
||||
<uui-table-head-cell style="width:0">${this.localize.term('general_id')}</uui-table-head-cell>
|
||||
<uui-table-head-cell>${this.localize.term('general_name')}</uui-table-head-cell>
|
||||
<uui-table-head-cell>${this.localize.term('examineManagement_fields')}</uui-table-head-cell>
|
||||
${this.renderHeadCells()}
|
||||
</uui-table-head>
|
||||
${this._searchResults?.map((rowData) => {
|
||||
const indexType = rowData.fields?.find((field) => field.name === '__IndexType')?.values?.join(', ') ?? '';
|
||||
this.#entityType = this.#getEntityTypeFromIndexType(indexType);
|
||||
const unique = rowData.fields?.find((field) => field.name === '__Key')?.values?.join(', ') ?? '';
|
||||
|
||||
return html`<uui-table-row>
|
||||
<uui-table-cell> ${rowData.score} </uui-table-cell>
|
||||
<uui-table-cell> ${rowData.id} </uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<uui-button look="secondary" label="Open workspace for this document" @click="${this._onNameClick}">
|
||||
<uui-button
|
||||
look="secondary"
|
||||
label=${this.localize.term('actions_editContent')}
|
||||
href=${this._workspacePath + this.#entityType + '/edit/' + unique}>
|
||||
${this.getSearchResultNodeName(rowData)}
|
||||
</uui-button>
|
||||
</uui-table-cell>
|
||||
@@ -157,9 +199,10 @@ export class UmbDashboardExamineSearcherElement extends UmbLitElement {
|
||||
<uui-button
|
||||
class="bright"
|
||||
look="secondary"
|
||||
label="Open sidebar to see all fields"
|
||||
label=${this.localize.term('examineManagement_fieldValues')}
|
||||
@click=${() => this.#onFieldViewClick(rowData)}>
|
||||
${rowData.fields ? Object.keys(rowData.fields).length : ''} fields
|
||||
${rowData.fields ? Object.keys(rowData.fields).length : ''}
|
||||
${this.localize.term('examineManagement_fields')}
|
||||
</uui-button>
|
||||
</uui-table-cell>
|
||||
${rowData.fields ? this.renderBodyCells(rowData.fields) : ''}
|
||||
@@ -185,7 +228,7 @@ export class UmbDashboardExamineSearcherElement extends UmbLitElement {
|
||||
<span>${field.name}</span>
|
||||
<uui-button
|
||||
look="secondary"
|
||||
label="Close field ${field.name}"
|
||||
label="${this.localize.term('actions_remove')} ${field.name}"
|
||||
compact
|
||||
@click="${() => {
|
||||
this._exposedFields = this._exposedFields?.map((f) => {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { manifests as examineManifests } from './examine-management-dashboard/manifests.js';
|
||||
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
import './examine-management-dashboard/index.js';
|
||||
|
||||
export const manifests: Array<ManifestTypes> = [
|
||||
{
|
||||
type: 'headerApp',
|
||||
@@ -37,10 +40,5 @@ export const manifests: Array<ManifestTypes> = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'modal',
|
||||
alias: 'Umb.Modal.ExamineFieldsSettings',
|
||||
name: 'Examine Field Settings Modal',
|
||||
js: () => import('./examine-management-dashboard/views/modal-views/fields-settings-modal.element.js'),
|
||||
},
|
||||
...examineManifests,
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user