Merge remote-tracking branch 'origin/main' into feature/document-type-workspace-take-5
# Conflicts: # libs/modal/modal-handler.ts # package-lock.json # src/backoffice/core/components/input-multi-url-picker/input-multi-url-picker.element.ts # src/backoffice/core/components/input-multi-url/input-multi-url.element.ts # src/packages/core/components/input-multi-url-picker/input-multi-url-picker.element.ts # src/packages/core/components/input-multi-url-picker/input-multi-url-picker.stories.ts # src/packages/core/modals/property-settings/property-settings-modal.element.ts # src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-design.element.ts # src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-design.stories.ts # src/shared/router/encode-folder-name.function.ts
This commit is contained in:
@@ -44,7 +44,7 @@ The frontend has an API formatter that takes the OpenAPI schema file and convert
|
||||
|
||||
**How to convert it:**
|
||||
|
||||
* Run `npm run generate:api`
|
||||
- Run `npm run generate:api`
|
||||
|
||||
## A contribution example
|
||||
|
||||
@@ -56,9 +56,9 @@ The frontend has an API formatter that takes the OpenAPI schema file and convert
|
||||
|
||||
Links for Lit examples and documentation:
|
||||
|
||||
* [https://lit.dev](https://lit.dev)
|
||||
* [https://lit.dev/docs/](https://lit.dev/docs/)
|
||||
* [https://lit.dev/playground/](https://lit.dev/playground/)
|
||||
- [https://lit.dev](https://lit.dev)
|
||||
- [https://lit.dev/docs/](https://lit.dev/docs/)
|
||||
- [https://lit.dev/playground/](https://lit.dev/playground/)
|
||||
|
||||
### Functionality
|
||||
|
||||
@@ -128,28 +128,29 @@ To declare the Published Cache Status Dashboard as a new manifest, we need to ad
|
||||
|
||||
Let’s go through each of these properties…
|
||||
|
||||
* Type: can be one of the following:
|
||||
* section - examples include: `Content`, `Media`
|
||||
* dashboard - a view within a section. Examples include: the welcome dashboard
|
||||
* propertyEditorUI
|
||||
* editorView
|
||||
* propertyAction
|
||||
* tree
|
||||
* editor
|
||||
* treeItemAction
|
||||
- Type: can be one of the following:
|
||||
|
||||
* Alias: is the unique key used to identify this item.
|
||||
* Name: is the human-readable name for this item.
|
||||
- section - examples include: `Content`, `Media`
|
||||
- dashboard - a view within a section. Examples include: the welcome dashboard
|
||||
- propertyEditorUI
|
||||
- editorView
|
||||
- propertyAction
|
||||
- tree
|
||||
- editor
|
||||
- treeItemAction
|
||||
|
||||
* ElementName: this is the customElementName declared on the element at the top of the file i.e
|
||||
- Alias: is the unique key used to identify this item.
|
||||
- Name: is the human-readable name for this item.
|
||||
|
||||
- ElementName: this is the customElementName declared on the element at the top of the file i.e
|
||||
|
||||
```typescript
|
||||
@customElement('umb-dashboard-published-status')
|
||||
```
|
||||
|
||||
* Loader: references a function call to import the file that the element is declared within
|
||||
- Loader: references a function call to import the file that the element is declared within
|
||||
|
||||
* Meta: allows us to reference additional data - in our case we can specify the section that our dashboard will sit within, the pathname that will be displayed in the url and the weight of the section
|
||||
- Meta: allows us to reference additional data - in our case we can specify the section that our dashboard will sit within, the pathname that will be displayed in the url and the weight of the section
|
||||
|
||||
## API mock handlers
|
||||
|
||||
@@ -162,19 +163,19 @@ From the existing functionality, we can see that this is a string message that i
|
||||
So to define this, we must first add a handler for the Published Status called `published-status.handlers.ts` within the mocks/domains folder. In this file we will have code that looks like the following:
|
||||
|
||||
```typescript
|
||||
import { rest } from 'msw';
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbracoPath } from '@umbraco-cms/utils';
|
||||
|
||||
export const handlers = [
|
||||
rest.get(umbracoPath('/published-cache/status'), (_req, res, ctx) => {
|
||||
return res(
|
||||
// Respond with a 200 status code
|
||||
ctx.status(200),
|
||||
ctx.json<string>(
|
||||
'Database cache is ok. ContentStore contains 1 item and has 1 generation and 0 snapshot. MediaStore contains 5 items and has 1 generation and 0 snapshot.'
|
||||
)
|
||||
);
|
||||
}),
|
||||
rest.get(umbracoPath('/published-cache/status'), (_req, res, ctx) => {
|
||||
return res(
|
||||
// Respond with a 200 status code
|
||||
ctx.status(200),
|
||||
ctx.json<string>(
|
||||
'Database cache is ok. ContentStore contains 1 item and has 1 generation and 0 snapshot. MediaStore contains 5 items and has 1 generation and 0 snapshot.'
|
||||
)
|
||||
);
|
||||
}),
|
||||
];
|
||||
```
|
||||
|
||||
@@ -211,7 +212,7 @@ In depth: [https://storybook.js.org/docs/web-components/get-started/introduction
|
||||
|
||||
Reference: [https://ambitious-stone-0033b3603.1.azurestaticapps.net/](https://ambitious-stone-0033b3603.1.azurestaticapps.net/)
|
||||
|
||||
* Locally: `npm run storybook`
|
||||
- Locally: `npm run storybook`
|
||||
|
||||
For Umbraco UI stories, please navigate to [https://uui.umbraco.com/](https://uui.umbraco.com/)
|
||||
|
||||
|
||||
@@ -4,17 +4,23 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
# pull_request:
|
||||
# types: [opened, synchronize, reopened, closed]
|
||||
# branches:
|
||||
# - main
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, closed]
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
issue_number:
|
||||
type: number
|
||||
description: 'Issue/PR Number to comment on'
|
||||
required: false
|
||||
|
||||
env:
|
||||
NODE_OPTIONS: --max_old_space_size=16384
|
||||
|
||||
jobs:
|
||||
build_and_deploy_job:
|
||||
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
|
||||
if: github.event_name != 'pull_request' || (github.event_name == 'pull_request' && github.event.action != 'closed' && contains(github.event.pull_request.labels.*.name, 'storybook'))
|
||||
runs-on: ubuntu-latest
|
||||
name: Build and Deploy Job
|
||||
steps:
|
||||
@@ -27,17 +33,39 @@ jobs:
|
||||
with:
|
||||
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_AMBITIOUS_STONE_0033B3603 }}
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
|
||||
action: "upload"
|
||||
action: 'upload'
|
||||
###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
|
||||
# For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
|
||||
app_location: "/" # App source code path
|
||||
app_build_command: "npm run build-storybook"
|
||||
api_location: "" # Api source code path - optional
|
||||
output_location: "/storybook-static" # Built app content directory - optional
|
||||
app_location: '/' # App source code path
|
||||
app_build_command: 'npm run build-storybook'
|
||||
api_location: '' # Api source code path - optional
|
||||
output_location: '/storybook-static' # Built app content directory - optional
|
||||
###### End of Repository/Build Configurations ######
|
||||
- name: Comment on PR
|
||||
# azure/static-web-apps-deploy doesn't support workflow_dispatch, so we need to manually comment on the PR
|
||||
if: github.event_name == 'workflow_dispatch' && inputs.issue_number != null
|
||||
uses: actions/github-script@v6
|
||||
env:
|
||||
ISSUE_NUMBER: ${{ inputs.issue_number }}
|
||||
SITE_URL: ${{ steps.builddeploy.outputs.static_web_app_url }}
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
github.rest.issues.addLabels({
|
||||
issue_number: process.env.ISSUE_NUMBER,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
labels: ['storybook']
|
||||
})
|
||||
github.rest.issues.createComment({
|
||||
issue_number: process.env.ISSUE_NUMBER,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: `Storybook is available at: ${process.env.SITE_URL}`
|
||||
})
|
||||
|
||||
close_pull_request_job:
|
||||
if: github.event_name == 'pull_request' && github.event.action == 'closed'
|
||||
if: github.event_name == 'pull_request' && github.event.action == 'closed' && contains(github.event.pull_request.labels.*.name, 'storybook')
|
||||
runs-on: ubuntu-latest
|
||||
name: Close Pull Request Job
|
||||
steps:
|
||||
@@ -45,5 +73,6 @@ jobs:
|
||||
id: closepullrequest
|
||||
uses: Azure/static-web-apps-deploy@v1
|
||||
with:
|
||||
app_location: '/'
|
||||
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_AMBITIOUS_STONE_0033B3603 }}
|
||||
action: "close"
|
||||
action: 'close'
|
||||
|
||||
@@ -27,12 +27,12 @@ jobs:
|
||||
with:
|
||||
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ASHY_BAY_09F36A803 }}
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
|
||||
action: "upload"
|
||||
action: 'upload'
|
||||
###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
|
||||
# For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
|
||||
app_location: "/" # App source code path
|
||||
api_location: "api" # Api source code path - optional
|
||||
output_location: "dist" # Built app content directory - optional
|
||||
app_location: '/' # App source code path
|
||||
api_location: 'api' # Api source code path - optional
|
||||
output_location: 'dist' # Built app content directory - optional
|
||||
###### End of Repository/Build Configurations ######
|
||||
|
||||
close_pull_request_job:
|
||||
@@ -44,5 +44,6 @@ jobs:
|
||||
id: closepullrequest
|
||||
uses: Azure/static-web-apps-deploy@v1
|
||||
with:
|
||||
app_location: '/'
|
||||
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ASHY_BAY_09F36A803 }}
|
||||
action: "close"
|
||||
action: 'close'
|
||||
|
||||
@@ -1 +1 @@
|
||||
18.15
|
||||
18.16
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
import { StorybookConfig } from '@storybook/web-components-vite';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories: ['../@(src|libs|apps|storybook)/**/*.mdx', '../@(src|libs|apps|storybook)/**/*.stories.@(js|jsx|ts|tsx)'],
|
||||
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-a11y'],
|
||||
addons: [
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-essentials',
|
||||
'@storybook/addon-a11y',
|
||||
{
|
||||
name: '@storybook/addon-docs',
|
||||
options: {
|
||||
mdxPluginOptions: {
|
||||
mdxCompileOptions: {
|
||||
remarkPlugins: [remarkGfm],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
framework: {
|
||||
name: '@storybook/web-components-vite',
|
||||
options: {},
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
line-height: 1.3em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/msw/lib/iife/index.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
window.addEventListener('load', () => {
|
||||
@@ -40,3 +40,4 @@
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import '@umbraco-ui/uui-css/dist/uui-css.css';
|
||||
import '../src/core/css/custom-properties.css';
|
||||
import '../src/shared/css/custom-properties.css';
|
||||
|
||||
import 'element-internals-polyfill';
|
||||
import '@umbraco-ui/uui';
|
||||
@@ -8,32 +8,32 @@ import { html } from 'lit';
|
||||
import { initialize, mswDecorator } from 'msw-storybook-addon';
|
||||
import { setCustomElements } from '@storybook/web-components';
|
||||
|
||||
import { UmbDataTypeStore } from '../src/backoffice/settings/data-types/repository/data-type.store.ts';
|
||||
import { UmbDocumentTypeStore } from '../src/backoffice/documents/document-types/repository/document-type.store.ts';
|
||||
import { UmbDocumentStore } from '../src/backoffice/documents/documents/repository/document.store.ts';
|
||||
import { UmbDocumentTreeStore } from '../src/backoffice/documents/documents/repository/document.tree.store.ts';
|
||||
import { UmbDataTypeStore } from '../src/packages/settings/data-types/repository/data-type.store.ts';
|
||||
import { UmbDocumentTypeStore } from '../src/packages/documents/document-types/repository/document-type.store.ts';
|
||||
import { UmbDocumentStore } from '../src/packages/documents/documents/repository/document.store.ts';
|
||||
import { UmbDocumentTreeStore } from '../src/packages/documents/documents/repository/document.tree.store.ts';
|
||||
|
||||
import customElementManifests from '../dist/libs/custom-elements.json';
|
||||
import { UmbIconStore } from '../src/core/stores/icon/icon.store';
|
||||
import { onUnhandledRequest } from '../src/core/mocks/browser';
|
||||
import { handlers } from '../src/core/mocks/browser-handlers';
|
||||
import { UmbIconRegistry } from '../src/shared/icon-registry/icon.registry';
|
||||
import { onUnhandledRequest } from '../src/shared/mocks';
|
||||
import { handlers } from '../src/shared/mocks/browser-handlers';
|
||||
import { UMB_MODAL_CONTEXT_TOKEN, UmbModalContext } from '../libs/modal';
|
||||
import { UmbLitElement } from '../src/core/lit-element';
|
||||
import { UmbLitElement } from '../src/shared/lit-element';
|
||||
|
||||
import { umbExtensionsRegistry } from '../libs/extensions-api';
|
||||
import { umbExtensionsRegistry } from '../libs/extension-registry';
|
||||
|
||||
import '../src/core/context-provider/context-provider.element';
|
||||
import '../src/core/controller-host/controller-host-test.element';
|
||||
import '../src/backoffice/core/components';
|
||||
import '../libs/context-api/provide/context-provider.element';
|
||||
import '../libs/controller-api/controller-host-initializer.element.ts';
|
||||
import '../src/packages/core/components';
|
||||
|
||||
import { manifests as documentManifests } from '../src/backoffice/documents';
|
||||
import { manifests as documentManifests } from '../src/packages/documents';
|
||||
|
||||
class UmbStoryBookElement extends UmbLitElement {
|
||||
_umbIconStore = new UmbIconStore();
|
||||
_umbIconRegistry = new UmbIconRegistry();
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._umbIconStore.attach(this);
|
||||
this._umbIconRegistry.attach(this);
|
||||
this._registerExtensions(documentManifests);
|
||||
this.provideContext(UMB_MODAL_CONTEXT_TOKEN, new UmbModalContext(this));
|
||||
}
|
||||
@@ -56,19 +56,27 @@ customElements.define('umb-storybook', UmbStoryBookElement);
|
||||
const storybookProvider = (story) => html` <umb-storybook>${story()}</umb-storybook> `;
|
||||
|
||||
const dataTypeStoreProvider = (story) => html`
|
||||
<umb-controller-host-test .create=${(host) => new UmbDataTypeStore(host)}>${story()}</umb-controller-host-test>
|
||||
<umb-controller-host-initializer .create=${(host) => new UmbDataTypeStore(host)}
|
||||
>${story()}</umb-controller-host-initializer
|
||||
>
|
||||
`;
|
||||
|
||||
const documentTypeStoreProvider = (story) => html`
|
||||
<umb-controller-host-test .create=${(host) => new UmbDocumentTypeStore(host)}>${story()}</umb-controller-host-test>
|
||||
<umb-controller-host-initializer .create=${(host) => new UmbDocumentTypeStore(host)}
|
||||
>${story()}</umb-controller-host-initializer
|
||||
>
|
||||
`;
|
||||
|
||||
const documentStoreProvider = (story) => html`
|
||||
<umb-controller-host-test .create=${(host) => new UmbDocumentStore(host)}>${story()}</umb-controller-host-test>
|
||||
<umb-controller-host-initializer .create=${(host) => new UmbDocumentStore(host)}
|
||||
>${story()}</umb-controller-host-initializer
|
||||
>
|
||||
`;
|
||||
|
||||
const documentTreeStoreProvider = (story) => html`
|
||||
<umb-controller-host-test .create=${(host) => new UmbDocumentTreeStore(host)}>${story()}</umb-controller-host-test>
|
||||
<umb-controller-host-initializer .create=${(host) => new UmbDocumentTreeStore(host)}
|
||||
>${story()}</umb-controller-host-initializer
|
||||
>
|
||||
`;
|
||||
|
||||
// Initialize MSW
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// TODO: could these be renamed as login providers?
|
||||
import type { ManifestExternalLoginProvider } from '@umbraco-cms/backoffice/extensions-registry';
|
||||
import type { ManifestExternalLoginProvider } from '@umbraco-cms/backoffice/extension-registry';
|
||||
|
||||
export const manifests: Array<ManifestExternalLoginProvider> = [
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extensions-api';
|
||||
import { ManifestTypes, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { manifests as externalLoginProviders } from './external-login-providers/manifests';
|
||||
|
||||
import '@umbraco-ui/uui-css/dist/uui-css.css';
|
||||
|
||||
@@ -6,7 +6,7 @@ const path = pathModule.default;
|
||||
const getDirName = path.dirname;
|
||||
const glob = globModule.default;
|
||||
|
||||
const moduleDirectory = 'libs/store/icon/';
|
||||
const moduleDirectory = 'src/shared/icon-registry/';
|
||||
const iconsSVGDirectory = `${moduleDirectory}svgs/`;
|
||||
const iconsOutputDirectory = `public-assets/icons/`;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { rest } from 'msw';
|
||||
const { rest } = window.MockServiceWorker;
|
||||
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
import { ProblemDetailsModel, RuntimeLevelModel, ServerStatusResponseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
|
||||
@@ -2,7 +2,7 @@ import { expect, test as base } from '@playwright/test';
|
||||
import { createWorkerFixture } from 'playwright-msw';
|
||||
import type { MockServiceWorker } from 'playwright-msw';
|
||||
|
||||
import { handlers } from '../src/core/mocks/e2e-handlers';
|
||||
import { handlers } from '../src/shared/mocks/e2e-handlers';
|
||||
|
||||
const test = base.extend<{
|
||||
worker: MockServiceWorker;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { rest } from 'msw';
|
||||
const { rest } = window.MockServiceWorker;
|
||||
import { umbracoPath } from '@umbraco-cms/backoffice/utils';
|
||||
import { ProblemDetailsModel, RuntimeLevelModel, ServerStatusResponseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { expect, test } from './test';
|
||||
|
||||
@@ -5,11 +5,10 @@
|
||||
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Umbraco</title>
|
||||
<script type="module" src="/src/index.ts"></script>
|
||||
<script src="/node_modules/msw/lib/iife/index.js"></script>
|
||||
<script type="module" src="index.ts"></script>
|
||||
<base href="/" />
|
||||
</head>
|
||||
|
||||
<body class="uui-font uui-text" style="margin: 0; padding: 0; overflow: hidden">
|
||||
<umb-app></umb-app>
|
||||
</body>
|
||||
<body class="uui-font uui-text" style="margin: 0; padding: 0; overflow: hidden"></body>
|
||||
</html>
|
||||
|
||||
21
src/Umbraco.Web.UI.Client/index.ts
Normal file
21
src/Umbraco.Web.UI.Client/index.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { UmbAppElement } from './src/apps/app/app.element';
|
||||
import { startMockServiceWorker } from './src/shared/mocks';
|
||||
|
||||
if (import.meta.env.VITE_UMBRACO_USE_MSW === 'on') {
|
||||
startMockServiceWorker();
|
||||
}
|
||||
|
||||
const appElement = new UmbAppElement();
|
||||
const isMocking = import.meta.env.VITE_UMBRACO_USE_MSW === 'on';
|
||||
|
||||
if (!isMocking) {
|
||||
appElement.serverUrl = import.meta.env.VITE_UMBRACO_API_URL;
|
||||
}
|
||||
|
||||
if (import.meta.env.DEV) {
|
||||
appElement.backofficePath = '/';
|
||||
}
|
||||
|
||||
appElement.bypassAuth = isMocking;
|
||||
|
||||
document.body.appendChild(appElement);
|
||||
@@ -40,7 +40,7 @@ Create an umbraco-package.json file in the root of your package.
|
||||
Then create a dashboard.js file the same folder.
|
||||
|
||||
```javascript
|
||||
import { UmbElementMixin } from '@umbraco-cms/backoffice/element';
|
||||
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
|
||||
import { UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification';
|
||||
|
||||
const template = document.createElement('template');
|
||||
@@ -106,12 +106,11 @@ Then go to the element located in `src/my-element.ts` and replace it with the fo
|
||||
// src/my-element.ts
|
||||
import { LitElement, html } from 'lit';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
import { UmbElementMixin } from '@umbraco-cms/backoffice/element';
|
||||
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
|
||||
import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification';
|
||||
|
||||
@customElement('my-element')
|
||||
export default class MyElement extends UmbElementMixin(LitElement) {
|
||||
|
||||
private _notificationContext?: UmbNotificationContext;
|
||||
|
||||
constructor() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
|
||||
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import {
|
||||
UmbArrayState,
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
UmbObjectState,
|
||||
UmbObserverController,
|
||||
} from '@umbraco-cms/backoffice/observable-api';
|
||||
import { umbExtensionsRegistry, createExtensionClass } from '@umbraco-cms/backoffice/extensions-api';
|
||||
import { createExtensionClass } from '@umbraco-cms/backoffice/extension-api';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { UmbCollectionRepository } from '@umbraco-cms/backoffice/repository';
|
||||
import type { UmbCollectionFilterModel } from '@umbraco-cms/backoffice/collection';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { PropertyContainerTypes, UmbContentTypePropertyStructureManager } from './content-type-structure-manager.class';
|
||||
import { PropertyTypeContainerResponseModelBaseModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbArrayState, UmbBooleanState, UmbObserverController } from '@umbraco-cms/backoffice/observable-api';
|
||||
|
||||
export class UmbContentTypeContainerStructureHelper {
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
DocumentTypePropertyTypeResponseModel,
|
||||
PropertyTypeResponseModelBaseModel,
|
||||
} from '@umbraco-cms/backoffice/backend-api';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbArrayState, UmbObserverController } from '@umbraco-cms/backoffice/observable-api';
|
||||
|
||||
export class UmbContentTypePropertyStructureHelper {
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
PropertyTypeResponseModelBaseModel,
|
||||
DocumentTypeResponseModel,
|
||||
} from '@umbraco-cms/backoffice/backend-api';
|
||||
import { UmbControllerHostElement, UmbControllerInterface } from '@umbraco-cms/backoffice/controller';
|
||||
import { UmbControllerHostElement, UmbControllerInterface } from '@umbraco-cms/backoffice/controller-api';
|
||||
import {
|
||||
UmbArrayState,
|
||||
UmbObserverController,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { UmbContextToken } from '../token/context-token';
|
||||
import { UmbContextConsumer } from './context-consumer';
|
||||
import { UmbContextCallback } from './context-request.event';
|
||||
import type { UmbControllerHostElement, UmbControllerInterface } from '@umbraco-cms/backoffice/controller';
|
||||
import type { UmbControllerHostElement, UmbControllerInterface } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbContextConsumerController<T = unknown>
|
||||
extends UmbContextConsumer<UmbControllerHostElement, T>
|
||||
|
||||
@@ -4,5 +4,6 @@ export * from './consume/context-request.event';
|
||||
export * from './provide/context-provider.controller';
|
||||
export * from './provide/context-provider';
|
||||
export * from './provide/context-provide.event';
|
||||
export * from './provide/context-provider.element';
|
||||
export * from './token/';
|
||||
export * from './debug/context-data.function';
|
||||
export * from './debug/context-data.function';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { UmbContextToken } from '../token/context-token';
|
||||
import { UmbContextProvider } from './context-provider';
|
||||
import type { UmbControllerHostElement, UmbControllerInterface } from '@umbraco-cms/backoffice/controller';
|
||||
import type { UmbControllerHostElement, UmbControllerInterface } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbContextProviderController<T = unknown>
|
||||
extends UmbContextProvider<UmbControllerHostElement>
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { expect, fixture, html } from '@open-wc/testing';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
import { UmbContextConsumerController } from '../consume/context-consumer.controller';
|
||||
import { UmbContextProviderElement } from './context-provider.element';
|
||||
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
|
||||
import { UmbControllerHostMixin } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
@customElement('umb-context-test')
|
||||
export class UmbContextTestElement extends UmbLitElement {
|
||||
@customElement('umb-test-context')
|
||||
export class UmbTestContextElement extends UmbControllerHostMixin(HTMLElement) {
|
||||
public value: string | null = null;
|
||||
constructor() {
|
||||
super();
|
||||
this.consumeContext<string>('test-context', (value) => {
|
||||
|
||||
new UmbContextConsumerController<string>(this, 'test-context', (value) => {
|
||||
this.value = value;
|
||||
});
|
||||
}
|
||||
@@ -16,16 +18,16 @@ export class UmbContextTestElement extends UmbLitElement {
|
||||
|
||||
describe('UmbContextProvider', () => {
|
||||
let element: UmbContextProviderElement;
|
||||
let consumer: UmbContextTestElement;
|
||||
let consumer: UmbTestContextElement;
|
||||
const contextValue = 'test-value';
|
||||
|
||||
beforeEach(async () => {
|
||||
element = await fixture(
|
||||
html` <umb-context-provider key="test-context" .value=${contextValue}>
|
||||
<umb-context-test></umb-context-test>
|
||||
<umb-test-context></umb-test-context>
|
||||
</umb-context-provider>`
|
||||
);
|
||||
consumer = element.getElementsByTagName('umb-context-test')[0] as UmbContextTestElement;
|
||||
consumer = element.getElementsByTagName('umb-test-context')[0] as UmbTestContextElement;
|
||||
});
|
||||
|
||||
it('is defined with its own instance', () => {
|
||||
@@ -0,0 +1,68 @@
|
||||
import { UmbControllerHostElement, UmbControllerHostMixin } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbContextProviderController, UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
/**
|
||||
* Provides a value to the context down the DOM tree.
|
||||
*
|
||||
* @remarks This element is a wrapper around the `provideContext` function.
|
||||
* @slot - The context will be available to all descendants given in the default slot.
|
||||
* @throws {Error} If the key property is not set.
|
||||
* @throws {Error} If the value property is not set.
|
||||
*/
|
||||
export class UmbContextProviderElement extends UmbControllerHostMixin(HTMLElement) {
|
||||
/**
|
||||
* The value to provide to the context.
|
||||
* @optional
|
||||
*/
|
||||
public create?: (host: UmbControllerHostElement) => unknown;
|
||||
|
||||
/**
|
||||
* The value to provide to the context.
|
||||
* @required
|
||||
*/
|
||||
public value: unknown;
|
||||
|
||||
/**
|
||||
* The key to provide to the context.
|
||||
* @required
|
||||
*/
|
||||
public key!: string | UmbContextToken;
|
||||
|
||||
static get observedAttributes() {
|
||||
return ['value', 'key'];
|
||||
}
|
||||
|
||||
attributeChangedCallback(name: string, _oldValue: string | UmbContextToken, newValue: string | UmbContextToken) {
|
||||
if (name === 'key') this.key = newValue;
|
||||
if (name === 'value') this.value = newValue;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
const slot = document.createElement('slot');
|
||||
this.shadowRoot?.appendChild(slot);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
if (!this.key) {
|
||||
throw new Error('The key property is required.');
|
||||
}
|
||||
if (this.create) {
|
||||
this.value = this.create(this);
|
||||
} else if (!this.value) {
|
||||
throw new Error('The value property is required.');
|
||||
}
|
||||
|
||||
new UmbContextProviderController(this, this.key, this.value);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('umb-context-provider', UmbContextProviderElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-context-provider': UmbContextProviderElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { UmbControllerHostElement, UmbControllerHostMixin } from './controller-host.mixin';
|
||||
|
||||
export class UmbControllerHostInitializerElement
|
||||
extends UmbControllerHostMixin(HTMLElement)
|
||||
implements UmbControllerHostElement
|
||||
{
|
||||
/**
|
||||
* A way to initialize controllers.
|
||||
* @required
|
||||
*/
|
||||
create?: (host: UmbControllerHostElement) => void;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
const slot = document.createElement('slot');
|
||||
this.shadowRoot?.appendChild(slot);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
if (this.create) {
|
||||
this.create(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('umb-controller-host-initializer', UmbControllerHostInitializerElement);
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-controller-host-initializer': UmbControllerHostInitializerElement;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { expect, fixture, html } from '@open-wc/testing';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
import { UmbControllerHostInitializerElement } from './controller-host-initializer.element';
|
||||
import { UmbControllerHostElement, UmbControllerHostMixin } from './controller-host.mixin';
|
||||
import { UmbContextConsumerController, UmbContextProviderController } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
@customElement('umb-test-controller-host-initializer-consumer')
|
||||
export class UmbTestControllerHostInitializerConsumerElement extends UmbControllerHostMixin(HTMLElement) {
|
||||
public value: string | null = null;
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
new UmbContextConsumerController<string>(this, 'my-test-context-alias', (value) => {
|
||||
this.value = value;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
describe('UmbControllerHostTestElement', () => {
|
||||
let element: UmbControllerHostInitializerElement;
|
||||
let consumer: UmbTestControllerHostInitializerConsumerElement;
|
||||
const contextValue = 'test-value';
|
||||
|
||||
beforeEach(async () => {
|
||||
element = await fixture(
|
||||
html` <umb-controller-host-initializer
|
||||
.create=${(host: UmbControllerHostElement) =>
|
||||
new UmbContextProviderController(host, 'my-test-context-alias', contextValue)}>
|
||||
<umb-test-controller-host-initializer-consumer></umb-test-controller-host-initializer-consumer>
|
||||
</umb-controller-host-initializer>`
|
||||
);
|
||||
consumer = element.getElementsByTagName(
|
||||
'umb-test-controller-host-initializer-consumer'
|
||||
)[0] as UmbTestControllerHostInitializerConsumerElement;
|
||||
});
|
||||
|
||||
it('element is defined with its own instance', () => {
|
||||
expect(element).to.be.instanceOf(UmbControllerHostInitializerElement);
|
||||
});
|
||||
|
||||
it('provides the context', () => {
|
||||
expect(consumer.value).to.equal(contextValue);
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
import { UmbControllerInterface } from './controller.interface';
|
||||
import type { HTMLElementConstructor } from '@umbraco-cms/backoffice/models';
|
||||
|
||||
type HTMLElementConstructor<T = HTMLElement> = new (...args: any[]) => T;
|
||||
|
||||
export declare class UmbControllerHostElement extends HTMLElement {
|
||||
hasController(controller: UmbControllerInterface): boolean;
|
||||
@@ -0,0 +1,25 @@
|
||||
import { DataTypePropertyPresentationModel } from '@umbraco-cms/backoffice/backend-api';
|
||||
|
||||
/**
|
||||
* Extends Array to add utility functions for accessing data type properties
|
||||
* by alias, returning either the value or the complete DataTypePropertyPresentationModel object
|
||||
*/
|
||||
export class UmbDataTypePropertyCollection extends Array<DataTypePropertyPresentationModel> {
|
||||
constructor(args: Array<DataTypePropertyPresentationModel> = []) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
getValueByAlias<T>(alias: string): T | undefined {
|
||||
const property = this.getByAlias(alias);
|
||||
|
||||
if (property?.value === undefined || property?.value === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
return property.value as T;
|
||||
}
|
||||
|
||||
getByAlias(alias: string): DataTypePropertyPresentationModel | undefined {
|
||||
return this.find((x) => x.alias === alias);
|
||||
}
|
||||
}
|
||||
1
src/Umbraco.Web.UI.Client/libs/data-type/index.ts
Normal file
1
src/Umbraco.Web.UI.Client/libs/data-type/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './data-type-property-collection.class';
|
||||
@@ -1,8 +1,6 @@
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import type { HTMLElementConstructor } from '@umbraco-cms/backoffice/models';
|
||||
|
||||
import { UmbControllerHostElement, UmbControllerHostMixin } from '@umbraco-cms/backoffice/controller';
|
||||
import type { HTMLElementConstructor } from '@umbraco-cms/backoffice/extension-api';
|
||||
import { UmbControllerHostElement, UmbControllerHostMixin } from '@umbraco-cms/backoffice/controller-api';
|
||||
import {
|
||||
UmbContextToken,
|
||||
UmbContextCallback,
|
||||
@@ -1,5 +1,6 @@
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
|
||||
import { umbExtensionsRegistry, createExtensionClass } from '@umbraco-cms/backoffice/extensions-api';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { createExtensionClass } from '@umbraco-cms/backoffice/extension-api';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
|
||||
import { UmbObserverController } from '@umbraco-cms/backoffice/observable-api';
|
||||
|
||||
export interface UmbAction<RepositoryType = unknown> {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbCopyEntityAction<T extends { copy(): Promise<void> }> extends UmbEntityActionBase<T> {
|
||||
constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
|
||||
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN, UMB_CONFIRM_MODAL } from '@umbraco-cms/backoffice/modal';
|
||||
import { UmbFolderRepository } from '@umbraco-cms/backoffice/repository';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
|
||||
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN, UMB_CONFIRM_MODAL } from '@umbraco-cms/backoffice/modal';
|
||||
import { UmbDetailRepository, UmbItemRepository } from '@umbraco-cms/backoffice/repository';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
|
||||
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbModalContext, UMB_FOLDER_MODAL, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal';
|
||||
import { UmbFolderRepository } from '@umbraco-cms/backoffice/repository';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
// TODO: investigate what we need to finish the generic move action. We would need to open a picker, which requires a modal token,
|
||||
// maybe we can use kinds to make a specific manifest to the move action.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbSortChildrenOfEntityAction<
|
||||
T extends { sortChildrenOf(): Promise<void> }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
|
||||
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN, UMB_CONFIRM_MODAL } from '@umbraco-cms/backoffice/modal';
|
||||
import { UmbItemRepository } from '@umbraco-cms/backoffice/repository';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UmbAction, UmbActionBase } from './action';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export interface UmbEntityAction<RepositoryType> extends UmbAction<RepositoryType> {
|
||||
unique: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UmbAction, UmbActionBase } from './action';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export interface UmbEntityBulkAction<RepositoryType = unknown> extends UmbAction<RepositoryType> {
|
||||
selection: Array<string>;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { hasDefaultExport } from './has-default-export.function';
|
||||
import { isManifestClassConstructorType } from './is-manifest-class-instance-type.function';
|
||||
import { isManifestClassConstructorType } from './type-guards';
|
||||
import { loadExtension } from './load-extension.function';
|
||||
import type { ClassConstructor } from '@umbraco-cms/backoffice/models';
|
||||
import type { ManifestClass } from '@umbraco-cms/backoffice/extensions-registry';
|
||||
import type { ManifestClass, ClassConstructor } from './types';
|
||||
|
||||
//TODO: Write tests for this method:
|
||||
export async function createExtensionClass<T = unknown>(
|
||||
@@ -1,7 +1,10 @@
|
||||
import { createExtensionElement } from './create-extension-element.function';
|
||||
import { isManifestElementableType } from './is-manifest-elementable-type.function';
|
||||
import { isManifestElementableType } from './type-guards';
|
||||
|
||||
export async function createExtensionElementOrFallback(manifest: any, fallbackElementName: string): Promise<HTMLElement | undefined> {
|
||||
export async function createExtensionElementOrFallback(
|
||||
manifest: any,
|
||||
fallbackElementName: string
|
||||
): Promise<HTMLElement | undefined> {
|
||||
if (isManifestElementableType(manifest)) {
|
||||
return createExtensionElement(manifest);
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
import { hasDefaultExport } from './has-default-export.function';
|
||||
import { isManifestElementNameType } from './is-manifest-element-name-type.function';
|
||||
import { isManifestElementNameType } from './type-guards';
|
||||
import { loadExtension } from './load-extension.function';
|
||||
import type { HTMLElementConstructor } from '@umbraco-cms/backoffice/models';
|
||||
import type { ManifestElement } from '@umbraco-cms/backoffice/extensions-registry';
|
||||
import type { HTMLElementConstructor, ManifestElement } from './types';
|
||||
|
||||
export async function createExtensionElement<ElementType extends HTMLElement>(
|
||||
manifest: ManifestElement<ElementType>
|
||||
@@ -1,13 +1,15 @@
|
||||
import type { ManifestEntrypoint } from './models';
|
||||
import { hasInitExport, loadExtension, UmbExtensionRegistry } from '@umbraco-cms/backoffice/extensions-api';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller';
|
||||
import type { ManifestEntryPoint } from './types';
|
||||
import { hasInitExport } from './has-init-export.function';
|
||||
import { loadExtension } from './load-extension.function';
|
||||
import { UmbExtensionRegistry } from './registry/extension.registry';
|
||||
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbEntryPointExtensionInitializer {
|
||||
#host;
|
||||
#extensionRegistry;
|
||||
#entryPointMap = new Map();
|
||||
|
||||
constructor(host: UmbControllerHostElement, extensionRegistry: UmbExtensionRegistry) {
|
||||
constructor(host: UmbControllerHostElement, extensionRegistry: UmbExtensionRegistry<ManifestEntryPoint>) {
|
||||
this.#host = host;
|
||||
this.#extensionRegistry = extensionRegistry;
|
||||
extensionRegistry.extensionsOfType('entryPoint').subscribe((entryPoints) => {
|
||||
@@ -19,7 +21,7 @@ export class UmbEntryPointExtensionInitializer {
|
||||
});
|
||||
}
|
||||
|
||||
async instantiateEntryPoint(manifest: ManifestEntrypoint) {
|
||||
async instantiateEntryPoint(manifest: ManifestEntryPoint) {
|
||||
const js = await loadExtension(manifest);
|
||||
// If the extension has an onInit export, be sure to run that or else let the module handle itself
|
||||
if (hasInitExport(js)) {
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { UmbEntrypointModule } from './umb-lifecycle.interface';
|
||||
import type { UmbEntryPointModule } from './umb-lifecycle.interface';
|
||||
|
||||
/**
|
||||
* Validate if an ESModule exports a known init function called 'onInit'
|
||||
*/
|
||||
export function hasInitExport(obj: unknown): obj is Pick<UmbEntrypointModule, 'onInit'> {
|
||||
export function hasInitExport(obj: unknown): obj is Pick<UmbEntryPointModule, 'onInit'> {
|
||||
return obj !== null && typeof obj === 'object' && 'onInit' in obj;
|
||||
}
|
||||
@@ -1,16 +1,11 @@
|
||||
import { UmbExtensionRegistry } from './registry/extension.registry';
|
||||
|
||||
export * from './registry/extension.registry';
|
||||
export * from './type-guards';
|
||||
export * from './create-extension-element.function';
|
||||
export * from './has-default-export.function';
|
||||
export * from './has-init-export.function';
|
||||
export * from './is-manifest-element-name-type.function';
|
||||
export * from './is-manifest-elementable-type.function';
|
||||
export * from './is-manifest-js-type.function';
|
||||
export * from './is-manifest-loader-type.function';
|
||||
export * from './load-extension.function';
|
||||
export * from './create-extension-element-or-fallback.function';
|
||||
export * from './create-extension-class.function';
|
||||
export * from './umb-lifecycle.interface';
|
||||
|
||||
export const umbExtensionsRegistry = new UmbExtensionRegistry();
|
||||
export * from './entry-point-extension-initializer';
|
||||
export * from './types';
|
||||
@@ -1,6 +1,5 @@
|
||||
import { isManifestJSType } from './is-manifest-js-type.function';
|
||||
import { isManifestLoaderType } from './is-manifest-loader-type.function';
|
||||
import type { ManifestWithLoader } from '@umbraco-cms/backoffice/extensions-registry';
|
||||
import { isManifestJSType, isManifestLoaderType } from './type-guards';
|
||||
import type { ManifestWithLoader } from './types';
|
||||
|
||||
export async function loadExtension<T = unknown>(manifest: ManifestWithLoader<T>): Promise<T | null> {
|
||||
try {
|
||||
@@ -1,10 +1,10 @@
|
||||
import { expect } from '@open-wc/testing';
|
||||
import type { ManifestElementWithElementName, ManifestKind, ManifestWithMeta } from '../types';
|
||||
import { UmbExtensionRegistry } from './extension.registry';
|
||||
import type { ManifestKind, ManifestTypes } from '@umbraco-cms/backoffice/extensions-registry';
|
||||
|
||||
describe('UmbExtensionRegistry', () => {
|
||||
let extensionRegistry: UmbExtensionRegistry;
|
||||
let manifests: Array<ManifestTypes>;
|
||||
let extensionRegistry: UmbExtensionRegistry<ManifestWithMeta>;
|
||||
let manifests: Array<ManifestWithMeta>;
|
||||
|
||||
beforeEach(() => {
|
||||
extensionRegistry = new UmbExtensionRegistry();
|
||||
@@ -152,11 +152,13 @@ describe('UmbExtensionRegistry', () => {
|
||||
});
|
||||
|
||||
describe('UmbExtensionRegistry with kinds', () => {
|
||||
let extensionRegistry: UmbExtensionRegistry;
|
||||
let manifests: Array<ManifestTypes | ManifestKind>;
|
||||
let extensionRegistry: UmbExtensionRegistry<any>;
|
||||
let manifests: Array<
|
||||
ManifestElementWithElementName | ManifestWithMeta | ManifestKind<ManifestElementWithElementName>
|
||||
>;
|
||||
|
||||
beforeEach(() => {
|
||||
extensionRegistry = new UmbExtensionRegistry();
|
||||
extensionRegistry = new UmbExtensionRegistry<any>();
|
||||
manifests = [
|
||||
{
|
||||
type: 'kind',
|
||||
@@ -1,12 +1,5 @@
|
||||
import { BehaviorSubject, map, Observable, distinctUntilChanged, combineLatest } from 'rxjs';
|
||||
import type {
|
||||
ManifestTypes,
|
||||
ManifestTypeMap,
|
||||
ManifestBase,
|
||||
SpecificManifestTypeOrManifestBase,
|
||||
ManifestKind,
|
||||
} from '@umbraco-cms/backoffice/extensions-registry';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { ManifestTypeMap, ManifestBase, SpecificManifestTypeOrManifestBase, ManifestKind } from '../types';
|
||||
|
||||
function extensionArrayMemoization<T extends { alias: string }>(
|
||||
previousValue: Array<T>,
|
||||
@@ -35,27 +28,34 @@ function extensionSingleMemoization<T extends { alias: string }>(
|
||||
|
||||
const sortExtensions = (a: ManifestBase, b: ManifestBase) => (b.weight || 0) - (a.weight || 0);
|
||||
|
||||
export class UmbExtensionRegistry {
|
||||
export class UmbExtensionRegistry<
|
||||
IncomingManifestTypes extends ManifestBase,
|
||||
ManifestTypes extends ManifestBase = IncomingManifestTypes | ManifestBase
|
||||
> {
|
||||
// TODO: Use UniqueBehaviorSubject, as we don't want someone to edit data of extensions.
|
||||
private _extensions = new BehaviorSubject<Array<ManifestTypes>>([]);
|
||||
public readonly extensions = this._extensions.asObservable();
|
||||
|
||||
private _kinds = new BehaviorSubject<Array<ManifestKind>>([]);
|
||||
private _kinds = new BehaviorSubject<Array<ManifestKind<ManifestTypes>>>([]);
|
||||
public readonly kinds = this._kinds.asObservable();
|
||||
|
||||
defineKind(kind: ManifestKind) {
|
||||
defineKind(kind: ManifestKind<ManifestTypes>) {
|
||||
const nextData = this._kinds
|
||||
.getValue()
|
||||
.filter(
|
||||
(k) => !(k.matchType === (kind as ManifestKind).matchType && k.matchKind === (kind as ManifestKind).matchKind)
|
||||
(k) =>
|
||||
!(
|
||||
k.matchType === (kind as ManifestKind<ManifestTypes>).matchType &&
|
||||
k.matchKind === (kind as ManifestKind<ManifestTypes>).matchKind
|
||||
)
|
||||
);
|
||||
nextData.push(kind as ManifestKind);
|
||||
nextData.push(kind as ManifestKind<ManifestTypes>);
|
||||
this._kinds.next(nextData);
|
||||
}
|
||||
|
||||
register(manifest: ManifestTypes | ManifestKind): void {
|
||||
register(manifest: ManifestTypes | ManifestKind<ManifestTypes>): void {
|
||||
if (manifest.type === 'kind') {
|
||||
this.defineKind(manifest as ManifestKind);
|
||||
this.defineKind(manifest as ManifestKind<ManifestTypes>);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ export class UmbExtensionRegistry {
|
||||
this._extensions.next([...extensionsValues, manifest as ManifestTypes]);
|
||||
}
|
||||
|
||||
registerMany(manifests: Array<ManifestTypes>): void {
|
||||
registerMany(manifests: Array<ManifestTypes | ManifestKind<ManifestTypes>>): void {
|
||||
manifests.forEach((manifest) => this.register(manifest));
|
||||
}
|
||||
|
||||
@@ -99,13 +99,13 @@ export class UmbExtensionRegistry {
|
||||
}
|
||||
*/
|
||||
|
||||
private _kindsOfType<Key extends keyof ManifestTypeMap | string>(type: Key) {
|
||||
private _kindsOfType<Key extends keyof ManifestTypeMap<ManifestTypes> | string>(type: Key) {
|
||||
return this.kinds.pipe(
|
||||
map((kinds) => kinds.filter((kind) => kind.matchType === type)),
|
||||
distinctUntilChanged(extensionArrayMemoization)
|
||||
);
|
||||
}
|
||||
private _extensionsOfType<Key extends keyof ManifestTypeMap | string>(type: Key) {
|
||||
private _extensionsOfType<Key extends keyof ManifestTypeMap<ManifestTypes> | string>(type: Key) {
|
||||
return this.extensions.pipe(
|
||||
map((exts) => exts.filter((ext) => ext.type === type)),
|
||||
distinctUntilChanged(extensionArrayMemoization)
|
||||
@@ -117,16 +117,20 @@ export class UmbExtensionRegistry {
|
||||
distinctUntilChanged(extensionArrayMemoization)
|
||||
);
|
||||
}
|
||||
private _extensionsOfTypes<ExtensionType = ManifestBase>(types: string[]): Observable<Array<ExtensionType>> {
|
||||
|
||||
// TODO: can we get rid of as unknown here
|
||||
private _extensionsOfTypes<ExtensionType extends ManifestBase = ManifestBase>(
|
||||
types: Array<ExtensionType['type']>
|
||||
): Observable<Array<ExtensionType>> {
|
||||
return this.extensions.pipe(
|
||||
map((exts) => exts.filter((ext) => types.indexOf(ext.type) !== -1)),
|
||||
distinctUntilChanged(extensionArrayMemoization)
|
||||
) as Observable<Array<ExtensionType>>;
|
||||
) as unknown as Observable<Array<ExtensionType>>;
|
||||
}
|
||||
|
||||
getByTypeAndAlias<
|
||||
Key extends keyof ManifestTypeMap | string,
|
||||
T extends ManifestBase = SpecificManifestTypeOrManifestBase<Key>
|
||||
Key extends keyof ManifestTypeMap<ManifestTypes> | string,
|
||||
T extends ManifestBase = SpecificManifestTypeOrManifestBase<ManifestTypes, Key>
|
||||
>(type: Key, alias: string) {
|
||||
return combineLatest([
|
||||
this.extensions.pipe(
|
||||
@@ -155,8 +159,8 @@ export class UmbExtensionRegistry {
|
||||
}
|
||||
|
||||
extensionsOfType<
|
||||
Key extends keyof ManifestTypeMap | string,
|
||||
T extends ManifestBase = SpecificManifestTypeOrManifestBase<Key>
|
||||
Key extends keyof ManifestTypeMap<ManifestTypes> | string,
|
||||
T extends ManifestBase = SpecificManifestTypeOrManifestBase<ManifestTypes, Key>
|
||||
>(type: Key) {
|
||||
return combineLatest([this._extensionsOfType(type), this._kindsOfType(type)]).pipe(
|
||||
map(([exts, kinds]) =>
|
||||
@@ -205,5 +209,3 @@ export class UmbExtensionRegistry {
|
||||
) as Observable<Array<ExtensionTypes>>;
|
||||
}
|
||||
}
|
||||
|
||||
export const UMB_EXTENSION_REGISTRY_TOKEN = new UmbContextToken<UmbExtensionRegistry>('UmbExtensionRegistry');
|
||||
@@ -0,0 +1,6 @@
|
||||
export * from './is-manifest-class-instance-type.function';
|
||||
export * from './is-manifest-classable-type.function';
|
||||
export * from './is-manifest-element-name-type.function';
|
||||
export * from './is-manifest-elementable-type.function';
|
||||
export * from './is-manifest-js-type.function';
|
||||
export * from './is-manifest-loader-type.function';
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ManifestClass, ManifestClassWithClassConstructor } from '@umbraco-cms/backoffice/extensions-registry';
|
||||
import type { ManifestClass, ManifestClassWithClassConstructor } from '../types';
|
||||
|
||||
export function isManifestClassConstructorType(manifest: unknown): manifest is ManifestClassWithClassConstructor {
|
||||
return typeof manifest === 'object' && manifest !== null && (manifest as ManifestClass).class !== undefined;
|
||||
@@ -1,8 +1,12 @@
|
||||
import type { ManifestBase, ManifestClass } from '../types';
|
||||
import { isManifestJSType } from './is-manifest-js-type.function';
|
||||
import { isManifestLoaderType } from './is-manifest-loader-type.function';
|
||||
import { isManifestClassConstructorType } from './is-manifest-class-instance-type.function';
|
||||
import type { ManifestBase, ManifestClass } from '@umbraco-cms/backoffice/extensions-registry';
|
||||
|
||||
export function isManifestClassableType(manifest: ManifestBase): manifest is ManifestClass {
|
||||
return isManifestClassConstructorType(manifest) || isManifestLoaderType<object>(manifest) || isManifestJSType<object>(manifest);
|
||||
return (
|
||||
isManifestClassConstructorType(manifest) ||
|
||||
isManifestLoaderType<object>(manifest) ||
|
||||
isManifestJSType<object>(manifest)
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ManifestElement, ManifestElementWithElementName } from '@umbraco-cms/backoffice/extensions-registry';
|
||||
import type { ManifestElement, ManifestElementWithElementName } from '../types';
|
||||
|
||||
export function isManifestElementNameType(manifest: unknown): manifest is ManifestElementWithElementName {
|
||||
return typeof manifest === 'object' && manifest !== null && (manifest as ManifestElement).elementName !== undefined;
|
||||
@@ -1,9 +1,11 @@
|
||||
import type { ManifestElement, ManifestBase } from '../types';
|
||||
import { isManifestElementNameType } from './is-manifest-element-name-type.function';
|
||||
import { isManifestJSType } from './is-manifest-js-type.function';
|
||||
import { isManifestLoaderType } from './is-manifest-loader-type.function';
|
||||
import type { ManifestElement, ManifestBase } from '@umbraco-cms/backoffice/extensions-registry';
|
||||
|
||||
export function isManifestElementableType<ElementType extends HTMLElement = HTMLElement>(manifest: ManifestBase): manifest is ManifestElement {
|
||||
export function isManifestElementableType<ElementType extends HTMLElement = HTMLElement>(
|
||||
manifest: ManifestBase
|
||||
): manifest is ManifestElement {
|
||||
return (
|
||||
isManifestElementNameType(manifest) ||
|
||||
isManifestLoaderType<ElementType>(manifest) ||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ManifestBase, ManifestWithLoader } from '@umbraco-cms/backoffice/extensions-registry';
|
||||
import type { ManifestBase, ManifestWithLoader } from '../types';
|
||||
|
||||
export type ManifestJSType<T> = ManifestWithLoader<T> & { js: string };
|
||||
export function isManifestJSType<T>(manifest: ManifestBase | unknown): manifest is ManifestJSType<T> {
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { ManifestBase, ManifestWithLoader } from '../types';
|
||||
|
||||
import type { ManifestBase, ManifestWithLoader } from '@umbraco-cms/backoffice/extensions-registry';
|
||||
export type ManifestLoaderType<T> = ManifestWithLoader<T> & {
|
||||
loader: () => Promise<T>;
|
||||
};
|
||||
|
||||
export function isManifestLoaderType<T>(manifest: ManifestBase): manifest is ManifestLoaderType<T> {
|
||||
return typeof (manifest as ManifestLoaderType<T>).loader === 'function';
|
||||
}
|
||||
159
src/Umbraco.Web.UI.Client/libs/extension-api/types.ts
Normal file
159
src/Umbraco.Web.UI.Client/libs/extension-api/types.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type HTMLElementConstructor<T = HTMLElement> = new (...args: any[]) => T;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type ClassConstructor<T> = new (...args: any[]) => T;
|
||||
|
||||
export type ManifestTypeMap<ManifestTypes extends ManifestBase> = {
|
||||
[Manifest in ManifestTypes as Manifest['type']]: Manifest;
|
||||
} & {
|
||||
[key: string]: ManifestBase;
|
||||
};
|
||||
|
||||
export type SpecificManifestTypeOrManifestBase<
|
||||
ManifestTypes extends ManifestBase,
|
||||
T extends keyof ManifestTypeMap<ManifestTypes> | string
|
||||
> = T extends keyof ManifestTypeMap<ManifestTypes> ? ManifestTypeMap<ManifestTypes>[T] : ManifestBase;
|
||||
|
||||
export interface ManifestBase {
|
||||
/**
|
||||
* The type of extension such as dashboard etc...
|
||||
*/
|
||||
type: string;
|
||||
|
||||
/**
|
||||
* The alias of the extension, ensure it is unique
|
||||
*/
|
||||
alias: string;
|
||||
|
||||
/**
|
||||
* The kind of the extension, used to group extensions together
|
||||
*
|
||||
* @examples ["button"]
|
||||
*/
|
||||
kind?: unknown; // I had to add the optional kind property set to undefined. To make the ManifestTypes recognize the Manifest Kind types. Notice that Kinds has to Omit the kind property when extending.
|
||||
|
||||
/**
|
||||
* The friendly name of the extension
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* Extensions such as dashboards are ordered by weight with lower numbers being first in the list
|
||||
*/
|
||||
weight?: number;
|
||||
}
|
||||
|
||||
export interface ManifestKind<ManifestTypes> {
|
||||
type: 'kind';
|
||||
alias: string;
|
||||
matchType: string;
|
||||
matchKind: string;
|
||||
manifest: Partial<ManifestTypes>;
|
||||
}
|
||||
|
||||
export interface ManifestWithConditions<ConditionsType> {
|
||||
/**
|
||||
* Set the conditions for when the extension should be loaded
|
||||
*/
|
||||
conditions: ConditionsType;
|
||||
}
|
||||
|
||||
export interface ManifestWithLoader<LoaderReturnType> extends ManifestBase {
|
||||
/**
|
||||
* @TJS-ignore
|
||||
*/
|
||||
loader?: () => Promise<LoaderReturnType>;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of extension such as dashboard etc...
|
||||
*/
|
||||
export interface ManifestClass<ClassType = unknown>
|
||||
extends ManifestWithLoader<{ default: ClassConstructor<ClassType> }> {
|
||||
readonly CLASS_TYPE?: ClassType;
|
||||
|
||||
/**
|
||||
* The file location of the javascript file to load
|
||||
* @TJS-required
|
||||
*/
|
||||
js?: string;
|
||||
|
||||
/**
|
||||
* @TJS-ignore
|
||||
*/
|
||||
className?: string;
|
||||
|
||||
/**
|
||||
* @TJS-ignore
|
||||
*/
|
||||
class?: ClassConstructor<ClassType>;
|
||||
//loader?: () => Promise<object | HTMLElement>;
|
||||
}
|
||||
|
||||
export interface ManifestClassWithClassConstructor<T = unknown> extends ManifestClass<T> {
|
||||
class: ClassConstructor<T>;
|
||||
}
|
||||
|
||||
export interface ManifestElement<ElementType extends HTMLElement = HTMLElement>
|
||||
extends ManifestWithLoader<{ default: ClassConstructor<ElementType> } | Omit<object, 'default'>> {
|
||||
readonly ELEMENT_TYPE?: ElementType;
|
||||
|
||||
/**
|
||||
* The file location of the javascript file to load
|
||||
*
|
||||
* @TJS-require
|
||||
*/
|
||||
js?: string;
|
||||
|
||||
/**
|
||||
* The HTML web component name to use such as 'my-dashboard'
|
||||
* Note it is NOT <my-dashboard></my-dashboard> but just the name
|
||||
*/
|
||||
elementName?: string;
|
||||
|
||||
//loader?: () => Promise<object | HTMLElement>;
|
||||
|
||||
/**
|
||||
* This contains properties specific to the type of extension
|
||||
*/
|
||||
meta?: unknown;
|
||||
}
|
||||
|
||||
export interface ManifestWithView<ElementType extends HTMLElement = HTMLElement> extends ManifestElement<ElementType> {
|
||||
meta: MetaManifestWithView;
|
||||
}
|
||||
|
||||
export interface MetaManifestWithView {
|
||||
pathname: string;
|
||||
label: string;
|
||||
icon: string;
|
||||
}
|
||||
|
||||
export interface ManifestElementWithElementName extends ManifestElement {
|
||||
/**
|
||||
* The HTML web component name to use such as 'my-dashboard'
|
||||
* Note it is NOT <my-dashboard></my-dashboard> but just the name
|
||||
*/
|
||||
elementName: string;
|
||||
}
|
||||
|
||||
export interface ManifestWithMeta extends ManifestBase {
|
||||
/**
|
||||
* This contains properties specific to the type of extension
|
||||
*/
|
||||
meta: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* This type of extension gives full control and will simply load the specified JS file
|
||||
* You could have custom logic to decide which extensions to load/register by using extensionRegistry
|
||||
*/
|
||||
export interface ManifestEntryPoint extends ManifestBase {
|
||||
type: 'entryPoint';
|
||||
|
||||
/**
|
||||
* The file location of the javascript file to load in the backoffice
|
||||
*/
|
||||
js: string;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { UmbExtensionRegistry } from './registry/extension.registry';
|
||||
import { ManifestBase } from './types';
|
||||
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export type UmbEntryPointOnInit = (
|
||||
host: UmbControllerHostElement,
|
||||
extensionRegistry: UmbExtensionRegistry<ManifestBase>
|
||||
) => void;
|
||||
|
||||
/**
|
||||
* Interface containing supported life-cycle functions for ESModule entry points
|
||||
*/
|
||||
export interface UmbEntryPointModule {
|
||||
onInit: UmbEntryPointOnInit;
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from './interfaces';
|
||||
export * from './models';
|
||||
export * from './entry-point-extension-initializer';
|
||||
export * from './registry';
|
||||
@@ -0,0 +1,14 @@
|
||||
import type { ManifestModal } from '../models';
|
||||
import type { UmbModalHandler } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
export interface UmbModalExtensionElement<
|
||||
UmbModalData extends object = object,
|
||||
UmbModalResult = unknown,
|
||||
ModalManifestType extends ManifestModal = ManifestModal
|
||||
> extends HTMLElement {
|
||||
manifest?: ModalManifestType;
|
||||
|
||||
modalHandler?: UmbModalHandler<UmbModalData, UmbModalResult>;
|
||||
|
||||
data?: UmbModalData;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { UmbDataTypePropertyCollection } from '@umbraco-cms/backoffice/data-type';
|
||||
|
||||
export interface UmbPropertyEditorExtensionElement extends HTMLElement {
|
||||
value: unknown;
|
||||
config?: UmbDataTypePropertyCollection;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ManifestElement, ManifestWithConditions } from '.';
|
||||
import type { ManifestElement, ManifestWithConditions } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestCollectionView extends ManifestElement, ManifestWithConditions<ConditionsCollectionView> {
|
||||
type: 'collectionView';
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ManifestBase } from '.';
|
||||
import type { ManifestBase } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestDashboardCollection extends ManifestBase {
|
||||
type: 'dashboardCollection';
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { UmbDashboardExtensionElement } from '../interfaces';
|
||||
import type { ManifestElement, ManifestWithConditions } from '.';
|
||||
import type { ManifestElement, ManifestWithConditions } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestDashboard
|
||||
extends ManifestElement<UmbDashboardExtensionElement>,
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ManifestElement } from '.';
|
||||
import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
/**
|
||||
* An action to perform on an entity
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ManifestElement, ManifestWithConditions } from '.';
|
||||
import type { ManifestElement, ManifestWithConditions } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
/**
|
||||
* An action to perform on multiple entities
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { UmbExternalLoginProviderExtensionElement } from '../interfaces/external-login-provider-extension-element.interface';
|
||||
import type { ManifestElement } from '.';
|
||||
import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestExternalLoginProvider extends ManifestElement<UmbExternalLoginProviderExtensionElement> {
|
||||
type: 'externalLoginProvider';
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ManifestElement } from '.';
|
||||
import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
/**
|
||||
* Header apps are displayed in the top right corner of the backoffice
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ManifestElement } from '.';
|
||||
import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestHealthCheck extends ManifestElement {
|
||||
type: 'healthCheck';
|
||||
@@ -0,0 +1,93 @@
|
||||
import type { ManifestCollectionView } from './collection-view.model';
|
||||
import type { ManifestDashboard } from './dashboard.model';
|
||||
import type { ManifestDashboardCollection } from './dashboard-collection.model';
|
||||
import type { ManifestEntityAction } from './entity-action.model';
|
||||
import type { ManifestEntityBulkAction } from './entity-bulk-action.model';
|
||||
import type { ManifestExternalLoginProvider } from './external-login-provider.model';
|
||||
import type { ManifestHeaderApp, ManifestHeaderAppButtonKind } from './header-app.model';
|
||||
import type { ManifestHealthCheck } from './health-check.model';
|
||||
import type { ManifestMenu } from './menu.model';
|
||||
import type { ManifestMenuItem, ManifestMenuItemTreeKind } from './menu-item.model';
|
||||
import type { ManifestModal } from './modal.model';
|
||||
import type { ManifestPackageView } from './package-view.model';
|
||||
import type { ManifestPropertyAction } from './property-action.model';
|
||||
import type { ManifestPropertyEditorUI, ManifestPropertyEditorModel } from './property-editor.model';
|
||||
import type { ManifestRepository } from './repository.model';
|
||||
import type { ManifestSection } from './section.model';
|
||||
import type { ManifestSectionSidebarApp, ManifestSectionSidebarAppMenuKind } from './section-sidebar-app.model';
|
||||
import type { ManifestSectionView } from './section-view.model';
|
||||
import type { ManifestStore, ManifestTreeStore, ManifestItemStore } from './store.model';
|
||||
import type { ManifestTheme } from './theme.model';
|
||||
import type { ManifestTree } from './tree.model';
|
||||
import type { ManifestTreeItem } from './tree-item.model';
|
||||
import type { ManifestUserProfileApp } from './user-profile-app.model';
|
||||
import type { ManifestWorkspace } from './workspace.model';
|
||||
import type { ManifestWorkspaceAction } from './workspace-action.model';
|
||||
import type { ManifestWorkspaceEditorView } from './workspace-editor-view.model';
|
||||
import type { ManifestWorkspaceViewCollection } from './workspace-view-collection.model';
|
||||
import type { ManifestBase, ManifestEntryPoint } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export * from './collection-view.model';
|
||||
export * from './dashboard-collection.model';
|
||||
export * from './dashboard.model';
|
||||
export * from './entity-action.model';
|
||||
export * from './entity-bulk-action.model';
|
||||
export * from './external-login-provider.model';
|
||||
export * from './header-app.model';
|
||||
export * from './health-check.model';
|
||||
export * from './menu-item.model';
|
||||
export * from './menu.model';
|
||||
export * from './modal.model';
|
||||
export * from './package-view.model';
|
||||
export * from './property-action.model';
|
||||
export * from './property-editor.model';
|
||||
export * from './repository.model';
|
||||
export * from './section-sidebar-app.model';
|
||||
export * from './section-view.model';
|
||||
export * from './section.model';
|
||||
export * from './store.model';
|
||||
export * from './theme.model';
|
||||
export * from './tree-item.model';
|
||||
export * from './tree.model';
|
||||
export * from './user-profile-app.model';
|
||||
export * from './workspace-action.model';
|
||||
export * from './workspace-view-collection.model';
|
||||
export * from './workspace-editor-view.model';
|
||||
export * from './workspace.model';
|
||||
|
||||
export type ManifestTypes =
|
||||
| ManifestCollectionView
|
||||
| ManifestDashboard
|
||||
| ManifestDashboardCollection
|
||||
| ManifestEntityAction
|
||||
| ManifestEntityBulkAction
|
||||
| ManifestEntryPoint
|
||||
| ManifestExternalLoginProvider
|
||||
| ManifestHeaderApp
|
||||
| ManifestHeaderAppButtonKind
|
||||
| ManifestHealthCheck
|
||||
| ManifestItemStore
|
||||
| ManifestMenu
|
||||
| ManifestMenuItem
|
||||
| ManifestMenuItemTreeKind
|
||||
| ManifestModal
|
||||
| ManifestPackageView
|
||||
| ManifestPropertyAction
|
||||
| ManifestPropertyEditorModel
|
||||
| ManifestPropertyEditorUI
|
||||
| ManifestRepository
|
||||
| ManifestSection
|
||||
| ManifestSectionSidebarApp
|
||||
| ManifestSectionSidebarAppMenuKind
|
||||
| ManifestSectionView
|
||||
| ManifestStore
|
||||
| ManifestTheme
|
||||
| ManifestTree
|
||||
| ManifestTreeItem
|
||||
| ManifestTreeStore
|
||||
| ManifestUserProfileApp
|
||||
| ManifestWorkspace
|
||||
| ManifestWorkspaceAction
|
||||
| ManifestWorkspaceEditorView
|
||||
| ManifestWorkspaceViewCollection
|
||||
| ManifestBase;
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { UmbMenuItemExtensionElement } from '../interfaces/menu-item-extension-element.interface';
|
||||
import type { ManifestElement } from '.';
|
||||
import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestMenuItem extends ManifestElement<UmbMenuItemExtensionElement> {
|
||||
type: 'menuItem';
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestMenu extends ManifestElement {
|
||||
type: 'menu';
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestModal extends ManifestElement {
|
||||
type: 'modal';
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ManifestElement } from '.';
|
||||
import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestPackageView extends ManifestElement {
|
||||
type: 'packageView';
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ManifestElement, ManifestWithConditions } from '.';
|
||||
import type { ManifestElement, ManifestWithConditions } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestPropertyAction extends ManifestElement, ManifestWithConditions<ConditionsPropertyAction> {
|
||||
type: 'propertyAction';
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { UmbPropertyEditorExtensionElement } from '../interfaces';
|
||||
import type { ManifestElement, ManifestBase } from '.';
|
||||
import type { ManifestElement, ManifestBase } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestPropertyEditorUI extends ManifestElement<UmbPropertyEditorExtensionElement> {
|
||||
type: 'propertyEditorUI';
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { ManifestClass } from '.';
|
||||
|
||||
import type { ManifestClass } from '@umbraco-cms/backoffice/extension-api';
|
||||
// TODO: Consider adding a ClassType for this manifest. (Currently we cannot know the scope of a repository, therefor we are going with unknown for now.)
|
||||
export interface ManifestRepository extends ManifestClass<unknown> {
|
||||
type: 'repository';
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { UmbSectionSidebarAppExtensionElement } from '../interfaces/section-sidebar-app-extension-element.interface';
|
||||
import type { ManifestElement } from '.';
|
||||
import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestSectionSidebarApp extends ManifestElement<UmbSectionSidebarAppExtensionElement> {
|
||||
type: 'sectionSidebarApp';
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { UmbSectionViewExtensionElement } from '../interfaces/section-view-extension-element.interface';
|
||||
import type { ManifestElement, ManifestWithConditions } from '.';
|
||||
import type { ManifestElement, ManifestWithConditions } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestSectionView
|
||||
extends ManifestElement<UmbSectionViewExtensionElement>,
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { UmbSectionExtensionElement } from '../interfaces';
|
||||
import type { ManifestElement } from '.';
|
||||
import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestSection extends ManifestElement<UmbSectionExtensionElement> {
|
||||
type: 'section';
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ManifestClass } from '.';
|
||||
import type { ManifestClass } from '@umbraco-cms/backoffice/extension-api';
|
||||
import { UmbItemStore, UmbStoreBase, UmbTreeStore } from '@umbraco-cms/backoffice/store';
|
||||
|
||||
export interface ManifestStore extends ManifestClass<UmbStoreBase> {
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ManifestWithLoader } from '.';
|
||||
import type { ManifestWithLoader } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
// TODO: make or find type for JS Module with default export: Would be nice to support css file directly.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { UmbTreeItemExtensionElement } from '../interfaces';
|
||||
import type { ManifestElement } from '.';
|
||||
import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestTreeItem extends ManifestElement<UmbTreeItemExtensionElement> {
|
||||
type: 'treeItem';
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ManifestBase } from '.';
|
||||
import type { ManifestBase } from '@umbraco-cms/backoffice/extension-api';
|
||||
|
||||
export interface ManifestTree extends ManifestBase {
|
||||
type: 'tree';
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user