From cf12e684a9a2aa272fd35765cf90f9d53c59ecb9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 31 May 2022 10:41:29 +0200 Subject: [PATCH] split sections and tools from header element --- .../backoffice-header-sections.element.ts | 199 ++++++++++++++++ .../backoffice-header-tools.element.ts | 44 ++++ .../backoffice/backoffice-header.element.ts | 216 +----------------- .../src/backoffice/backoffice.element.ts | 8 +- 4 files changed, 255 insertions(+), 212 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/backoffice-header-sections.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/backoffice-header-tools.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice-header-sections.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice-header-sections.element.ts new file mode 100644 index 0000000000..e34c0ce43a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice-header-sections.element.ts @@ -0,0 +1,199 @@ +import { Subscription } from 'rxjs'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { css, CSSResultGroup, html, LitElement } from 'lit'; +import { customElement, state } from 'lit/decorators.js'; +import { when } from 'lit/directives/when.js'; + +import { getUserSections } from '../core/api/fetcher'; +import { UmbExtensionManifest } from '../core/extension'; +import { UmbRouteLocation, UmbRouter } from '../core/router'; +import { UmbSectionContext } from '../section.context'; +import { UmbContextConsumerMixin } from '../core/context'; + +@customElement('umb-backoffice-header-sections') +export class UmbBackofficeHeaderSections extends UmbContextConsumerMixin(LitElement) { + static styles: CSSResultGroup = [ + UUITextStyles, + css` + #tabs { + color: var(--uui-look-primary-contrast); + height: 60px; + font-size: 16px; + --uui-tab-text: var(--uui-look-primary-contrast); + --uui-tab-text-hover: var(--uui-look-primary-contrast-hover); + --uui-tab-text-active: var(--uui-interface-active); + --uui-tab-background: var(--uui-look-primary-surface); + } + + #dropdown { + background-color: white; + border-radius: var(--uui-border-radius); + width: 100%; + height: 100%; + box-sizing: border-box; + box-shadow: var(--uui-shadow-depth-3); + min-width: 200px; + color: black; /* Change to variable */ + } + `, + ]; + + @state() + private _open = false; + + @state() + private _allowedSection: Array = []; + + @state() + private _sections: Array = []; + + @state() + private _visibleSections: Array = []; + + @state() + private _extraSections: Array = []; + + @state() + private _currentSectionAlias = ''; + + private _router?: UmbRouter; + private _sectionContext?: UmbSectionContext; + private _sectionSubscription?: Subscription; + private _currentSectionSubscription?: Subscription; + private _locationSubscription?: Subscription; + private _location? : UmbRouteLocation; + + constructor () { + super(); + + this.consumeContext('umbRouter', (_instance: UmbRouter) => { + this._router = _instance; + this._useLocation(); + }); + + this.consumeContext('umbSectionContext', (_instance: UmbSectionContext) => { + this._sectionContext = _instance; + this._useCurrentSection(); + this._useSections(); + }); + } + + private _handleMore(e: MouseEvent) { + e.stopPropagation(); + this._open = !this._open; + } + + private _handleTabClick(e: PointerEvent, section: UmbExtensionManifest) { + const tab = e.currentTarget as any; + + // TODO: we need to be able to prevent the tab from setting the active state + if (tab.id === 'moreTab') { + return; + } + + // TODO: this could maybe be handled by an anchor tag + this._router?.push(`/section/${section.meta.pathname}`); + this._sectionContext?.setCurrent(section.alias); + } + + private _handleLabelClick(e: PointerEvent) { + const label = (e.target as any).label; + + // TODO: set current section + //this._sectionContext?.setCurrent(section.alias); + + const moreTab = this.shadowRoot?.getElementById('moreTab'); + moreTab?.setAttribute('active', 'true'); + + this._open = false; + } + + private _useLocation () { + this._locationSubscription?.unsubscribe(); + + this._locationSubscription = this._router?.location + .subscribe((location: UmbRouteLocation) => { + this._location = location; + }); + } + + private _useCurrentSection () { + this._currentSectionSubscription?.unsubscribe(); + + this._currentSectionSubscription = this._sectionContext?.getCurrent() + .subscribe(section => { + this._currentSectionAlias = section.alias; + }); + } + + private async _useSections() { + this._sectionSubscription?.unsubscribe(); + + const { data } = await getUserSections({}); + this._allowedSection = data.sections; + + this._sectionSubscription = this._sectionContext?.getSections() + .subscribe((sectionExtensions: any) => { + this._sections = sectionExtensions.filter((section: any) => this._allowedSection.includes(section.alias)); + this._visibleSections = this._sections; + const currentSectionAlias = this._sections.find(section => section.meta.pathname === this._location?.params?.section)?.alias; + if (!currentSectionAlias) return; + this._sectionContext?.setCurrent(currentSectionAlias); + }); + } + + disconnectedCallback(): void { + super.disconnectedCallback(); + this._locationSubscription?.unsubscribe(); + this._sectionSubscription?.unsubscribe(); + this._currentSectionSubscription?.unsubscribe(); + } + + render() { + return html` + + ${this._visibleSections.map( + (section) => html` + + ` + )} + ${this._renderExtraSections()} + + `; + } + + private _renderExtraSections() { + return when( + this._extraSections.length > 0, + () => html` + + + + + + + + + + ` + ); + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-backoffice-header-sections': UmbBackofficeHeaderSections; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice-header-tools.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice-header-tools.element.ts new file mode 100644 index 0000000000..fdb90b3ce9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice-header-tools.element.ts @@ -0,0 +1,44 @@ + +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { css, CSSResultGroup, html, LitElement } from 'lit'; +import { customElement } from 'lit/decorators.js'; + +@customElement('umb-backoffice-header-tools') +export class UmbBackofficeHeaderTools extends LitElement { + static styles: CSSResultGroup = [ + UUITextStyles, + css` + #tools { + display: flex; + align-items: center; + gap: var(--uui-size-space-2); + } + + .tool { + font-size: 18px; + } + `, + ]; + + render() { + return html` +
+ + + + + + + + + +
+ `; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-backoffice-header-tools': UmbBackofficeHeaderTools; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice-header.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice-header.element.ts index ecaa9e793b..393cb15405 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice-header.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice-header.element.ts @@ -1,25 +1,19 @@ -import { Subscription } from 'rxjs'; + import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, CSSResultGroup, html, LitElement } from 'lit'; -import { customElement, state } from 'lit/decorators.js'; -import { when } from 'lit/directives/when.js'; - -import { getUserSections } from '../core/api/fetcher'; -import { UmbExtensionManifest, UmbManifestSectionMeta } from '../core/extension'; -import { UmbRouteLocation, UmbRouter } from '../core/router'; -import { UmbSectionContext } from '../section.context'; -import { UmbContextConsumerMixin } from '../core/context'; - -// TODO: umb or not umb in file name? +import { customElement } from 'lit/decorators.js'; +import './backoffice-header-sections.element'; +import './backoffice-header-tools.element'; @customElement('umb-backoffice-header') -export class UmbBackofficeHeader extends UmbContextConsumerMixin(LitElement) { +export class UmbBackofficeHeader extends LitElement { static styles: CSSResultGroup = [ UUITextStyles, css` :host { width: 100%; } + #appHeader { background-color: var(--uui-look-primary-surface); display: flex; @@ -41,181 +35,10 @@ export class UmbBackofficeHeader extends UmbContextConsumerMixin(LitElement) { #sections { flex: 1 1 auto; - display: flex; - align-items: center; - gap: var(--uui-size-space-2); - } - - #tabs { - color: var(--uui-look-primary-contrast); - height: 60px; - font-size: 16px; - --uui-tab-text: var(--uui-look-primary-contrast); - --uui-tab-text-hover: var(--uui-look-primary-contrast-hover); - --uui-tab-text-active: var(--uui-interface-active); - --uui-tab-background: var(--uui-look-primary-surface); - } - - #tools { - display: flex; - align-items: center; - gap: var(--uui-size-space-2); - } - - .tool { - font-size: 18px; - } - - #dropdown { - background-color: white; - border-radius: var(--uui-border-radius); - width: 100%; - height: 100%; - box-sizing: border-box; - box-shadow: var(--uui-shadow-depth-3); - min-width: 200px; - color: black; /* Change to variable */ } `, ]; - @state() - private _open = false; - - @state() - private _allowedSection: Array = []; - - @state() - private _sections: Array = []; - - @state() - private _visibleSections: Array = []; - - @state() - private _extraSections: Array = []; - - @state() - private _currentSectionAlias = ''; - - private _router?: UmbRouter; - private _sectionContext?: UmbSectionContext; - private _sectionSubscription?: Subscription; - private _currentSectionSubscription?: Subscription; - private _locationSubscription?: Subscription; - private _location? : UmbRouteLocation; - - constructor () { - super(); - - this.consumeContext('umbRouter', (_instance: UmbRouter) => { - this._router = _instance; - this._useLocation(); - }); - - this.consumeContext('umbSectionContext', (_instance: UmbSectionContext) => { - this._sectionContext = _instance; - this._useCurrentSection(); - this._useSections(); - }); - } - - private _handleMore(e: MouseEvent) { - e.stopPropagation(); - this._open = !this._open; - } - - private _handleTabClick(e: PointerEvent, section: UmbExtensionManifest) { - const tab = e.currentTarget as any; - - // TODO: we need to be able to prevent the tab from setting the active state - if (tab.id === 'moreTab') { - return; - } - - // TODO: this could maybe be handled by an anchor tag - this._router?.push(`/section/${section.meta.pathname}`); - this._sectionContext?.setCurrent(section.alias); - } - - private _handleLabelClick(e: PointerEvent) { - const label = (e.target as any).label; - - // TODO: set current section - //this._sectionContext?.setCurrent(section.alias); - - const moreTab = this.shadowRoot?.getElementById('moreTab'); - moreTab?.setAttribute('active', 'true'); - - this._open = false; - } - - private _useLocation () { - this._locationSubscription?.unsubscribe(); - - this._locationSubscription = this._router?.location - .subscribe((location: UmbRouteLocation) => { - this._location = location; - }); - } - - private _useCurrentSection () { - this._currentSectionSubscription?.unsubscribe(); - - this._currentSectionSubscription = this._sectionContext?.getCurrent() - .subscribe(section => { - this._currentSectionAlias = section.alias; - }); - } - - private async _useSections() { - this._sectionSubscription?.unsubscribe(); - - const { data } = await getUserSections({}); - this._allowedSection = data.sections; - - this._sectionSubscription = this._sectionContext?.getSections() - .subscribe((sectionExtensions: any) => { - this._sections = sectionExtensions.filter((section: any) => this._allowedSection.includes(section.alias)); - this._visibleSections = this._sections; - const currentSectionAlias = this._sections.find(section => section.meta.pathname === this._location?.params?.section)?.alias; - if (!currentSectionAlias) return; - this._sectionContext?.setCurrent(currentSectionAlias); - }); - } - - disconnectedCallback(): void { - super.disconnectedCallback(); - this._locationSubscription?.unsubscribe(); - this._sectionSubscription?.unsubscribe(); - this._currentSectionSubscription?.unsubscribe(); - } - - private _renderExtraSections() { - return when( - this._extraSections.length > 0, - () => html` - - - - - - - - - - ` - ); - } - render() { return html`
@@ -223,31 +46,8 @@ export class UmbBackofficeHeader extends UmbContextConsumerMixin(LitElement) { Umbraco -
- - ${this._visibleSections.map( - (section) => html` - - ` - )} - ${this._renderExtraSections()} - -
- -
- - - - - - - - - -
+ +
`; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index 013de137c6..7a67950cac 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -1,11 +1,11 @@ -import './backoffice-header.element'; -import './backoffice-sidebar.element'; -import './backoffice-main.element'; - import { defineElement } from '@umbraco-ui/uui-base/lib/registration'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, html, LitElement } from 'lit'; +import './backoffice-header.element'; +import './backoffice-sidebar.element'; +import './backoffice-main.element'; + @defineElement('umb-backoffice') export class UmbBackoffice extends LitElement { static styles = [