From 9612f34d24f0431ef8c92510c95dc0990400e559 Mon Sep 17 00:00:00 2001 From: Richard Ockerby Date: Fri, 6 Sep 2024 10:50:33 +0200 Subject: [PATCH 1/4] Add in custom dialogs (WIP) --- .../src/manifest.ts | 6 ++ .../dashboards/custom-dialogs-dashboard.ts | 64 +++++++++++++------ .../src/scripts/dialogs/custom-modal.token.ts | 16 +++++ .../src/scripts/dialogs/custom-modal.ts | 36 +++++++++++ 4 files changed, 101 insertions(+), 21 deletions(-) create mode 100644 src/Our.Umbraco.UiExamples.v14/src/scripts/dialogs/custom-modal.token.ts create mode 100644 src/Our.Umbraco.UiExamples.v14/src/scripts/dialogs/custom-modal.ts diff --git a/src/Our.Umbraco.UiExamples.v14/src/manifest.ts b/src/Our.Umbraco.UiExamples.v14/src/manifest.ts index 8d59391..ecb753a 100644 --- a/src/Our.Umbraco.UiExamples.v14/src/manifest.ts +++ b/src/Our.Umbraco.UiExamples.v14/src/manifest.ts @@ -61,6 +61,12 @@ export const manifests: Array = [ "match": "example.ui.section" } ] + }, + { + "type": "modal", + "alias": "My.Modal", + "name": "My Modal", + "element": () => import("./scripts/dialogs/custom-modal.ts"), } // ... insert as many manifests as you like diff --git a/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-dialogs-dashboard.ts b/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-dialogs-dashboard.ts index 8223e86..fb92a6d 100644 --- a/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-dialogs-dashboard.ts +++ b/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-dialogs-dashboard.ts @@ -1,5 +1,8 @@ import { LitElement, css, html } from 'lit' import { customElement, property } from 'lit/decorators.js' +import { MY_MODAL_TOKEN } from '../dialogs/custom-modal.token'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; /** * An example element. @@ -8,29 +11,48 @@ import { customElement, property } from 'lit/decorators.js' * @csspart button - The button */ @customElement('uie-custom-dialogs-dashboard') -export default class UieCustomDialogsDashboard extends LitElement { - /** - * Copy for the read the docs hint. - */ - @property() - docsHint = 'Click on the Vite and Lit logos to learn more' +export default class UieCustomDialogsDashboard extends UmbElementMixin(LitElement) { + #modalManagerContext?: typeof UMB_MODAL_MANAGER_CONTEXT.TYPE; + constructor() { + super(); + this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (instance) => { + this.#modalManagerContext = instance; + // modalManagerContext is now ready to be used. + }); + } - /** - * The number of times the button has been clicked. - */ - @property({ type: Number }) - count = 0 + render() { + return html` + +
+
+
Overlay Dialogs
Overlays give you a 'modal' dialog across the whole screen
+
+
+
+ + ! + + View the Storybook library +
+ +

The overlay service has a confirm option built, in with this you can quickly create a confirm dialog, to present your users with a simple option.

+ + Confirm + Confirm Remove + Confirm Delete + +
+
` + } - render() { - return html` - - -

My Modal

-

My modal content

-
-
- ` + private _openModal() { + this.#modalManagerContext?.open(this, MY_MODAL_TOKEN, { + data: { + headline: "My modal headline", + }, + }); } static styles = css` @@ -85,6 +107,6 @@ export default class UieCustomDialogsDashboard extends LitElement { declare global { interface HTMLElementTagNameMap { - 'uie-custom-dialogs-dashboard': UieCustomDialogsDashboard + 'uie-custom-dialogs-dashboard': UieCustomDialogsDashboard } } diff --git a/src/Our.Umbraco.UiExamples.v14/src/scripts/dialogs/custom-modal.token.ts b/src/Our.Umbraco.UiExamples.v14/src/scripts/dialogs/custom-modal.token.ts new file mode 100644 index 0000000..2bee6b0 --- /dev/null +++ b/src/Our.Umbraco.UiExamples.v14/src/scripts/dialogs/custom-modal.token.ts @@ -0,0 +1,16 @@ +import { UmbModalToken } from "@umbraco-cms/backoffice/modal"; + +export type MyModalData = { + headline: string; +} + +export type MyModalValue = { + myData: string; +} + +export const MY_MODAL_TOKEN = new UmbModalToken('My.Modal', { + modal: { + type: 'sidebar', + size: 'small' + } +}); \ No newline at end of file diff --git a/src/Our.Umbraco.UiExamples.v14/src/scripts/dialogs/custom-modal.ts b/src/Our.Umbraco.UiExamples.v14/src/scripts/dialogs/custom-modal.ts new file mode 100644 index 0000000..a99f30a --- /dev/null +++ b/src/Our.Umbraco.UiExamples.v14/src/scripts/dialogs/custom-modal.ts @@ -0,0 +1,36 @@ +import { html, LitElement, property, customElement } from "@umbraco-cms/backoffice/external/lit"; +import { UmbElementMixin } from "@umbraco-cms/backoffice/element-api"; +import type { UmbModalContext } from "@umbraco-cms/backoffice/modal"; +import type { MyModalData, MyModalValue } from "./custom-modal.token.ts"; +import { UmbModalExtensionElement } from "@umbraco-cms/backoffice/extension-registry"; + +@customElement('my-dialog') +export default class MyDialogElement + extends UmbElementMixin(LitElement) + implements UmbModalExtensionElement { + + @property({ attribute: false }) + modalContext?: UmbModalContext; + + @property({ attribute: false }) + data?: MyModalData; + + private _handleCancel() { + this.modalContext?.submit(); + } + + private _handleSubmit() { + this.modalContext?.updateValue({ myData: "hello world" }); + this.modalContext?.submit(); + } + + render() { + return html` +
+

${this.modalContext?.data.headline ?? "Default headline"}

+ + +
+ `; + } +} \ No newline at end of file From 142fa4bf4ef2e9900fe2d760dcd6e355c5648aae Mon Sep 17 00:00:00 2001 From: Richard Ockerby Date: Fri, 6 Sep 2024 12:35:21 +0200 Subject: [PATCH 2/4] Add in custom dialogs and sidebars --- .../src/manifest.ts | 22 +- .../dashboards/custom-dialogs-dashboard.ts | 112 ---------- .../dashboards/custom-modals-dashboard.ts | 200 ++++++++++++++++++ .../custom-dialog.token.ts} | 4 +- .../custom-dialog.ts} | 21 +- .../scripts/modals/custom-sidebar.token.ts | 17 ++ .../src/scripts/modals/custom-sidebar.ts | 65 ++++++ 7 files changed, 311 insertions(+), 130 deletions(-) delete mode 100644 src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-dialogs-dashboard.ts create mode 100644 src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-modals-dashboard.ts rename src/Our.Umbraco.UiExamples.v14/src/scripts/{dialogs/custom-modal.token.ts => modals/custom-dialog.token.ts} (64%) rename src/Our.Umbraco.UiExamples.v14/src/scripts/{dialogs/custom-modal.ts => modals/custom-dialog.ts} (53%) create mode 100644 src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.token.ts create mode 100644 src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.ts diff --git a/src/Our.Umbraco.UiExamples.v14/src/manifest.ts b/src/Our.Umbraco.UiExamples.v14/src/manifest.ts index ecb753a..dc281b6 100644 --- a/src/Our.Umbraco.UiExamples.v14/src/manifest.ts +++ b/src/Our.Umbraco.UiExamples.v14/src/manifest.ts @@ -30,13 +30,13 @@ export const manifests: Array = [ }, { "type": "dashboard", - "alias": "example.ui.dashboard.dialogs", - "name": "Dialogs", - "element": () => import("./scripts/dashboards/custom-dialogs-dashboard.ts"), + "alias": "example.ui.dashboard.modals", + "name": "Modals", + "element": () => import("./scripts/dashboards/custom-modals-dashboard.ts"), "weight": -1, "meta": { - "label": "Dialogs", - "pathname": "dialogs" + "label": "Modals", + "pathname": "modals" }, "conditions": [ { @@ -64,9 +64,15 @@ export const manifests: Array = [ }, { "type": "modal", - "alias": "My.Modal", - "name": "My Modal", - "element": () => import("./scripts/dialogs/custom-modal.ts"), + "alias": "My.Dialog", + "name": "My Dialog", + "element": () => import("./scripts/modals/custom-dialog.ts"), + }, + { + "type": "modal", + "alias": "My.Sidebar", + "name": "My Sidebar Modal", + "element": () => import("./scripts/modals/custom-sidebar.ts"), } // ... insert as many manifests as you like diff --git a/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-dialogs-dashboard.ts b/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-dialogs-dashboard.ts deleted file mode 100644 index fb92a6d..0000000 --- a/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-dialogs-dashboard.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { LitElement, css, html } from 'lit' -import { customElement, property } from 'lit/decorators.js' -import { MY_MODAL_TOKEN } from '../dialogs/custom-modal.token'; -import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; -import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; - -/** - * An example element. - * - * @slot - This element has a slot - * @csspart button - The button - */ -@customElement('uie-custom-dialogs-dashboard') -export default class UieCustomDialogsDashboard extends UmbElementMixin(LitElement) { - #modalManagerContext?: typeof UMB_MODAL_MANAGER_CONTEXT.TYPE; - - constructor() { - super(); - this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (instance) => { - this.#modalManagerContext = instance; - // modalManagerContext is now ready to be used. - }); - } - - render() { - return html` - -
-
-
Overlay Dialogs
Overlays give you a 'modal' dialog across the whole screen
-
-
-
- - ! - - View the Storybook library -
- -

The overlay service has a confirm option built, in with this you can quickly create a confirm dialog, to present your users with a simple option.

- - Confirm - Confirm Remove - Confirm Delete - -
-
` - } - - private _openModal() { - this.#modalManagerContext?.open(this, MY_MODAL_TOKEN, { - data: { - headline: "My modal headline", - }, - }); - } - - static styles = css` - :host { - padding: var(--uui-size-layout-1); - display:block; - } - - ::slotted(h1) { - font-size: 3.2em; - line-height: 1.1; - } - .header-bar { - - display: flex; - align-items: center; - justify-content: space-between; - } - .title { - font-size: 15px; - color: #000; - font-weight: 700; - margin:0; - } - a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; - } - a:hover { - color: #535bf2; - } - .sub-header { - font-size: 13px; - color: #515054; - line-height: 1.6em; - margin-top: 1px; - } - p:first-child { - margin-top:0; - } - @media (prefers-color-scheme: light) { - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } - } - ` -} - -declare global { - interface HTMLElementTagNameMap { - 'uie-custom-dialogs-dashboard': UieCustomDialogsDashboard - } -} diff --git a/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-modals-dashboard.ts b/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-modals-dashboard.ts new file mode 100644 index 0000000..3e0a962 --- /dev/null +++ b/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-modals-dashboard.ts @@ -0,0 +1,200 @@ +import { LitElement, css, html } from 'lit' +import { customElement, property } from 'lit/decorators.js' +import { MY_DIALOG_TOKEN } from '../modals/custom-dialog.token'; +import { MY_SIDEBAR_TOKEN } from '../modals/custom-sidebar.token'; +import { UMB_MODAL_MANAGER_CONTEXT, UMB_CONTEXT_DEBUGGER_MODAL, UMB_CONFIRM_MODAL, UMB_CODE_EDITOR_MODAL } from '@umbraco-cms/backoffice/modal'; +import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; + +/** + * An example element. + * + * @slot - This element has a slot + * @csspart button - The button + */ +@customElement('uie-custom-modals-dashboard') +export default class UieCustomDialogsDashboard extends UmbElementMixin(LitElement) { + #modalManagerContext?: typeof UMB_MODAL_MANAGER_CONTEXT.TYPE; + + constructor() { + super(); + this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (instance) => { + this.#modalManagerContext = instance; + // modalManagerContext is now ready to be used. + }); + } + + + @property({ attribute: false }) + message?: string; + + @property({ attribute: false }) + returnData?: string; + + render() { + return html` + +
+
+
Modals
Modals are the mechanism to display content on-top of the current display.
+
+
+
+ + ! + + View the Storybook library +
+ +

The overlay service has a confirm option built, in with this you can quickly create a confirm dialog, to present your users with a simple option. The term "Modal" covers both types of pop-overs; Dialogs and Sidebars.

+ +

You can checkout all of the prebuilt modals by checking the GitHub Source

+ + Confirm Dialog + Debug Sidebar + Code Editor Sidebar + Custom Sidebar + Custom Dialog + +

Your last action was: ${this.message ?? "Nothing clicked yet..."}

+

With data: ${this.returnData ?? "{}"}

+ +
+
` + } + + private _handleSubmit(isPositive?: boolean, data?: string) { + this.message = isPositive ? "Submitted" : "Cancelled"; + this.returnData = data; + } + + private _openCodeDialog() { + const ctx = this.#modalManagerContext?.open(this, UMB_CODE_EDITOR_MODAL, { + data: { + headline:"text", + content:"Enter something", + language:"javascript" + }, + }); + + ctx?.onSubmit().then((e) => { + this._handleSubmit(true, JSON.stringify(e)); + }).catch(() => { + this._handleSubmit(false); + }) + } + private _openDebugDialog() { + const ctx = this.#modalManagerContext?.open(this, UMB_CONTEXT_DEBUGGER_MODAL, { + data: { + content:"I am a debugger modal!" + }, + }); + + ctx?.onSubmit().then((e) => { + this._handleSubmit(true, JSON.stringify(e)); + }).catch(() => { + this._handleSubmit(false); + }) + } + + private _openConfirmationModal() { + const ctx = this.#modalManagerContext?.open(this, UMB_CONFIRM_MODAL, { + data: { + headline: "This is a confirmation modal", + content: "Word up modal", + cancelLabel: 'Cancel', + confirmLabel: 'Confirm', + color: 'positive' // You can change the colour of the submit button (but not cancel)! + }, + }); + + ctx?.onSubmit().then((e) => { + this._handleSubmit(true, JSON.stringify(e)); + }).catch(() => { + this._handleSubmit(false); + }) + } + + private _openCustomModal() { + const ctx = this.#modalManagerContext?.open(this, MY_DIALOG_TOKEN, { + data: { + headline: "My modal headline", + } + }); + + ctx?.onSubmit().then((e) => { + console.log("Submitted", e); + this._handleSubmit(true, JSON.stringify(e)); + }).catch(() => { + this._handleSubmit(false); + }) + } + private _openCustomSidebar() { + const ctx = this.#modalManagerContext?.open(this, MY_SIDEBAR_TOKEN, { + data: { + headline: "My sidebar headline", + } + }); + + ctx?.onSubmit().then((e) => { + console.log("Submitted", e); + this._handleSubmit(true, JSON.stringify(e)); + }).catch(() => { + this._handleSubmit(false); + }) + } + + static styles = css` + :host { + padding: var(--uui-size-layout-1); + display:block; + } + + ::slotted(h1) { + font-size: 3.2em; + line-height: 1.1; + } + .header-bar { + + display: flex; + align-items: center; + justify-content: space-between; + } + .title { + font-size: 15px; + color: #000; + font-weight: 700; + margin:0; + } + a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; + } + a:hover { + color: #535bf2; + } + .sub-header { + font-size: 13px; + color: #515054; + line-height: 1.6em; + margin-top: 1px; + } + p:first-child { + margin-top:0; + } + @media (prefers-color-scheme: light) { + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } + } + ` +} + +declare global { + interface HTMLElementTagNameMap { + 'uie-custom-dialogs-dashboard': UieCustomDialogsDashboard + } +} diff --git a/src/Our.Umbraco.UiExamples.v14/src/scripts/dialogs/custom-modal.token.ts b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-dialog.token.ts similarity index 64% rename from src/Our.Umbraco.UiExamples.v14/src/scripts/dialogs/custom-modal.token.ts rename to src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-dialog.token.ts index 2bee6b0..6c68eec 100644 --- a/src/Our.Umbraco.UiExamples.v14/src/scripts/dialogs/custom-modal.token.ts +++ b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-dialog.token.ts @@ -8,9 +8,9 @@ export type MyModalValue = { myData: string; } -export const MY_MODAL_TOKEN = new UmbModalToken('My.Modal', { +export const MY_DIALOG_TOKEN = new UmbModalToken('My.Dialog', { modal: { - type: 'sidebar', + type: 'dialog', size: 'small' } }); \ No newline at end of file diff --git a/src/Our.Umbraco.UiExamples.v14/src/scripts/dialogs/custom-modal.ts b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-dialog.ts similarity index 53% rename from src/Our.Umbraco.UiExamples.v14/src/scripts/dialogs/custom-modal.ts rename to src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-dialog.ts index a99f30a..c1c1e65 100644 --- a/src/Our.Umbraco.UiExamples.v14/src/scripts/dialogs/custom-modal.ts +++ b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-dialog.ts @@ -1,10 +1,10 @@ import { html, LitElement, property, customElement } from "@umbraco-cms/backoffice/external/lit"; import { UmbElementMixin } from "@umbraco-cms/backoffice/element-api"; import type { UmbModalContext } from "@umbraco-cms/backoffice/modal"; -import type { MyModalData, MyModalValue } from "./custom-modal.token.ts"; +import type { MyModalData, MyModalValue } from "./custom-dialog.token.ts"; import { UmbModalExtensionElement } from "@umbraco-cms/backoffice/extension-registry"; -@customElement('my-dialog') +@customElement('custom-dialog') export default class MyDialogElement extends UmbElementMixin(LitElement) implements UmbModalExtensionElement { @@ -16,7 +16,7 @@ export default class MyDialogElement data?: MyModalData; private _handleCancel() { - this.modalContext?.submit(); + this.modalContext?.reject(); } private _handleSubmit() { @@ -26,11 +26,16 @@ export default class MyDialogElement render() { return html` -
-

${this.modalContext?.data.headline ?? "Default headline"}

- - -
+ + + + ${this.modalContext?.data.headline ?? "Default headline"} + +

This is using a slot for the headline.

+ Cancel + Submit +
+
`; } } \ No newline at end of file diff --git a/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.token.ts b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.token.ts new file mode 100644 index 0000000..d855f2c --- /dev/null +++ b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.token.ts @@ -0,0 +1,17 @@ +import { UmbModalToken } from "@umbraco-cms/backoffice/modal"; + +export type MySidebarData = { + headline: string; +} + +export type MySidebarValue = { + myData: string; + myText: string; +} + +export const MY_SIDEBAR_TOKEN = new UmbModalToken('My.Sidebar', { + modal: { + type: 'sidebar', + size: 'large' + } +}); \ No newline at end of file diff --git a/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.ts b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.ts new file mode 100644 index 0000000..508ac0d --- /dev/null +++ b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.ts @@ -0,0 +1,65 @@ +import { html, LitElement, property, customElement } from "@umbraco-cms/backoffice/external/lit"; +import { UmbElementMixin } from "@umbraco-cms/backoffice/element-api"; +import type { UmbModalContext } from "@umbraco-cms/backoffice/modal"; +import type { MySidebarData, MySidebarValue } from "./custom-sidebar.token.ts"; +import { UmbModalExtensionElement } from "@umbraco-cms/backoffice/extension-registry"; +import { UmbPropertyValueChangeEvent } from "@umbraco-cms/backoffice/property-editor"; + +@customElement('my-sidebar') +export default class MySidebarElement + extends UmbElementMixin(LitElement) + implements UmbModalExtensionElement { + + @property({ attribute: false }) + modalContext?: UmbModalContext; + + @property({ attribute: false }) + data?: MySidebarData; + + private _handleCancel() { + this.modalContext?.reject(); + } + + private _handleSubmit() { + this.modalContext?.updateValue({ myData: "hello world", myText: this.textInput }); + this.modalContext?.submit(); + } + + @property({ type: String }) + public textInput = ""; + + #onInput(e: InputEvent) { + this.textInput = (e.target as HTMLInputElement).value; + this.#dispatchChangeEvent(); + } + + #dispatchChangeEvent() { + this.dispatchEvent(new UmbPropertyValueChangeEvent()); + } + + render() { + return html` + + +

Some content of this box, appended in the default slot.

+

The headline is currently rendered as a h5.

+ + + + +
+ +
+ Cancel + Submit +
+
+ `; + } +} \ No newline at end of file From 92bcd3489251d4f72c409003cb1547f72effd8b6 Mon Sep 17 00:00:00 2001 From: Richard Ockerby Date: Fri, 6 Sep 2024 14:31:52 +0200 Subject: [PATCH 3/4] Split out modals into inbuilt and custom Remove comments in manifest --- .../src/manifest.ts | 65 ------------------- .../dashboards/custom-modals-dashboard.ts | 47 ++++++++++---- .../src/scripts/modals/custom-sidebar.ts | 4 +- 3 files changed, 39 insertions(+), 77 deletions(-) diff --git a/src/Our.Umbraco.UiExamples.v14/src/manifest.ts b/src/Our.Umbraco.UiExamples.v14/src/manifest.ts index dc281b6..4c579c7 100644 --- a/src/Our.Umbraco.UiExamples.v14/src/manifest.ts +++ b/src/Our.Umbraco.UiExamples.v14/src/manifest.ts @@ -74,69 +74,4 @@ export const manifests: Array = [ "name": "My Sidebar Modal", "element": () => import("./scripts/modals/custom-sidebar.ts"), } - // ... insert as many manifests as you like - - /*"extensions": [ - { - "type": "section", - "alias": "example.ui.section", - "name": "Example UI Dashboard", - "weight": -1, - "meta": { - "label": "Example UI", - "pathname": "my-dashboard" - } - }, - { - "type": "dashboard", - "alias": "example.ui.dashboard", - "name": "Example UI Dashboard", - "js": "/App_Plugins/Example.UI/scripts/dashboards/welcome-dashboard.js", - "weight": -1, - "meta": { - "label": "Welcome Dashboard", - "pathname": "welcome-dashboard" - }, - "conditions": [ - { - "alias": "Umb.Condition.SectionAlias", - "match": "example.ui.section" - } - ] - }, - { - "type": "dashboard", - "alias": "example.ui.dashboard.dialogs", - "name": "Dialogs", - "js": "/App_Plugins/Example.UI/scripts/dashboards/custom-dialogs-dashboard.js", - "weight": -1, - "meta": { - "label": "Dialogs", - "pathname": "dialogs" - }, - "conditions": [ - { - "alias": "Umb.Condition.SectionAlias", - "match": "example.ui.section" - } - ] - }, - { - "type": "sectionView", - "alias": "example.ui.dashboard.section.boxlayout", - "js": "/App_Plugins/Example.UI/scripts/sections/box-layout-section.js", - "name": "Box Layout", - "meta": { - "sections": [ "example.ui.section" ], - "label": "Box Layout", - "icon": "folder", - "pathname": "box-layout" - }, - "conditions": [ - { - "alias": "Umb.Condition.SectionAlias", - "match": "example.ui.section" - } - ] - }*/ ] \ No newline at end of file diff --git a/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-modals-dashboard.ts b/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-modals-dashboard.ts index 3e0a962..ecc10e0 100644 --- a/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-modals-dashboard.ts +++ b/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-modals-dashboard.ts @@ -32,7 +32,10 @@ export default class UieCustomDialogsDashboard extends UmbElementMixin(LitElemen render() { return html` - + Your last action was: ${this.message ?? "Nothing clicked yet..."} +With data: ${this.returnData ?? "{}"} + +
Modals
Modals are the mechanism to display content on-top of the current display.
@@ -40,25 +43,48 @@ export default class UieCustomDialogsDashboard extends UmbElementMixin(LitElemen
- ! View the Storybook library + + + View the dialog tutorial
-

The overlay service has a confirm option built, in with this you can quickly create a confirm dialog, to present your users with a simple option. The term "Modal" covers both types of pop-overs; Dialogs and Sidebars.

- -

You can checkout all of the prebuilt modals by checking the GitHub Source

+

The term "Modal" covers both types of pop-overs; Dialogs and Sidebars. You can see examples below that define how you would open an Umbraco pre-built modal.

+ +

Modals come in two parts; the element and the token.
+ The token is responsible for triggering the modal to be displayed using the ModalManagerContext
+ The element is the UI components and is responsible for showing the HTML on screen, along with any in-modal functionality +

+ +

You can see all of the prebuilt modals by checking the GitHub Source

Confirm Dialog Debug Sidebar Code Editor Sidebar - Custom Sidebar - Custom Dialog -

Your last action was: ${this.message ?? "Nothing clicked yet..."}

-

With data: ${this.returnData ?? "{}"}

+

+

+ + +
+
+
Custom Modals
+
+
+
+ + + View the custom modal tutorial +
+ +

When you have specific requirements and the inbuilt modals don't suit your needs, you can create your own custom modal and put anything you want in there.

+ + Custom Sidebar + Custom Dialog +
` } @@ -71,11 +97,10 @@ export default class UieCustomDialogsDashboard extends UmbElementMixin(LitElemen const ctx = this.#modalManagerContext?.open(this, UMB_CODE_EDITOR_MODAL, { data: { headline:"text", - content:"Enter something", + content:"Enter something and it will be sent back from the modal", language:"javascript" }, }); - ctx?.onSubmit().then((e) => { this._handleSubmit(true, JSON.stringify(e)); }).catch(() => { diff --git a/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.ts b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.ts index 508ac0d..f6b25dc 100644 --- a/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.ts +++ b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.ts @@ -21,7 +21,7 @@ export default class MySidebarElement } private _handleSubmit() { - this.modalContext?.updateValue({ myData: "hello world", myText: this.textInput }); + this.modalContext?.updateValue({ myData: "I am added in code!", myText: this.textInput }); this.modalContext?.submit(); } @@ -49,6 +49,8 @@ export default class MySidebarElement class="element" label="text input" .value=${this.textInput || ""} + placeholder="This text will be passed back to the opener!" + width="100%" @input=${this.#onInput} > From 463e816975553e7b7ac37057be32bf532f2c0c57 Mon Sep 17 00:00:00 2001 From: Richard Ockerby Date: Fri, 6 Sep 2024 14:45:49 +0200 Subject: [PATCH 4/4] Restructure the code to have modals self contained with it's own bundle identity --- .../public/umbraco-package.json | 4 +- .../src/manifest.ts | 55 ++++++------------- .../src/scripts/modals/custom-dialog.token.ts | 2 +- .../custom-modals-dashboard.ts | 4 +- .../scripts/modals/custom-sidebar.token.ts | 2 +- .../src/scripts/modals/manifest.ts | 33 +++++++++++ 6 files changed, 55 insertions(+), 45 deletions(-) rename src/Our.Umbraco.UiExamples.v14/src/scripts/{dashboards => modals}/custom-modals-dashboard.ts (98%) create mode 100644 src/Our.Umbraco.UiExamples.v14/src/scripts/modals/manifest.ts diff --git a/src/Our.Umbraco.UiExamples.v14/public/umbraco-package.json b/src/Our.Umbraco.UiExamples.v14/public/umbraco-package.json index 20ad916..c413f4c 100644 --- a/src/Our.Umbraco.UiExamples.v14/public/umbraco-package.json +++ b/src/Our.Umbraco.UiExamples.v14/public/umbraco-package.json @@ -1,10 +1,10 @@ { - "name": "My Package Name", + "name": "Umbraco UI Examples", "version": "0.1.0", "extensions": [ { "type": "bundle", - "alias": "My.Package.Bundle", + "alias": "example.ui.bundle", "name": "Example.UI", "js": "/App_Plugins/Example.UI/manifest.js" } diff --git a/src/Our.Umbraco.UiExamples.v14/src/manifest.ts b/src/Our.Umbraco.UiExamples.v14/src/manifest.ts index 4c579c7..603f224 100644 --- a/src/Our.Umbraco.UiExamples.v14/src/manifest.ts +++ b/src/Our.Umbraco.UiExamples.v14/src/manifest.ts @@ -1,21 +1,21 @@ import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ - { - "type": "section", - "name": "Example UI Dashboard", - "alias": "example.ui.section", - "weight": 900, - "meta": { - "label": "Example UI", - "pathname": "example-ui" - } - }, + { + "type": "section", + "name": "Example UI Dashboard", + "alias": "example.ui.section", + "weight": 900, + "meta": { + "label": "Example UI", + "pathname": "example-ui" + } + }, { "type": "dashboard", "alias": "example.ui.dashboard", "name": "Example UI Dashboard", - "element": () => import("./scripts/dashboards/welcome-dashboard.ts"), + "element": () => import("./scripts/dashboards/welcome-dashboard.ts"), "weight": -1, "meta": { "label": "Welcome Dashboard", @@ -29,26 +29,15 @@ export const manifests: Array = [ ] }, { - "type": "dashboard", - "alias": "example.ui.dashboard.modals", - "name": "Modals", - "element": () => import("./scripts/dashboards/custom-modals-dashboard.ts"), - "weight": -1, - "meta": { - "label": "Modals", - "pathname": "modals" - }, - "conditions": [ - { - "alias": "Umb.Condition.SectionAlias", - "match": "example.ui.section" - } - ] + "type": "bundle", + "alias": "example.ui.modals", + "name": "Example.UI - Modals", + "js": () => import("./scripts/modals/manifest.ts") }, { "type": "sectionView", "alias": "example.ui.dashboard.section.boxlayout", - "element": () => import("./scripts/sections/box-layout-section.ts"), + "element": () => import("./scripts/sections/box-layout-section.ts"), "name": "Box Layout", "meta": { "label": "Box Layout", @@ -61,17 +50,5 @@ export const manifests: Array = [ "match": "example.ui.section" } ] - }, - { - "type": "modal", - "alias": "My.Dialog", - "name": "My Dialog", - "element": () => import("./scripts/modals/custom-dialog.ts"), - }, - { - "type": "modal", - "alias": "My.Sidebar", - "name": "My Sidebar Modal", - "element": () => import("./scripts/modals/custom-sidebar.ts"), } ] \ No newline at end of file diff --git a/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-dialog.token.ts b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-dialog.token.ts index 6c68eec..be8bb68 100644 --- a/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-dialog.token.ts +++ b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-dialog.token.ts @@ -8,7 +8,7 @@ export type MyModalValue = { myData: string; } -export const MY_DIALOG_TOKEN = new UmbModalToken('My.Dialog', { +export const MY_DIALOG_TOKEN = new UmbModalToken('example.ui.modals.dialog', { modal: { type: 'dialog', size: 'small' diff --git a/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-modals-dashboard.ts b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-modals-dashboard.ts similarity index 98% rename from src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-modals-dashboard.ts rename to src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-modals-dashboard.ts index ecc10e0..971a6b3 100644 --- a/src/Our.Umbraco.UiExamples.v14/src/scripts/dashboards/custom-modals-dashboard.ts +++ b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-modals-dashboard.ts @@ -1,7 +1,7 @@ import { LitElement, css, html } from 'lit' import { customElement, property } from 'lit/decorators.js' -import { MY_DIALOG_TOKEN } from '../modals/custom-dialog.token'; -import { MY_SIDEBAR_TOKEN } from '../modals/custom-sidebar.token'; +import { MY_DIALOG_TOKEN } from './custom-dialog.token'; +import { MY_SIDEBAR_TOKEN } from './custom-sidebar.token'; import { UMB_MODAL_MANAGER_CONTEXT, UMB_CONTEXT_DEBUGGER_MODAL, UMB_CONFIRM_MODAL, UMB_CODE_EDITOR_MODAL } from '@umbraco-cms/backoffice/modal'; import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; diff --git a/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.token.ts b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.token.ts index d855f2c..dcb36e0 100644 --- a/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.token.ts +++ b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/custom-sidebar.token.ts @@ -9,7 +9,7 @@ export type MySidebarValue = { myText: string; } -export const MY_SIDEBAR_TOKEN = new UmbModalToken('My.Sidebar', { +export const MY_SIDEBAR_TOKEN = new UmbModalToken('example.ui.modals.sidebar', { modal: { type: 'sidebar', size: 'large' diff --git a/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/manifest.ts b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/manifest.ts new file mode 100644 index 0000000..ff5a10b --- /dev/null +++ b/src/Our.Umbraco.UiExamples.v14/src/scripts/modals/manifest.ts @@ -0,0 +1,33 @@ +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + "type": "dashboard", + "alias": "example.ui.modals.dashboard", + "name": "Modals", + "element": () => import("./custom-modals-dashboard.ts"), + "weight": -1, + "meta": { + "label": "Modals", + "pathname": "modals" + }, + "conditions": [ + { + "alias": "Umb.Condition.SectionAlias", + "match": "example.ui.section" + } + ] + }, + { + "type": "modal", + "alias": "example.ui.modals.dialog", + "name": "My Dialog", + "element": () => import("./custom-dialog.ts"), + }, + { + "type": "modal", + "alias": "example.ui.modals.sidebar", + "name": "My Sidebar Modal", + "element": () => import("./custom-sidebar.ts"), + } +] \ No newline at end of file