Merge remote-tracking branch 'origin/main' into feature/user-section-v2
This commit is contained in:
43158
src/Umbraco.Web.UI.Client/package-lock.json
generated
43158
src/Umbraco.Web.UI.Client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -48,7 +48,7 @@
|
||||
"@umbraco-ui/uui-modal-dialog": "file:umbraco-ui-uui-modal-dialog-0.0.0.tgz",
|
||||
"@umbraco-ui/uui-modal-sidebar": "file:umbraco-ui-uui-modal-sidebar-0.0.0.tgz",
|
||||
"element-internals-polyfill": "^1.1.16",
|
||||
"lit": "^2.4.0",
|
||||
"lit": "^2.4.1",
|
||||
"lodash": "^4.17.21",
|
||||
"openapi-typescript-fetch": "^1.1.3",
|
||||
"router-slot": "^1.5.5",
|
||||
@@ -59,7 +59,7 @@
|
||||
"@babel/core": "^7.20.2",
|
||||
"@mdx-js/react": "^2.1.5",
|
||||
"@open-wc/testing": "^3.1.7",
|
||||
"@playwright/test": "^1.27.1",
|
||||
"@playwright/test": "^1.28.0",
|
||||
"@storybook/addon-a11y": "^6.5.13",
|
||||
"@storybook/addon-actions": "^6.5.13",
|
||||
"@storybook/addon-essentials": "^6.5.13",
|
||||
@@ -69,7 +69,7 @@
|
||||
"@storybook/web-components": "^6.5.13",
|
||||
"@types/chai": "^4.3.4",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@types/mocha": "^9.1.1",
|
||||
"@types/mocha": "^10.0.0",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.43.0",
|
||||
"@typescript-eslint/parser": "^5.43.0",
|
||||
@@ -83,19 +83,19 @@
|
||||
"eslint-import-resolver-typescript": "^3.5.2",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-lit": "^1.6.1",
|
||||
"eslint-plugin-lit-a11y": "^2.2.3",
|
||||
"eslint-plugin-lit-a11y": "^2.3.0",
|
||||
"eslint-plugin-local-rules": "^1.3.2",
|
||||
"eslint-plugin-storybook": "^0.6.7",
|
||||
"lit-html": "^2.4.0",
|
||||
"msw": "^0.47.4",
|
||||
"msw": "^0.48.3",
|
||||
"msw-storybook-addon": "^1.6.3",
|
||||
"openapi-typescript-codegen": "^0.23.0",
|
||||
"playwright-msw": "^2.0.1",
|
||||
"plop": "^3.1.1",
|
||||
"prettier": "2.7.1",
|
||||
"tiny-glob": "^0.2.9",
|
||||
"typescript": "^4.8.4",
|
||||
"vite": "^3.2.3",
|
||||
"typescript": "^4.9.3",
|
||||
"vite": "^3.2.4",
|
||||
"vite-plugin-static-copy": "^0.12.0",
|
||||
"vite-tsconfig-paths": "^3.5.2",
|
||||
"web-component-analyzer": "^2.0.0-next.4"
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
/* tslint:disable */
|
||||
|
||||
/**
|
||||
* Mock Service Worker (0.47.4).
|
||||
* Mock Service Worker (0.48.3).
|
||||
* @see https://github.com/mswjs/msw
|
||||
* - Please do NOT modify this file.
|
||||
* - Please do NOT serve this file on production.
|
||||
*/
|
||||
|
||||
const INTEGRITY_CHECKSUM = 'b3066ef78c2f9090b4ce87e874965995'
|
||||
const INTEGRITY_CHECKSUM = '3d6b9f06410d179a7f7404d4bf4c3c70'
|
||||
const activeClientIds = new Set()
|
||||
|
||||
self.addEventListener('install', function () {
|
||||
@@ -174,7 +174,7 @@ async function handleRequest(event, requestId) {
|
||||
async function resolveMainClient(event) {
|
||||
const client = await self.clients.get(event.clientId)
|
||||
|
||||
if (client.frameType === 'top-level') {
|
||||
if (client?.frameType === 'top-level') {
|
||||
return client
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,66 @@
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { css, html, LitElement } from 'lit';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
import { html, LitElement, css, nothing } from 'lit';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { IRoute, IRoutingInfo, path } from 'router-slot';
|
||||
|
||||
import { UmbDashboardExamineIndexElement } from './views/section-view-examine-indexers';
|
||||
import { UmbDashboardExamineSearcherElement } from './views/section-view-examine-searchers';
|
||||
|
||||
import { UmbContextConsumerMixin } from '@umbraco-cms/context-api';
|
||||
|
||||
@customElement('umb-dashboard-examine-management')
|
||||
export class UmbDashboardExamineManagementElement extends LitElement {
|
||||
static styles = [UUITextStyles, css``];
|
||||
export class UmbDashboardExamineManagementElement extends UmbContextConsumerMixin(LitElement) {
|
||||
static styles = [
|
||||
css`
|
||||
a {
|
||||
color: var(--uui-color-text);
|
||||
background: transparent;
|
||||
border: none;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
}
|
||||
`,
|
||||
];
|
||||
@state()
|
||||
private _routes: IRoute[] = [
|
||||
{
|
||||
path: `/index/:indexerName`,
|
||||
component: () => import('./views/section-view-examine-indexers'),
|
||||
setup: (component: HTMLElement, info: IRoutingInfo) => {
|
||||
const element = component as UmbDashboardExamineIndexElement;
|
||||
element.indexName = info.match.params.indexerName;
|
||||
},
|
||||
},
|
||||
{
|
||||
path: `/searcher/:searcherName`,
|
||||
component: () => import('./views/section-view-examine-searchers'),
|
||||
setup: (component: HTMLElement, info: IRoutingInfo) => {
|
||||
const element = component as UmbDashboardExamineSearcherElement;
|
||||
element.searcherName = info.match.params.searcherName;
|
||||
},
|
||||
},
|
||||
{
|
||||
path: ``,
|
||||
component: () => import('./views/section-view-examine-overview'),
|
||||
},
|
||||
];
|
||||
|
||||
@state()
|
||||
private _currentPath?: string;
|
||||
|
||||
private _onRouteChange() {
|
||||
this._currentPath = path();
|
||||
}
|
||||
|
||||
private get backbutton(): boolean {
|
||||
return this._currentPath != '/section/settings/dashboard/examine-management/' || !this._currentPath ? true : false;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<uui-box>
|
||||
<h1>Examine Management</h1>
|
||||
</uui-box>
|
||||
`;
|
||||
return html` ${this.backbutton
|
||||
? html` <a href="/section/settings/dashboard/examine-management/"> ← Back to overview </a> `
|
||||
: nothing}
|
||||
<router-slot @changestate="${this._onRouteChange}" .routes=${this._routes}></router-slot>`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,12 +4,27 @@ import { html } from 'lit-html';
|
||||
import type { UmbDashboardExamineManagementElement } from './dashboard-examine-management.element';
|
||||
import './dashboard-examine-management.element';
|
||||
|
||||
import type { UmbDashboardExamineOverviewElement } from './views/section-view-examine-overview';
|
||||
import './views/section-view-examine-overview';
|
||||
|
||||
import type { UmbDashboardExamineIndexElement } from './views/section-view-examine-indexers';
|
||||
import './views/section-view-examine-indexers';
|
||||
|
||||
import type { UmbDashboardExamineSearcherElement } from './views/section-view-examine-searchers';
|
||||
import './views/section-view-examine-searchers';
|
||||
|
||||
export default {
|
||||
title: 'Dashboards/Examine Management',
|
||||
component: 'umb-dashboard-examine-management',
|
||||
id: 'umb-dashboard-examine-management',
|
||||
} as Meta;
|
||||
|
||||
export const AAAOverview: Story<UmbDashboardExamineManagementElement> = () =>
|
||||
html` <umb-dashboard-examine-management></umb-dashboard-examine-management>`;
|
||||
export const AAAOverview: Story<UmbDashboardExamineOverviewElement> = () =>
|
||||
html` <umb-dashboard-examine-overview></umb-dashboard-examine-overview>`;
|
||||
AAAOverview.storyName = 'Overview';
|
||||
|
||||
export const Index: Story<UmbDashboardExamineIndexElement> = () =>
|
||||
html` <umb-dashboard-examine-index indexName="InternalIndex"></umb-dashboard-examine-index>`;
|
||||
|
||||
export const Searcher: Story<UmbDashboardExamineSearcherElement> = () =>
|
||||
html` <umb-dashboard-examine-searcher searcherName="InternalSearcher"></umb-dashboard-examine-searcher>`;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
export interface SearcherModel {
|
||||
name: string;
|
||||
providerProperties: unknown; //TODO
|
||||
}
|
||||
|
||||
export interface IndexModel {
|
||||
name: string;
|
||||
canRebuild: boolean;
|
||||
healthStatus: string;
|
||||
isHealthy: boolean;
|
||||
providerProperties: ProviderPropertiesModel;
|
||||
}
|
||||
|
||||
export interface ProviderPropertiesModel {
|
||||
CommitCount: number;
|
||||
DefaultAnalyzer: string;
|
||||
DocumentCount: number;
|
||||
FieldCount: number;
|
||||
LuceneDirectory: string;
|
||||
LuceneIndexFolder: string;
|
||||
DirectoryFactory: string;
|
||||
EnableDefaultEventHandler: boolean;
|
||||
PublishedValuesOnly: boolean;
|
||||
SupportProtectedContent: boolean;
|
||||
IncludeFields?: string[];
|
||||
}
|
||||
|
||||
export interface FieldViewModel {
|
||||
name: string;
|
||||
values: string[];
|
||||
}
|
||||
|
||||
export interface SearchResultsModel {
|
||||
id: number;
|
||||
name: string;
|
||||
fields: FieldViewModel[];
|
||||
score: number;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import { html, css } from 'lit';
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { UmbModalLayoutElement } from '@umbraco-cms/services';
|
||||
|
||||
export interface UmbModalFieldsSettingsData {
|
||||
name: string;
|
||||
exposed: boolean;
|
||||
}
|
||||
|
||||
@customElement('umb-modal-layout-fields-settings')
|
||||
export class UmbModalLayoutFieldsSettingsElement extends UmbModalLayoutElement<UmbModalFieldsSettingsData> {
|
||||
static styles = [
|
||||
UUITextStyles,
|
||||
css`
|
||||
:host {
|
||||
display: relative;
|
||||
}
|
||||
|
||||
uui-dialog-layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
background-color: white;
|
||||
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;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@state()
|
||||
private _fields?: UmbModalFieldsSettingsData[];
|
||||
|
||||
private _handleClose() {
|
||||
this.modalHandler?.close({ fields: this._fields });
|
||||
}
|
||||
|
||||
disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
this._handleClose();
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
this.data
|
||||
? (this._fields = Object.values(this.data).map((field) => {
|
||||
return { name: field.name, exposed: field.exposed };
|
||||
}))
|
||||
: '';
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this._fields) {
|
||||
return html`
|
||||
<uui-dialog-layout headline="Show fields">
|
||||
<uui-scroll-container id="field-settings">
|
||||
<span>
|
||||
${Object.values(this._fields).map((field, index) => {
|
||||
return html`<uui-toggle
|
||||
name="${field.name}"
|
||||
label="${field.name}"
|
||||
.checked="${field.exposed}"
|
||||
@change="${() => {
|
||||
this._fields ? (this._fields[index].exposed = !field.exposed) : '';
|
||||
}}"></uui-toggle>
|
||||
<br />`;
|
||||
})}
|
||||
</span>
|
||||
</uui-scroll-container>
|
||||
<div>
|
||||
<uui-button look="primary" label="Close sidebar" @click="${this._handleClose}">Close</uui-button>
|
||||
</div>
|
||||
</uui-dialog-layout>
|
||||
`;
|
||||
} else return html``;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-modal-layout-fields-settings': UmbModalLayoutFieldsSettingsElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
import { html, css } from 'lit';
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
import { UmbModalLayoutElement } from '@umbraco-cms/services';
|
||||
import { SearchResultsModel } from 'src/backoffice/dashboards/examine-management/examine-extension';
|
||||
|
||||
@customElement('umb-modal-layout-fields-viewer')
|
||||
export class UmbModalLayoutFieldsViewerElement extends UmbModalLayoutElement<SearchResultsModel> {
|
||||
static styles = [
|
||||
UUITextStyles,
|
||||
css`
|
||||
:host {
|
||||
display: relative;
|
||||
}
|
||||
uui-dialog-layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
background-color: white;
|
||||
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;
|
||||
}
|
||||
|
||||
span {
|
||||
display: block;
|
||||
padding-right: var(--uui-size-space-5);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
private _handleClose() {
|
||||
this.modalHandler?.close();
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.data) {
|
||||
return html`
|
||||
<uui-dialog-layout class="uui-text" headline="${this.data.name}">
|
||||
<uui-scroll-container id="field-viewer">
|
||||
<span>
|
||||
<uui-table>
|
||||
<uui-table-head>
|
||||
<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) => {
|
||||
return html`<uui-table-row>
|
||||
<uui-table-cell> ${cell.name} </uui-table-cell>
|
||||
<uui-table-cell> ${cell.values.join(', ')} </uui-table-cell>
|
||||
</uui-table-row>`;
|
||||
})}
|
||||
</uui-table>
|
||||
</span>
|
||||
</uui-scroll-container>
|
||||
<div>
|
||||
<uui-button look="primary" @click="${this._handleClose}">Close</uui-button>
|
||||
</div>
|
||||
</uui-dialog-layout>
|
||||
`;
|
||||
} else return html``;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-modal-layout-fields-viewer': UmbModalLayoutFieldsViewerElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { css, html, LitElement } from 'lit';
|
||||
import { customElement, state, property } from 'lit/decorators.js';
|
||||
|
||||
import { UUIButtonState } from '@umbraco-ui/uui-button';
|
||||
|
||||
import { UmbModalService, UmbNotificationService, UmbNotificationDefaultData } from '@umbraco-cms/services';
|
||||
|
||||
import { UmbContextConsumerMixin } from '@umbraco-cms/context-api';
|
||||
import './section-view-examine-searchers';
|
||||
|
||||
import { ApiError, ProblemDetails, Index, SearchResource } from '@umbraco-cms/backend-api';
|
||||
|
||||
@customElement('umb-dashboard-examine-index')
|
||||
export class UmbDashboardExamineIndexElement extends UmbContextConsumerMixin(LitElement) {
|
||||
static styles = [
|
||||
UUITextStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
uui-box,
|
||||
umb-dashboard-examine-searcher {
|
||||
margin-top: var(--uui-size-space-5);
|
||||
}
|
||||
|
||||
uui-box p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.flex {
|
||||
display: flex;
|
||||
}
|
||||
div.flex > uui-button {
|
||||
padding-left: var(--uui-size-space-4);
|
||||
height: 0;
|
||||
}
|
||||
|
||||
uui-input {
|
||||
width: 100%;
|
||||
margin-bottom: var(--uui-size-space-5);
|
||||
}
|
||||
|
||||
uui-table.info uui-table-row:first-child uui-table-cell {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
uui-table-head-cell {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
uui-table-row:last-child uui-table-cell {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
uui-icon {
|
||||
vertical-align: top;
|
||||
padding-right: var(--uui-size-space-5);
|
||||
}
|
||||
|
||||
.positive {
|
||||
color: var(--uui-color-positive);
|
||||
}
|
||||
.danger {
|
||||
color: var(--uui-color-danger);
|
||||
}
|
||||
|
||||
button {
|
||||
background: none;
|
||||
border: none;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
button.bright {
|
||||
font-style: italic;
|
||||
color: var(--uui-color-positive-emphasis);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@property()
|
||||
indexName!: string;
|
||||
|
||||
@state()
|
||||
private _buttonState?: UUIButtonState = undefined;
|
||||
|
||||
@state()
|
||||
private _indexData!: Index;
|
||||
|
||||
private _notificationService?: UmbNotificationService;
|
||||
private _modalService?: UmbModalService;
|
||||
|
||||
private async _getIndexData() {
|
||||
try {
|
||||
const index = await SearchResource.getSearchIndexByIndexName({ indexName: this.indexName });
|
||||
this._indexData = index;
|
||||
} catch (e) {
|
||||
if (e instanceof ApiError) {
|
||||
const error = e as ProblemDetails;
|
||||
const data: UmbNotificationDefaultData = { message: error.message ?? 'Could not fetch index' };
|
||||
this._notificationService?.peek('danger', { data });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.consumeAllContexts(['umbNotificationService', 'umbModalService'], (instances) => {
|
||||
this._notificationService = instances['umbNotificationService'];
|
||||
this._modalService = instances['umbModalService'];
|
||||
});
|
||||
}
|
||||
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this._getIndexData();
|
||||
}
|
||||
|
||||
private async _onRebuildHandler() {
|
||||
const modalHandler = this._modalService?.confirm({
|
||||
headline: `Rebuild ${this.indexName}`,
|
||||
content: html`
|
||||
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.
|
||||
`,
|
||||
color: 'danger',
|
||||
confirmLabel: 'Rebuild',
|
||||
});
|
||||
modalHandler?.onClose().then(({ confirmed }) => {
|
||||
if (confirmed) this._rebuild();
|
||||
});
|
||||
}
|
||||
private async _rebuild() {
|
||||
this._buttonState = 'waiting';
|
||||
if (this._indexData.name)
|
||||
try {
|
||||
await SearchResource.postSearchIndexByIndexNameRebuild({ indexName: this._indexData.name });
|
||||
this._buttonState = 'success';
|
||||
} catch (e) {
|
||||
this._buttonState = 'failed';
|
||||
if (e instanceof ApiError) {
|
||||
const error = e as ProblemDetails;
|
||||
const data: UmbNotificationDefaultData = { message: error.message ?? 'Rebuild error' };
|
||||
this._notificationService?.peek('danger', { data });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this._indexData) {
|
||||
return html` <uui-box headline="${this.indexName}">
|
||||
<p>
|
||||
<strong>Health Status</strong><br />
|
||||
The health status of the ${this._indexData.name} and if it can be read
|
||||
</p>
|
||||
<div>
|
||||
<uui-icon-essentials>
|
||||
<uui-icon
|
||||
name=${this._indexData.isHealthy ? `check` : `wrong`}
|
||||
class=${this._indexData.isHealthy ? 'positive' : 'danger'}>
|
||||
</uui-icon>
|
||||
</uui-icon-essentials>
|
||||
${this._indexData.healthStatus}
|
||||
</div>
|
||||
</uui-box>
|
||||
<umb-dashboard-examine-searcher searcherName="${this.indexName}"></umb-dashboard-examine-searcher>
|
||||
${this.renderPropertyList()} ${this.renderTools()}`;
|
||||
} else return html``;
|
||||
}
|
||||
|
||||
private renderPropertyList() {
|
||||
return html`<uui-box headline="Index info">
|
||||
<p>Lists the properties of the ${this._indexData.name}</p>
|
||||
<uui-table class="info">
|
||||
<uui-table-row>
|
||||
<uui-table-cell style="width:0px; font-weight: bold;"> documentCount </uui-table-cell>
|
||||
<uui-table-cell>${this._indexData.documentCount} </uui-table-cell>
|
||||
</uui-table-row>
|
||||
<uui-table-row>
|
||||
<uui-table-cell style="width:0px; font-weight: bold;"> fieldCount </uui-table-cell>
|
||||
<uui-table-cell>${this._indexData.fieldCount} </uui-table-cell>
|
||||
</uui-table-row>
|
||||
${this._indexData.providerProperties
|
||||
? Object.entries(this._indexData.providerProperties).map((entry) => {
|
||||
return html`<uui-table-row>
|
||||
<uui-table-cell style="width:0px; font-weight: bold;"> ${entry[0]} </uui-table-cell>
|
||||
<uui-table-cell clip-text> ${entry[1]} </uui-table-cell>
|
||||
</uui-table-row>`;
|
||||
})
|
||||
: ''}
|
||||
</uui-table>
|
||||
</uui-box>`;
|
||||
}
|
||||
|
||||
private renderTools() {
|
||||
return html` <uui-box headline="Tools">
|
||||
<p>Tools to manage the ${this._indexData.name}</p>
|
||||
<uui-button
|
||||
color="danger"
|
||||
look="primary"
|
||||
.state="${this._buttonState}"
|
||||
@click="${this._onRebuildHandler}"
|
||||
.disabled="${!this._indexData?.canRebuild}"
|
||||
label="Rebuild index">
|
||||
Rebuild
|
||||
</uui-button>
|
||||
</uui-box>`;
|
||||
}
|
||||
}
|
||||
|
||||
export default UmbDashboardExamineIndexElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-dashboard-examine-index': UmbDashboardExamineIndexElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { css, html, LitElement } from 'lit';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
|
||||
import { UmbModalService, UmbNotificationService, UmbNotificationDefaultData } from '@umbraco-cms/services';
|
||||
|
||||
import { UmbContextConsumerMixin } from '@umbraco-cms/context-api';
|
||||
import { ApiError, ProblemDetails, Searcher, Index, SearchResource } from '@umbraco-cms/backend-api';
|
||||
|
||||
@customElement('umb-dashboard-examine-overview')
|
||||
export class UmbDashboardExamineOverviewElement extends UmbContextConsumerMixin(LitElement) {
|
||||
static styles = [
|
||||
UUITextStyles,
|
||||
css`
|
||||
uui-box + uui-box {
|
||||
margin-top: var(--uui-size-space-5);
|
||||
}
|
||||
|
||||
uui-box p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--uui-color-text);
|
||||
background: transparent;
|
||||
border: none;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
uui-table-cell {
|
||||
line-height: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
uui-table-row:last-child uui-table-cell {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.positive {
|
||||
color: var(--uui-color-positive);
|
||||
}
|
||||
|
||||
.danger {
|
||||
color: var(--uui-color-danger);
|
||||
}
|
||||
|
||||
.not-found-message {
|
||||
font-style: italic;
|
||||
color: var(--uui-color-text-alt);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@state()
|
||||
private _indexers?: Index[];
|
||||
|
||||
@state()
|
||||
private _searchers?: Searcher[];
|
||||
|
||||
private _notificationService?: UmbNotificationService;
|
||||
private _modalService?: UmbModalService;
|
||||
|
||||
private async _getIndexers() {
|
||||
try {
|
||||
const indexers = await SearchResource.getSearchIndex({ take: 9999, skip: 0 });
|
||||
this._indexers = indexers.items;
|
||||
} catch (e) {
|
||||
if (e instanceof ApiError) {
|
||||
const error = e as ProblemDetails;
|
||||
const data: UmbNotificationDefaultData = { message: error.message ?? 'Could not fetch indexers' };
|
||||
this._notificationService?.peek('danger', { data });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async _getSearchers() {
|
||||
try {
|
||||
const searchers = await SearchResource.getSearchSearcher({ take: 9999, skip: 0 });
|
||||
this._searchers = searchers.items;
|
||||
} catch (e) {
|
||||
if (e instanceof ApiError) {
|
||||
const error = e as ProblemDetails;
|
||||
const data: UmbNotificationDefaultData = { message: error.message ?? 'Could not fetch searchers' };
|
||||
this._notificationService?.peek('danger', { data });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._getIndexers();
|
||||
this._getSearchers();
|
||||
|
||||
this.consumeAllContexts(['umbNotificationService', 'umbModalService'], (instances) => {
|
||||
this._notificationService = instances['umbNotificationService'];
|
||||
this._modalService = instances['umbModalService'];
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<uui-box headline="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
|
||||
</p>
|
||||
${this.renderIndexersList()}
|
||||
</uui-box>
|
||||
<uui-box headline="Searchers">
|
||||
<p>
|
||||
<strong>Configured Searchers</strong><br />
|
||||
Shows properties and tools for any configured Searcher (i.e. such as a multi-index searcher)
|
||||
</p>
|
||||
${this.renderSearchersList()}
|
||||
</uui-box>
|
||||
`;
|
||||
}
|
||||
|
||||
private renderIndexersList() {
|
||||
if (!this._indexers) return;
|
||||
return html` <uui-table class="overview">
|
||||
${this._indexers.map((index) => {
|
||||
return html`
|
||||
<uui-table-row>
|
||||
<uui-table-cell style="width:0px">
|
||||
<uui-icon-essentials>
|
||||
<uui-icon
|
||||
style="vertical-align: top"
|
||||
name=${index.isHealthy ? `check` : `wrong`}
|
||||
class=${index.isHealthy ? 'positive' : 'danger'}>
|
||||
</uui-icon>
|
||||
</uui-icon-essentials>
|
||||
</uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<a href="${window.location.href.replace(/\/+$/, '')}/index/${index.name}">${index.name}</a>
|
||||
</uui-table-cell>
|
||||
</uui-table-row>
|
||||
`;
|
||||
})}
|
||||
</uui-table>`;
|
||||
}
|
||||
|
||||
private renderSearchersList() {
|
||||
if (!this._searchers) return html`<span class="not-found-message">No searchers were found</span>`;
|
||||
return html`
|
||||
<uui-table class="overview2">
|
||||
${this._searchers.map((searcher) => {
|
||||
return html`<uui-table-row>
|
||||
<uui-table-cell style="width:0px">
|
||||
<uui-icon-essentials>
|
||||
<uui-icon
|
||||
style="vertical-align: top"
|
||||
name="info"></uui-icon>
|
||||
</uui-icon>
|
||||
</uui-icon-essentials>
|
||||
</uui-table-cell>
|
||||
<uui-table-cell><a href="${window.location.href.replace(/\/+$/, '')}/searcher/${searcher.name}">${searcher.name}</a>
|
||||
</uui-table-cell>
|
||||
</uui-table-row>`;
|
||||
})}
|
||||
</uui-table>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
export default UmbDashboardExamineOverviewElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-dashboard-examine-overview': UmbDashboardExamineOverviewElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { css, html, LitElement } from 'lit';
|
||||
import { customElement, state, query, property } from 'lit/decorators.js';
|
||||
|
||||
import { UmbModalService, UmbNotificationService, UmbNotificationDefaultData } from '@umbraco-cms/services';
|
||||
|
||||
import { UmbContextConsumerMixin } from '@umbraco-cms/context-api';
|
||||
|
||||
import { ApiError, ProblemDetails, SearchResult, SearchResource, Field } from '@umbraco-cms/backend-api';
|
||||
|
||||
import './modal-views/fields-viewer.element';
|
||||
import './modal-views/fields-settings.element';
|
||||
|
||||
interface ExposedSearchResultField {
|
||||
name?: string | null;
|
||||
exposed: boolean;
|
||||
}
|
||||
|
||||
@customElement('umb-dashboard-examine-searcher')
|
||||
export class UmbDashboardExamineSearcherElement extends UmbContextConsumerMixin(LitElement) {
|
||||
static styles = [
|
||||
UUITextStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
uui-box {
|
||||
margin-top: var(--uui-size-space-5);
|
||||
}
|
||||
|
||||
uui-box p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.flex {
|
||||
display: flex;
|
||||
}
|
||||
div.flex > uui-button {
|
||||
padding-left: var(--uui-size-space-4);
|
||||
height: 0;
|
||||
}
|
||||
|
||||
uui-input {
|
||||
width: 100%;
|
||||
margin-bottom: var(--uui-size-space-5);
|
||||
}
|
||||
|
||||
uui-table-head-cell {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
uui-table-row:last-child uui-table-cell {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
uui-table-cell {
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
button.bright {
|
||||
font-style: italic;
|
||||
color: var(--uui-color-positive-emphasis);
|
||||
}
|
||||
|
||||
.field-adder {
|
||||
line-height: 0;
|
||||
cursor: pointer;
|
||||
vertical-align: top;
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.table-container uui-scroll-container {
|
||||
padding-bottom: var(--uui-size-space-4);
|
||||
max-width: 100%;
|
||||
overflow-x: scroll;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.table-container {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
uui-tag {
|
||||
margin-block: var(--uui-size-5, 15px);
|
||||
}
|
||||
|
||||
.exposed-field uui-button {
|
||||
align-items: center;
|
||||
font-weight: normal;
|
||||
font-size: 10px;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
.exposed-field-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
private _notificationService?: UmbNotificationService;
|
||||
private _modalService?: UmbModalService;
|
||||
|
||||
@property()
|
||||
searcherName!: string;
|
||||
|
||||
@state()
|
||||
private _searchResults?: SearchResult[];
|
||||
|
||||
@state()
|
||||
private _exposedFields?: ExposedSearchResultField[];
|
||||
|
||||
@query('#search-input')
|
||||
private _searchInput!: HTMLInputElement;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.consumeAllContexts(['umbNotificationService', 'umbModalService'], (instances) => {
|
||||
this._notificationService = instances['umbNotificationService'];
|
||||
this._modalService = instances['umbModalService'];
|
||||
});
|
||||
}
|
||||
|
||||
private _onNameClick() {
|
||||
const data: UmbNotificationDefaultData = { message: 'TODO: Open editor for this' }; // TODO
|
||||
this._notificationService?.peek('warning', { data });
|
||||
}
|
||||
|
||||
private _onKeyPress(e: KeyboardEvent) {
|
||||
e.key == 'Enter' ? this._onSearch() : undefined;
|
||||
}
|
||||
|
||||
private async _onSearch() {
|
||||
if (!this._searchInput.value.length) return;
|
||||
try {
|
||||
const res = await SearchResource.getSearchSearcherBySearcherNameSearch({
|
||||
searcherName: this.searcherName,
|
||||
query: this._searchInput.value,
|
||||
take: 9999,
|
||||
skip: 0,
|
||||
});
|
||||
this._searchResults = res.items;
|
||||
this._updateFieldFilter();
|
||||
} catch (e) {
|
||||
if (e instanceof ApiError) {
|
||||
const error = e as ProblemDetails;
|
||||
const data: UmbNotificationDefaultData = { message: error.message ?? 'Could not fetch search results' };
|
||||
this._notificationService?.peek('danger', { data });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _updateFieldFilter() {
|
||||
this._searchResults?.map((doc) => {
|
||||
const document = doc.fields?.filter((field) => {
|
||||
return field.name?.toUpperCase() !== 'NODENAME';
|
||||
});
|
||||
if (document) {
|
||||
const newFieldNames = document.map((field) => {
|
||||
return field.name;
|
||||
});
|
||||
|
||||
this._exposedFields = this._exposedFields
|
||||
? this._exposedFields.filter((field) => {
|
||||
return { name: field.name, exposed: field.exposed };
|
||||
})
|
||||
: newFieldNames?.map((name) => {
|
||||
return { name, exposed: false };
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _onFieldFilterClick() {
|
||||
const modalHandler = this._modalService?.open('umb-modal-layout-fields-settings', {
|
||||
type: 'sidebar',
|
||||
size: 'small',
|
||||
data: { ...this._exposedFields },
|
||||
});
|
||||
modalHandler?.onClose().then(({ fields } = {}) => {
|
||||
if (!fields) return;
|
||||
this._exposedFields = fields;
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<uui-box headline="Search">
|
||||
<p>Search the ${this.searcherName} and view the results</p>
|
||||
<div class="flex">
|
||||
<uui-input
|
||||
id="search-input"
|
||||
placeholder="Type to filter..."
|
||||
label="Type to filter"
|
||||
@keypress=${this._onKeyPress}>
|
||||
</uui-input>
|
||||
<uui-button color="positive" look="primary" label="Search" @click="${this._onSearch}"> Search </uui-button>
|
||||
</div>
|
||||
${this.renderSearchResults()}
|
||||
</uui-box>
|
||||
`;
|
||||
}
|
||||
|
||||
private renderSearchResults() {
|
||||
if (this._searchResults?.length) {
|
||||
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>
|
||||
${this.renderHeadCells()}
|
||||
</uui-table-head>
|
||||
${this._searchResults?.map((rowData) => {
|
||||
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 editor for this document" @click="${this._onNameClick}">
|
||||
${rowData.fields?.find((field) => {
|
||||
if (field.name?.toUpperCase() === 'NODENAME') return field.values;
|
||||
else return;
|
||||
})?.values}
|
||||
</uui-button>
|
||||
</uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<uui-button
|
||||
class="bright"
|
||||
look="secondary"
|
||||
label="Open sidebar to see all fields"
|
||||
@click="${() =>
|
||||
this._modalService?.open('umb-modal-layout-fields-viewer', {
|
||||
type: 'sidebar',
|
||||
size: 'medium',
|
||||
data: { ...rowData },
|
||||
})}">
|
||||
${rowData.fields ? Object.keys(rowData.fields).length : ''} fields
|
||||
</uui-button>
|
||||
</uui-table-cell>
|
||||
${rowData.fields ? this.renderBodyCells(rowData.fields) : ''}
|
||||
</uui-table-row>`;
|
||||
})}
|
||||
</uui-table>
|
||||
</uui-scroll-container>
|
||||
<button class="field-adder" @click="${this._onFieldFilterClick}">
|
||||
<uui-icon-registry-essential>
|
||||
<uui-tag look="secondary">
|
||||
<uui-icon name="add"></uui-icon>
|
||||
</uui-tag>
|
||||
</uui-icon-registry-essential>
|
||||
</button>
|
||||
</div>`;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
renderHeadCells() {
|
||||
return html`${this._exposedFields?.map((field) => {
|
||||
return field.exposed
|
||||
? html`<uui-table-head-cell class="exposed-field">
|
||||
<div class="exposed-field-container">
|
||||
<span>${field.name}</span>
|
||||
<uui-button
|
||||
look="secondary"
|
||||
label="Close field ${field.name}"
|
||||
compact
|
||||
@click="${() => {
|
||||
this._exposedFields = this._exposedFields?.map((f) => {
|
||||
return f.name == field.name ? { name: f.name, exposed: false } : f;
|
||||
});
|
||||
}}"
|
||||
>x</uui-button
|
||||
>
|
||||
</div>
|
||||
</uui-table-head-cell>`
|
||||
: html``;
|
||||
})}`;
|
||||
}
|
||||
|
||||
renderBodyCells(cellData: Field[]) {
|
||||
return html`${this._exposedFields?.map((slot) => {
|
||||
return cellData.map((field) => {
|
||||
return slot.exposed && field.name == slot.name
|
||||
? html`<uui-table-cell clip-text>${field.values}</uui-table-cell>`
|
||||
: html``;
|
||||
});
|
||||
})}`;
|
||||
}
|
||||
}
|
||||
|
||||
export default UmbDashboardExamineSearcherElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-dashboard-examine-searcher': UmbDashboardExamineSearcherElement;
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ export class UmbSectionDashboardsElement extends UmbContextConsumerMixin(UmbObse
|
||||
}
|
||||
|
||||
#scroll-container {
|
||||
width: calc(-300px + 100vw);
|
||||
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.
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { handlers as userHandlers } from './domains/user.handlers';
|
||||
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';
|
||||
|
||||
const handlers = [
|
||||
serverHandlers.serverVersionHandler,
|
||||
@@ -26,6 +27,7 @@ const handlers = [
|
||||
...publishedStatusHandlers,
|
||||
...usersHandlers,
|
||||
...userGroupsHandlers,
|
||||
...examineManagementHandlers,
|
||||
];
|
||||
|
||||
switch (import.meta.env.VITE_UMBRACO_INSTALL_STATUS) {
|
||||
|
||||
145
src/Umbraco.Web.UI.Client/src/core/mocks/data/examine.data.ts
Normal file
145
src/Umbraco.Web.UI.Client/src/core/mocks/data/examine.data.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
import { Index, PagedIndex, SearchResult } from '@umbraco-cms/backend-api';
|
||||
|
||||
export function getIndexByName(indexName: string) {
|
||||
return Indexers.find((index) => {
|
||||
if (index.name) return index.name.toLocaleLowerCase() == indexName.toLocaleLowerCase();
|
||||
else return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
export function getSearchResultsMockData(): SearchResult[] {
|
||||
return searchResultMockData;
|
||||
}
|
||||
|
||||
export const Indexers: Index[] = [
|
||||
{
|
||||
name: 'ExternalIndex',
|
||||
canRebuild: true,
|
||||
healthStatus: 'Healthy',
|
||||
isHealthy: true,
|
||||
documentCount: 0,
|
||||
fieldCount: 0,
|
||||
providerProperties: {
|
||||
CommitCount: 0,
|
||||
DefaultAnalyzer: 'StandardAnalyzer',
|
||||
|
||||
LuceneDirectory: 'SimpleFSDirectory',
|
||||
LuceneIndexFolder: '/ /umbraco /data /temp /examineindexes /externalindex',
|
||||
DirectoryFactory:
|
||||
'Umbraco.Cms.Infrastructure.Examine.ConfigurationEnabledDirectoryFactory, Umbraco.Examine.Lucene, Version=10.2.0.0, Culture=neutral, PublicKeyToken=null',
|
||||
EnableDefaultEventHandler: true,
|
||||
PublishedValuesOnly: true,
|
||||
SupportProtectedContent: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'InternalIndex',
|
||||
canRebuild: true,
|
||||
healthStatus: 'Healthy',
|
||||
isHealthy: true,
|
||||
documentCount: 0,
|
||||
fieldCount: 0,
|
||||
providerProperties: {
|
||||
CommitCount: 0,
|
||||
DefaultAnalyzer: 'CultureInvariantWhitespaceAnalyzer',
|
||||
LuceneDirectory: 'SimpleFSDirectory',
|
||||
LuceneIndexFolder: '/ /umbraco /data /temp /examineindexes /internalindex',
|
||||
DirectoryFactory:
|
||||
'Umbraco.Cms.Infrastructure.Examine.ConfigurationEnabledDirectoryFactory, Umbraco.Examine.Lucene, Version=10.2.0.0, Culture=neutral, PublicKeyToken=null',
|
||||
EnableDefaultEventHandler: true,
|
||||
PublishedValuesOnly: false,
|
||||
SupportProtectedContent: true,
|
||||
IncludeFields: ['id', 'nodeName', 'updateDate', 'loginName', 'email', '__Key'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'MemberIndex',
|
||||
canRebuild: true,
|
||||
healthStatus: 'Healthy',
|
||||
isHealthy: true,
|
||||
fieldCount: 0,
|
||||
documentCount: 0,
|
||||
providerProperties: {
|
||||
CommitCount: 0,
|
||||
DefaultAnalyzer: 'CultureInvariantWhitespaceAnalyzer',
|
||||
DirectoryFactory:
|
||||
'Umbraco.Cms.Infrastructure.Examine.ConfigurationEnabledDirectoryFactory, Umbraco.Examine.Lucene, Version=10.2.0.0, Culture=neutral, PublicKeyToken=null',
|
||||
EnableDefaultEventHandler: true,
|
||||
IncludeFields: ['id', 'nodeName', 'updateDate', 'loginName', 'email', '__Key'],
|
||||
LuceneDirectory: 'SimpleFSDirectory',
|
||||
LuceneIndexFolder: '/ /umbraco /data /temp /examineindexes /membersindex',
|
||||
PublishedValuesOnly: false,
|
||||
SupportProtectedContent: false,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const PagedIndexers: PagedIndex = {
|
||||
items: Indexers,
|
||||
total: 0,
|
||||
};
|
||||
|
||||
export const searchResultMockData: SearchResult[] = [
|
||||
{
|
||||
id: '1',
|
||||
score: 1,
|
||||
fields: [
|
||||
{ name: '__Icon', values: ['icon-document'] },
|
||||
{ name: '__IndexType', values: ['content'] },
|
||||
{ name: '__Key', values: ['903wyrqwjf-33wrefef-wefwef3-erw'] },
|
||||
{ name: '__NodeId', values: ['1059'] },
|
||||
{ name: '__NodeTypeAlias', values: ['Home'] },
|
||||
{ name: '__Path', values: ['-1.345'] },
|
||||
{ name: '__Published', values: ['y'] },
|
||||
{ name: '__VariesByCulture', values: ['n'] },
|
||||
{ name: 'createDate', values: ['30752539'] },
|
||||
{ name: 'creatorId', values: ['-1'] },
|
||||
{ name: 'creatorName', values: ['Lone'] },
|
||||
{ name: 'icon', values: ['icon-document'] },
|
||||
{ name: 'id', values: ['1059'] },
|
||||
{ name: 'image', values: ['34343-3wdsw-sd35-3s', 'afewr-q5-23rd-3red'] },
|
||||
{ name: 'level', values: ['1'] },
|
||||
{ name: 'nodeName', values: ['Just a picture'] },
|
||||
{ name: 'nodeType', values: ['1056'] },
|
||||
{ name: 'parentID', values: ['-1'] },
|
||||
{ name: 'path', values: ['-3.325'] },
|
||||
{ name: 'sortOrder', values: ['1'] },
|
||||
{ name: 'templateID', values: ['1055'] },
|
||||
{ name: 'updateDate', values: ['9573024532945'] },
|
||||
{ name: 'urlName', values: ['just-a-picture'] },
|
||||
{ name: 'writerID', values: ['-1'] },
|
||||
{ name: 'writerName', values: ['Lone'] },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
score: 0.9,
|
||||
fields: [
|
||||
{ name: '__Icon', values: ['icon-document'] },
|
||||
{ name: '__IndexType', values: ['content'] },
|
||||
{ name: '__Key', values: ['903wyrqwjf-33wrefef-wefwef3-erw'] },
|
||||
{ name: '__NodeId', values: ['1059'] },
|
||||
{ name: '__NodeTypeAlias', values: ['Home'] },
|
||||
{ name: '__Path', values: ['-1.345'] },
|
||||
{ name: '__Published', values: ['y'] },
|
||||
{ name: '__VariesByCulture', values: ['n'] },
|
||||
{ name: 'createDate', values: ['30752539'] },
|
||||
{ name: 'creatorId', values: ['-1'] },
|
||||
{ name: 'creatorName', values: ['Lone'] },
|
||||
{ name: 'icon', values: ['icon-document'] },
|
||||
{ name: 'id', values: ['1059'] },
|
||||
{ name: 'image', values: ['34343-3wdsw-sd35-3s', 'afewr-q5-23rd-3red'] },
|
||||
{ name: 'level', values: ['1'] },
|
||||
{ name: 'nodeName', values: ['Just a picture'] },
|
||||
{ name: 'nodeType', values: ['1056'] },
|
||||
{ name: 'parentID', values: ['-1'] },
|
||||
{ name: 'path', values: ['-3.325'] },
|
||||
{ name: 'sortOrder', values: ['1'] },
|
||||
{ name: 'templateID', values: ['1055'] },
|
||||
{ name: 'updateDate', values: ['9573024532945'] },
|
||||
{ name: 'urlName', values: ['just-a-picture'] },
|
||||
{ name: 'writerID', values: ['-1'] },
|
||||
{ name: 'writerName', values: ['Lone'] },
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,73 @@
|
||||
import { rest } from 'msw';
|
||||
import { searchResultMockData, getIndexByName, PagedIndexers } from '../data/examine.data';
|
||||
|
||||
import { umbracoPath } from '@umbraco-cms/utils';
|
||||
import { Index, PagedIndex, PagedSearcher, PagedSearchResult } from '@umbraco-cms/backend-api';
|
||||
|
||||
export const handlers = [
|
||||
rest.get(umbracoPath('/search/index'), (_req, res, ctx) => {
|
||||
return res(
|
||||
// Respond with a 200 status code
|
||||
ctx.status(200),
|
||||
ctx.json<PagedIndex>(PagedIndexers)
|
||||
);
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath('/search/index/:indexName'), (_req, res, ctx) => {
|
||||
const indexName = _req.params.indexName as string;
|
||||
|
||||
if (!indexName) return;
|
||||
const indexFound = getIndexByName(indexName);
|
||||
|
||||
if (indexFound) {
|
||||
return res(ctx.status(200), ctx.json<Index>(indexFound));
|
||||
} else {
|
||||
return res(ctx.status(404));
|
||||
}
|
||||
}),
|
||||
|
||||
rest.post(umbracoPath('/search/index/:indexName/rebuild'), async (_req, res, ctx) => {
|
||||
await new Promise((resolve) => setTimeout(resolve, (Math.random() + 1) * 1000)); // simulate a delay of 1-2 seconds
|
||||
|
||||
const indexName = _req.params.indexName as string;
|
||||
if (!indexName) return;
|
||||
|
||||
const indexFound = getIndexByName(indexName);
|
||||
if (indexFound) {
|
||||
return res(ctx.status(201));
|
||||
} else {
|
||||
return res(ctx.status(404));
|
||||
}
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath('/search/searcher'), (_req, res, ctx) => {
|
||||
return res(
|
||||
ctx.status(200),
|
||||
ctx.json<PagedSearcher>({
|
||||
total: 0,
|
||||
items: [{ name: 'ExternalSearcher' }, { name: 'InternalSearcher' }, { name: 'InternalMemberSearcher' }],
|
||||
})
|
||||
);
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath('/search/searcher/:searcherName/search'), (_req, res, ctx) => {
|
||||
const query = _req.url.searchParams.get('query');
|
||||
const take = _req.url.searchParams.get('take');
|
||||
|
||||
const searcherName = _req.params.searcherName as string;
|
||||
|
||||
if (!searcherName || !query) return;
|
||||
|
||||
if (searcherName) {
|
||||
return res(
|
||||
ctx.status(200),
|
||||
ctx.json<PagedSearchResult>({
|
||||
total: 0,
|
||||
items: searchResultMockData,
|
||||
})
|
||||
);
|
||||
} else {
|
||||
return res(ctx.status(404));
|
||||
}
|
||||
}),
|
||||
];
|
||||
@@ -10,6 +10,8 @@ import { handlers as userHandlers } from './domains/user.handlers';
|
||||
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';
|
||||
|
||||
export const handlers = [
|
||||
serverHandlers.serverRunningHandler,
|
||||
serverHandlers.serverVersionHandler,
|
||||
@@ -24,4 +26,5 @@ export const handlers = [
|
||||
...telemetryHandlers,
|
||||
...publishedStatusHandlers,
|
||||
...treeHandlers,
|
||||
...examineManagementHandlers,
|
||||
];
|
||||
|
||||
7
src/Umbraco.Web.UI.Client/src/core/services/index.ts
Normal file
7
src/Umbraco.Web.UI.Client/src/core/services/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
export * from './modal';
|
||||
export { UmbNotificationService } from './notification';
|
||||
export type { UmbNotificationDefaultData } from './notification/layouts/default';
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './modal.service';
|
||||
export * from './modal-handler';
|
||||
export * from './layouts/modal-layout.element';
|
||||
|
||||
@@ -31,7 +31,8 @@
|
||||
"@umbraco-cms/extensions-registry": ["src/core/extensions-registry"],
|
||||
"@umbraco-cms/observable-api": ["src/core/observable-api"],
|
||||
"@umbraco-cms/utils": ["src/core/utils"],
|
||||
"@umbraco-cms/test-utils": ["src/core/test-utils"]
|
||||
"@umbraco-cms/test-utils": ["src/core/test-utils"],
|
||||
"@umbraco-cms/services": ["src/core/services"]
|
||||
},
|
||||
},
|
||||
"include": [
|
||||
|
||||
Reference in New Issue
Block a user