Merge branch 'main' into feature/dashboard-health-check
This commit is contained in:
@@ -1,17 +1,330 @@
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { css, html, LitElement } from 'lit';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
import { css, html, nothing } from 'lit';
|
||||
import { customElement, state, query, property } from 'lit/decorators.js';
|
||||
import { UUIButtonState, UUIPaginationElement, UUIPaginationEvent } from '@umbraco-ui/uui';
|
||||
import { UmbModalService, UMB_MODAL_SERVICE_CONTEXT_TOKEN } from '../../../../core/modal';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import { RedirectManagementResource, RedirectStatus, RedirectUrl } from '@umbraco-cms/backend-api';
|
||||
import { tryExecuteAndNotify } from '@umbraco-cms/resources';
|
||||
|
||||
@customElement('umb-dashboard-redirect-management')
|
||||
export class UmbDashboardRedirectManagementElement extends LitElement {
|
||||
static styles = [UUITextStyles, css``];
|
||||
export class UmbDashboardRedirectManagementElement extends UmbLitElement {
|
||||
static styles = [
|
||||
UUITextStyles,
|
||||
css`
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.actions uui-icon {
|
||||
transform: translateX(50%);
|
||||
}
|
||||
|
||||
uui-table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
uui-table-head-cell:nth-child(2*n) {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
uui-table-head-cell:last-child,
|
||||
uui-table-cell:last-child {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
uui-table uui-icon {
|
||||
vertical-align: sub;
|
||||
}
|
||||
uui-pagination {
|
||||
display: inline-block;
|
||||
}
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: var(--uui-size-space-5);
|
||||
}
|
||||
|
||||
.trackerDisabled {
|
||||
position: relative;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.trackerDisabled::after {
|
||||
content: '';
|
||||
background-color: rgba(250, 250, 250, 0.7);
|
||||
position: absolute;
|
||||
border-radius: 2px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--uui-color-interactive);
|
||||
}
|
||||
a:hover,
|
||||
a:focus {
|
||||
color: var(--uui-color-interactive-emphasis);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@property({ type: Number, attribute: 'items-per-page' })
|
||||
itemsPerPage = 20;
|
||||
|
||||
@state()
|
||||
private _redirectData?: RedirectUrl[];
|
||||
|
||||
@state()
|
||||
private _trackerStatus = true;
|
||||
|
||||
@state()
|
||||
private _currentPage = 1;
|
||||
|
||||
@state()
|
||||
private _total?: number;
|
||||
|
||||
@state()
|
||||
private _buttonState: UUIButtonState;
|
||||
|
||||
@state()
|
||||
private _filter?: string;
|
||||
|
||||
@query('#search-input')
|
||||
private _searchField!: HTMLInputElement;
|
||||
|
||||
@query('uui-pagination')
|
||||
private _pagination?: UUIPaginationElement;
|
||||
|
||||
private _modalService?: UmbModalService;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.consumeContext(UMB_MODAL_SERVICE_CONTEXT_TOKEN, (_instance) => {
|
||||
this._modalService = _instance;
|
||||
});
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this._getTrackerStatus();
|
||||
this._getRedirectData();
|
||||
}
|
||||
|
||||
private async _getTrackerStatus() {
|
||||
const { data } = await tryExecuteAndNotify(this, RedirectManagementResource.getRedirectManagementStatus());
|
||||
if (data && data.status) this._trackerStatus = data.status === RedirectStatus.ENABLED ? true : false;
|
||||
}
|
||||
|
||||
private _removeRedirectHandler(data: RedirectUrl) {
|
||||
const modalHandler = this._modalService?.confirm({
|
||||
headline: 'Delete',
|
||||
content: html`
|
||||
<div style="width:300px">
|
||||
<p>This will remove the redirect</p>
|
||||
Original URL: <strong>${data.originalUrl}</strong><br />
|
||||
Redirected To: <strong>${data.destinationUrl}</strong>
|
||||
<p>Are you sure you want to delete?</p>
|
||||
</div>
|
||||
`,
|
||||
color: 'danger',
|
||||
confirmLabel: 'Delete',
|
||||
});
|
||||
modalHandler?.onClose().then(({ confirmed }) => {
|
||||
if (confirmed) this._removeRedirect(data);
|
||||
});
|
||||
}
|
||||
|
||||
private async _removeRedirect(r: RedirectUrl) {
|
||||
if (!r.key) return;
|
||||
const res = await tryExecuteAndNotify(
|
||||
this,
|
||||
RedirectManagementResource.deleteRedirectManagementByKey({ key: r.key })
|
||||
);
|
||||
if (!res.error) {
|
||||
// or just run a this._getRedirectData() again?
|
||||
this.shadowRoot?.getElementById(`redirect-key-${r.key}`)?.remove();
|
||||
}
|
||||
}
|
||||
|
||||
private _disableRedirectHandler() {
|
||||
const modalHandler = this._modalService?.confirm({
|
||||
headline: 'Disable URL tracker',
|
||||
content: html`Are you sure you want to disable the URL tracker?`,
|
||||
color: 'danger',
|
||||
confirmLabel: 'Disable',
|
||||
});
|
||||
modalHandler?.onClose().then(({ confirmed }) => {
|
||||
if (confirmed) this._toggleRedirect();
|
||||
});
|
||||
}
|
||||
|
||||
private async _toggleRedirect() {
|
||||
const { error } = await tryExecuteAndNotify(
|
||||
this,
|
||||
RedirectManagementResource.postRedirectManagementStatus({ status: RedirectStatus.ENABLED })
|
||||
);
|
||||
|
||||
if (!error) {
|
||||
this._trackerStatus = !this._trackerStatus;
|
||||
}
|
||||
}
|
||||
|
||||
private _inputHandler(pressed: KeyboardEvent) {
|
||||
if (pressed.key === 'Enter') this._searchHandler();
|
||||
}
|
||||
|
||||
private async _searchHandler() {
|
||||
this._filter = this._searchField.value;
|
||||
if (this._pagination) this._pagination.current = 1;
|
||||
this._currentPage = 1;
|
||||
if (this._filter.length) {
|
||||
this._buttonState = 'waiting';
|
||||
}
|
||||
this._getRedirectData();
|
||||
}
|
||||
|
||||
private _onPageChange(event: UUIPaginationEvent) {
|
||||
if (this._currentPage === event.target.current) return;
|
||||
this._currentPage = event.target.current;
|
||||
this._getRedirectData();
|
||||
}
|
||||
|
||||
private async _getRedirectData() {
|
||||
const skip = this._currentPage * this.itemsPerPage - this.itemsPerPage;
|
||||
const { data } = await tryExecuteAndNotify(
|
||||
this,
|
||||
RedirectManagementResource.getRedirectManagement({ filter: this._filter, take: this.itemsPerPage, skip })
|
||||
);
|
||||
if (data) {
|
||||
this._total = data?.total;
|
||||
this._redirectData = data?.items;
|
||||
if (this._filter?.length) this._buttonState = 'success';
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<uui-box>
|
||||
<h1>Redirect Management</h1>
|
||||
return html`<div class="actions">
|
||||
${this._trackerStatus
|
||||
? html`<div>
|
||||
<uui-input
|
||||
id="search-input"
|
||||
placeholder="Original URL"
|
||||
label="input for search"
|
||||
@keypress="${this._inputHandler}">
|
||||
</uui-input>
|
||||
<uui-button
|
||||
id="search-button"
|
||||
look="primary"
|
||||
color="positive"
|
||||
label="search"
|
||||
.state="${this._buttonState}"
|
||||
@click="${this._searchHandler}">
|
||||
Search<uui-icon name="umb:search"></uui-icon>
|
||||
</uui-button>
|
||||
</div>
|
||||
<uui-button
|
||||
label="Disable URL tracker"
|
||||
look="outline"
|
||||
color="danger"
|
||||
@click="${this._disableRedirectHandler}">
|
||||
Disable URL tracker
|
||||
</uui-button> `
|
||||
: html`<uui-button
|
||||
label="Enable URL tracker"
|
||||
look="primary"
|
||||
color="positive"
|
||||
@click="${this._toggleRedirect}">
|
||||
Enable URL tracker
|
||||
</uui-button>`}
|
||||
</div>
|
||||
|
||||
${this._total && this._total > 0
|
||||
? html`<div class="wrapper ${this._trackerStatus ? 'trackerEnabled' : 'trackerDisabled'}">
|
||||
${this.renderTable()}
|
||||
</div>`
|
||||
: this._filter?.length
|
||||
? this._renderZeroResults()
|
||||
: this.renderNoRedirects()} `;
|
||||
}
|
||||
|
||||
private _renderZeroResults() {
|
||||
return html`<uui-box>
|
||||
<strong>No redirects matching this search criteria</strong>
|
||||
<p>Double check your search for any error or spelling mistakes.</p>
|
||||
</uui-box>`;
|
||||
}
|
||||
|
||||
private renderNoRedirects() {
|
||||
return html`<uui-box>
|
||||
<strong>No redirects have been made</strong>
|
||||
<p>When a published page gets renamed or moved, a redirect will automatically be made to the new page.</p>
|
||||
</uui-box>`;
|
||||
}
|
||||
|
||||
private renderTable() {
|
||||
return html`<uui-box style="--uui-box-default-padding: 0;">
|
||||
<uui-table>
|
||||
<uui-table-head>
|
||||
<uui-table-head-cell style="width:10%;">Culture</uui-table-head-cell>
|
||||
<uui-table-head-cell>Original URL</uui-table-head-cell>
|
||||
<uui-table-head-cell style="width:10%;"></uui-table-head-cell>
|
||||
<uui-table-head-cell>Redirected To</uui-table-head-cell>
|
||||
<uui-table-head-cell style="width:10%;">Actions</uui-table-head-cell>
|
||||
</uui-table-head>
|
||||
${this._redirectData?.map((data) => {
|
||||
return html` <uui-table-row id="redirect-key-${data.key}">
|
||||
<uui-table-cell> ${data.culture || '*'} </uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<a href="${data.originalUrl || '#'}" target="_blank"> ${data.originalUrl}</a>
|
||||
<uui-icon name="umb:out"></uui-icon>
|
||||
</uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<uui-icon name="umb:arrow-right"></uui-icon>
|
||||
</uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<a href="${data.destinationUrl || '#'}" target="_blank"> ${data.destinationUrl}</a>
|
||||
<uui-icon name="umb:out"></uui-icon>
|
||||
</uui-table-cell>
|
||||
<uui-table-cell>
|
||||
<uui-action-bar style="justify-self: left;">
|
||||
<uui-button
|
||||
label="Delete"
|
||||
look="secondary"
|
||||
.disabled=${!this._trackerStatus}
|
||||
@click="${() => this._removeRedirectHandler(data)}">
|
||||
<uui-icon name="delete"></uui-icon>
|
||||
</uui-button>
|
||||
</uui-action-bar>
|
||||
</uui-table-cell>
|
||||
</uui-table-row>`;
|
||||
})}
|
||||
</uui-table>
|
||||
</uui-box>
|
||||
`;
|
||||
${this._renderPagination()}
|
||||
</uui-scroll-container
|
||||
>`;
|
||||
}
|
||||
|
||||
private _renderPagination() {
|
||||
if (!this._total) return nothing;
|
||||
|
||||
const totalPages = Math.ceil(this._total / this.itemsPerPage);
|
||||
|
||||
if (totalPages <= 1) return nothing;
|
||||
|
||||
return html`<div class="pagination">
|
||||
<uui-pagination .total=${totalPages} @change="${this._onPageChange}"></uui-pagination>
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { expect, fixture, html } from '@open-wc/testing';
|
||||
|
||||
import { UmbDashboardRedirectManagementElement } from './dashboard-redirect-management.element';
|
||||
import { defaultA11yConfig } from '@umbraco-cms/test-utils';
|
||||
|
||||
describe('UmbDashboardRedirectManagement', () => {
|
||||
let element: UmbDashboardRedirectManagementElement;
|
||||
|
||||
beforeEach(async () => {
|
||||
element = await fixture(html`<umb-dashboard-redirect-management></umb-dashboard-redirect-management>`);
|
||||
});
|
||||
|
||||
it('is defined with its own instance', () => {
|
||||
expect(element).to.be.instanceOf(UmbDashboardRedirectManagementElement);
|
||||
});
|
||||
|
||||
it('passes the a11y audit', async () => {
|
||||
await expect(element).to.be.accessible(defaultA11yConfig);
|
||||
});
|
||||
});
|
||||
@@ -4,12 +4,9 @@ import { customElement, state } from 'lit/decorators.js';
|
||||
import { IRoutingInfo } from 'router-slot';
|
||||
import { first, map } from 'rxjs';
|
||||
import { UmbSectionContext, UMB_SECTION_CONTEXT_TOKEN } from '../section.context';
|
||||
import { createExtensionElement , umbExtensionsRegistry } from '@umbraco-cms/extensions-api';
|
||||
import type {
|
||||
ManifestDashboard,
|
||||
ManifestDashboardCollection,
|
||||
ManifestWithMeta,
|
||||
} from '@umbraco-cms/models';
|
||||
import { createExtensionElement, umbExtensionsRegistry } from '@umbraco-cms/extensions-api';
|
||||
import type { ManifestDashboard, ManifestDashboardCollection, ManifestWithMeta } from '@umbraco-cms/models';
|
||||
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
|
||||
@customElement('umb-section-dashboards')
|
||||
@@ -29,7 +26,7 @@ export class UmbSectionDashboardsElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
#scroll-container {
|
||||
flex:1;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
#router-slot {
|
||||
|
||||
@@ -19,6 +19,7 @@ import { handlers as dictionaryHandlers } from './domains/dictionary.handlers';
|
||||
import { handlers as mediaTypeHandlers } from './domains/media-type.handlers';
|
||||
import { handlers as memberGroupHandlers } from './domains/member-group.handlers';
|
||||
import { handlers as memberTypeHandlers } from './domains/member-type.handlers';
|
||||
import { handlers as redirectManagement } from './domains/redirect-management.handlers';
|
||||
|
||||
const handlers = [
|
||||
serverHandlers.serverVersionHandler,
|
||||
@@ -42,6 +43,7 @@ const handlers = [
|
||||
...healthCheckHandlers,
|
||||
...profilingHandlers,
|
||||
...dictionaryHandlers,
|
||||
...redirectManagement,
|
||||
];
|
||||
|
||||
switch (import.meta.env.VITE_UMBRACO_INSTALL_STATUS) {
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
import { rest } from 'msw';
|
||||
import { umbracoPath } from '@umbraco-cms/utils';
|
||||
import { PagedRedirectUrl, RedirectUrl, RedirectStatus, RedirectUrlStatus } from '@umbraco-cms/backend-api';
|
||||
|
||||
export const handlers = [
|
||||
rest.get(umbracoPath('/redirect-management'), (_req, res, ctx) => {
|
||||
const filter = _req.url.searchParams.get('filter');
|
||||
const skip = parseInt(_req.url.searchParams.get('skip') ?? '0', 10);
|
||||
const take = parseInt(_req.url.searchParams.get('take') ?? '20', 10);
|
||||
|
||||
if (filter) {
|
||||
const filtered: RedirectUrl[] = [];
|
||||
|
||||
PagedRedirectUrlData.items.forEach((item) => {
|
||||
if (item.originalUrl?.includes(filter)) filtered.push(item);
|
||||
});
|
||||
const filteredPagedData: PagedRedirectUrl = {
|
||||
total: filtered.length,
|
||||
items: filtered.slice(skip, skip + take),
|
||||
};
|
||||
return res(ctx.status(200), ctx.json<PagedRedirectUrl>(filteredPagedData));
|
||||
} else {
|
||||
const items = PagedRedirectUrlData.items.slice(skip, skip + take);
|
||||
|
||||
const PagedData: PagedRedirectUrl = {
|
||||
total: PagedRedirectUrlData.total,
|
||||
items,
|
||||
};
|
||||
return res(ctx.status(200), ctx.json<PagedRedirectUrl>(PagedData));
|
||||
}
|
||||
}),
|
||||
|
||||
rest.get(umbracoPath('/redirect-management/:key'), async (_req, res, ctx) => {
|
||||
const key = _req.params.key as string;
|
||||
if (!key) return res(ctx.status(404));
|
||||
if (key === 'status') return res(ctx.status(200), ctx.json<RedirectUrlStatus>(UrlTracker));
|
||||
|
||||
const PagedRedirectUrlObject = _getRedirectUrlByKey(key);
|
||||
|
||||
return res(ctx.status(200), ctx.json<PagedRedirectUrl>(PagedRedirectUrlObject));
|
||||
}),
|
||||
|
||||
rest.delete(umbracoPath('/redirect-management/:key'), async (_req, res, ctx) => {
|
||||
const key = _req.params.key as string;
|
||||
if (!key) return res(ctx.status(404));
|
||||
|
||||
const PagedRedirectUrlObject = _deleteRedirectUrlByKey(key);
|
||||
|
||||
return res(ctx.status(200), ctx.json<any>(PagedRedirectUrlObject));
|
||||
}),
|
||||
|
||||
/*rest.get(umbracoPath('/redirect-management/status'), (_req, res, ctx) => {
|
||||
return res(ctx.status(200), ctx.json<RedirectUrlStatus>(UrlTracker));
|
||||
}),*/
|
||||
|
||||
rest.post(umbracoPath('/redirect-management/status'), async (_req, res, ctx) => {
|
||||
UrlTracker.status = UrlTracker.status === RedirectStatus.ENABLED ? RedirectStatus.DISABLED : RedirectStatus.ENABLED;
|
||||
return res(ctx.status(200), ctx.json<any>(UrlTracker.status));
|
||||
}),
|
||||
];
|
||||
|
||||
// Mock Data
|
||||
|
||||
const UrlTracker: RedirectUrlStatus = { status: RedirectStatus.ENABLED, userIsAdmin: true };
|
||||
|
||||
const _getRedirectUrlByKey = (key: string) => {
|
||||
const PagedResult: PagedRedirectUrl = {
|
||||
total: 0,
|
||||
items: [],
|
||||
};
|
||||
RedirectUrlData.forEach((data) => {
|
||||
if (data.key?.includes(key)) {
|
||||
PagedResult.items.push(data);
|
||||
PagedResult.total++;
|
||||
}
|
||||
});
|
||||
return PagedResult;
|
||||
};
|
||||
|
||||
const _deleteRedirectUrlByKey = (key: string) => {
|
||||
const index = RedirectUrlData.findIndex((data) => data.key === key);
|
||||
if (index > -1) RedirectUrlData.splice(index, 1);
|
||||
const PagedResult: PagedRedirectUrl = {
|
||||
items: RedirectUrlData,
|
||||
total: RedirectUrlData.length,
|
||||
};
|
||||
return PagedResult;
|
||||
};
|
||||
|
||||
const RedirectUrlData: RedirectUrl[] = [
|
||||
{
|
||||
key: '1',
|
||||
created: '2022-12-05T13:59:43.6827244',
|
||||
destinationUrl: 'kitty.com',
|
||||
originalUrl: 'kitty.dk',
|
||||
contentKey: '7191c911-6747-4824-849e-5208e2b31d9f2',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
created: '2022-13-05T13:59:43.6827244',
|
||||
destinationUrl: 'umbraco.com',
|
||||
originalUrl: 'umbraco.dk',
|
||||
contentKey: '7191c911-6747-4824-849e-5208e2b31d9f',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
created: '2022-12-05T13:59:43.6827244',
|
||||
destinationUrl: 'uui.umbraco.com',
|
||||
originalUrl: 'uui.umbraco.dk',
|
||||
contentKey: '7191c911-6747-4824-849e-5208e2b31d9f23',
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
created: '2022-13-05T13:59:43.6827244',
|
||||
destinationUrl: 'umbracoffee.com',
|
||||
originalUrl: 'umbracoffee.dk',
|
||||
contentKey: '7191c911-6747-4824-849e-5208e2b31d9fdsaa',
|
||||
},
|
||||
{
|
||||
key: '5',
|
||||
created: '2022-12-05T13:59:43.6827244',
|
||||
destinationUrl: 'section/settings',
|
||||
originalUrl: 'section/settings/123',
|
||||
contentKey: '7191c911-6747-4824-849e-5208e2b31d9f2e23',
|
||||
},
|
||||
{
|
||||
key: '6',
|
||||
created: '2022-13-05T13:59:43.6827244',
|
||||
destinationUrl: 'dxp.com',
|
||||
originalUrl: 'dxp.dk',
|
||||
contentKey: '7191c911-6747-4824-849e-5208e2b31d9fsafsfd',
|
||||
},
|
||||
{
|
||||
key: '7',
|
||||
created: '2022-12-05T13:59:43.6827244',
|
||||
destinationUrl: 'google.com',
|
||||
originalUrl: 'google.dk',
|
||||
contentKey: '7191c911-6747-4824-849e-5208e2b31d9f2cxza',
|
||||
},
|
||||
{
|
||||
key: '8',
|
||||
created: '2022-13-05T13:59:43.6827244',
|
||||
destinationUrl: 'unicorns.com',
|
||||
originalUrl: 'unicorns.dk',
|
||||
contentKey: '7191c911-6747-4824-849e-5208e2b31d9fweds',
|
||||
},
|
||||
{
|
||||
key: '9',
|
||||
created: '2022-12-05T13:59:43.6827244',
|
||||
destinationUrl: 'h5yr.com',
|
||||
originalUrl: 'h5yr.dk',
|
||||
contentKey: '7191c911-6747-4824-849e-5208e2b31ddsfsdsfadsfdx9f2',
|
||||
},
|
||||
{
|
||||
key: '10',
|
||||
created: '2022-13-05T13:59:43.6827244',
|
||||
destinationUrl: 'our.umbraco.com',
|
||||
originalUrl: 'our.umbraco.dk',
|
||||
contentKey: '7191c911-6747-4824-849e-52dsacx08e2b31d9dsafdsff',
|
||||
},
|
||||
{
|
||||
key: '11',
|
||||
created: '2022-13-05T13:59:43.6827244',
|
||||
destinationUrl: 'your.umbraco.com',
|
||||
originalUrl: 'your.umbraco.dk',
|
||||
contentKey: '7191c911-6747-4824-849e-52dsacx08e2b31d9fsda',
|
||||
},
|
||||
];
|
||||
|
||||
const PagedRedirectUrlData: PagedRedirectUrl = {
|
||||
total: RedirectUrlData.length,
|
||||
items: RedirectUrlData,
|
||||
};
|
||||
@@ -11,6 +11,7 @@ import { handlers as examineManagementHandlers } from './domains/examine-managem
|
||||
import { handlers as modelsBuilderHandlers } from './domains/modelsbuilder.handlers';
|
||||
import { handlers as profileHandlers } from './domains/performance-profiling.handlers';
|
||||
import { handlers as healthCheckHandlers } from './domains/health-check.handlers';
|
||||
import { handlers as redirectManagementHandlers } from './domains/redirect-management.handlers';
|
||||
|
||||
export const handlers = [
|
||||
serverHandlers.serverRunningHandler,
|
||||
@@ -28,4 +29,5 @@ export const handlers = [
|
||||
...modelsBuilderHandlers,
|
||||
...profileHandlers,
|
||||
...healthCheckHandlers,
|
||||
...redirectManagementHandlers,
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user