From 9dcd40e95d94d3c84208288a534beb76d4cbd8f9 Mon Sep 17 00:00:00 2001 From: ANDREI PADOLIN Date: Wed, 16 Jun 2021 16:25:20 +0300 Subject: [PATCH] feat(window): add window buttons configuration (#2762) --- src/app/playground-components.ts | 6 +++ .../components/window/window.component.scss | 2 +- .../components/window/window.component.ts | 41 ++++++++++++++----- .../theme/components/window/window.options.ts | 22 ++++++++++ .../components/window/window.service.spec.ts | 30 ++++++++++++++ .../theme/components/window/window.service.ts | 4 ++ .../window/window-controls.component.html | 12 ++++++ .../window/window-controls.component.scss | 12 ++++++ .../window/window-controls.component.ts | 28 +++++++++++++ .../window/window-routing.module.ts | 5 +++ .../with-layout/window/window.module.ts | 7 +++- 11 files changed, 157 insertions(+), 12 deletions(-) create mode 100644 src/playground/with-layout/window/window-controls.component.html create mode 100644 src/playground/with-layout/window/window-controls.component.scss create mode 100644 src/playground/with-layout/window/window-controls.component.ts diff --git a/src/app/playground-components.ts b/src/app/playground-components.ts index 9b7b0a5386..c3a189c562 100644 --- a/src/app/playground-components.ts +++ b/src/app/playground-components.ts @@ -1485,6 +1485,12 @@ export const PLAYGROUND_COMPONENTS: ComponentLink[] = [ component: 'WindowsBackdropComponent', name: 'Windows Backdrop', }, + { + path: 'window-controls.component', + link: '/window/window-controls.component', + component: 'WindowControlsComponent', + name: 'Window Controls', + }, ], }, { diff --git a/src/framework/theme/components/window/window.component.scss b/src/framework/theme/components/window/window.component.scss index 9e5314613f..4226ed58ca 100644 --- a/src/framework/theme/components/window/window.component.scss +++ b/src/framework/theme/components/window/window.component.scss @@ -21,7 +21,7 @@ .buttons { width: 9.5rem; display: flex; - justify-content: space-evenly; + justify-content: flex-end; [nbButton] { flex: 0 0 3rem; diff --git a/src/framework/theme/components/window/window.component.ts b/src/framework/theme/components/window/window.component.ts index 487c0ea975..708944f7ab 100644 --- a/src/framework/theme/components/window/window.component.ts +++ b/src/framework/theme/components/window/window.component.ts @@ -27,15 +27,24 @@ import { NbWindowRef } from './window-ref';
{{ config.title }}
- - - + + + + + + + + + + + + @@ -66,6 +75,18 @@ export class NbWindowComponent implements OnInit, AfterViewChecked, OnDestroy { return this.windowRef.state === NbWindowState.MINIMIZED; } + get showMinimize(): boolean { + return this.config.buttons.minimize; + } + + get showMaximize(): boolean { + return this.config.buttons.maximize; + } + + get showFullScreen(): boolean { + return this.config.buttons.fullScreen; + } + @ViewChild(NbOverlayContainerComponent) overlayContainer: NbOverlayContainerComponent; protected focusTrap: NbFocusTrap; @@ -127,7 +148,7 @@ export class NbWindowComponent implements OnInit, AfterViewChecked, OnDestroy { } maximizeOrFullScreen() { - if (this.windowRef.state === NbWindowState.MINIMIZED) { + if (this.windowRef.state === NbWindowState.MINIMIZED && this.showMaximize) { this.maximize(); } else { this.fullScreen(); diff --git a/src/framework/theme/components/window/window.options.ts b/src/framework/theme/components/window/window.options.ts index e9af8d5526..16f46e9b4d 100644 --- a/src/framework/theme/components/window/window.options.ts +++ b/src/framework/theme/components/window/window.options.ts @@ -15,6 +15,18 @@ export interface NbWindowStateChange { newState: NbWindowState; } +export interface NbWindowControlButtonsConfig { + minimize: boolean; + maximize: boolean; + fullScreen: boolean; +} + +export const NB_WINDOW_DEFAULT_BUTTONS_CONFIG: NbWindowControlButtonsConfig = { + minimize: true, + maximize: true, + fullScreen: true, +} + /** * Window configuration options. */ @@ -67,8 +79,18 @@ export class NbWindowConfig { */ viewContainerRef: ViewContainerRef = null; + /** + * Windows control buttons can be hidden by setting according property to false. + */ + buttons: Partial = {}; + constructor(...configs: Partial[]) { Object.assign(this, ...configs); + this.applyDefaultButtonConfig(); + } + + protected applyDefaultButtonConfig() { + Object.assign(this, { buttons: { ...NB_WINDOW_DEFAULT_BUTTONS_CONFIG, ...this.buttons } }); } } diff --git a/src/framework/theme/components/window/window.service.spec.ts b/src/framework/theme/components/window/window.service.spec.ts index cf262ebdbc..18f8bfa874 100644 --- a/src/framework/theme/components/window/window.service.spec.ts +++ b/src/framework/theme/components/window/window.service.spec.ts @@ -8,6 +8,7 @@ import { NbOverlayContainerAdapter, NB_DOCUMENT, NbThemeModule, + NbWindowControlButtonsConfig, } from '@nebular/theme'; const WINDOW_CONTENT = 'window content'; @@ -289,4 +290,33 @@ describe('window-service', () => { const windowContent = document.getElementById('window-content'); expect(document.body.contains(windowContent)).toEqual(true); })); + + it('should render all control buttons by default', () => { + const windowRef = windowService.open(NbTestWindowComponent); + windowRef.componentRef.changeDetectorRef.detectChanges(); + const windowElement: ElementRef = windowRef.componentRef.injector.get(ElementRef); + expect(windowElement.nativeElement.querySelectorAll('button').length).toBe(3); + }); + + it('should render only close button', () => { + const config: NbWindowControlButtonsConfig = { minimize: false, maximize: false, fullScreen: false }; + const windowRef = windowService.open(NbTestWindowComponent, { buttons: config}); + windowRef.componentRef.changeDetectorRef.detectChanges(); + const windowElement: ElementRef = windowRef.componentRef.injector.get(ElementRef); + const closeButton = windowElement.nativeElement.querySelectorAll('button')[0]; + expect(closeButton.getElementsByTagName('nb-icon')[0].getAttribute('icon')).toBe('close-outline'); + }); + + it('should render minimize and close button', () => { + const config: NbWindowControlButtonsConfig = { minimize: true, maximize: false, fullScreen: false }; + const windowRef = windowService.open(NbTestWindowComponent, { buttons: config}); + windowRef.maximize(); + windowRef.componentRef.changeDetectorRef.detectChanges(); + const windowElement: ElementRef = windowRef.componentRef.injector.get(ElementRef); + const buttons = Array.from(windowElement.nativeElement.querySelectorAll('button')); + const icons = buttons.map(e => e.getElementsByTagName('nb-icon')[0].getAttribute('icon')); + expect(icons.sort()).toEqual(['minus-outline', 'close-outline'].sort()); + }); + + }); diff --git a/src/framework/theme/components/window/window.service.ts b/src/framework/theme/components/window/window.service.ts index 50a95e0ff2..e328857e00 100644 --- a/src/framework/theme/components/window/window.service.ts +++ b/src/framework/theme/components/window/window.service.ts @@ -98,6 +98,10 @@ import { NB_DOCUMENT } from '../../theme.options'; * You can read about all available options on [API tab](docs/components/window/api#nbwindowconfig). * * @stacked-example(Configuration, window/windows-backdrop.component) + * + * You can configure which buttons are available in a window via the `buttons` property of the window config. + * @stacked-example(Control buttons, window/window-controls.component) + * */ @Injectable() export class NbWindowService { diff --git a/src/playground/with-layout/window/window-controls.component.html b/src/playground/with-layout/window/window-controls.component.html new file mode 100644 index 0000000000..acfde493f2 --- /dev/null +++ b/src/playground/with-layout/window/window-controls.component.html @@ -0,0 +1,12 @@ + + + +

Buttons config:

+ Minimize + Maximize + Full Screen + + + +
+
diff --git a/src/playground/with-layout/window/window-controls.component.scss b/src/playground/with-layout/window/window-controls.component.scss new file mode 100644 index 0000000000..ebd0ac44a0 --- /dev/null +++ b/src/playground/with-layout/window/window-controls.component.scss @@ -0,0 +1,12 @@ +.config-title { + margin-top: 0; + margin-bottom: 0.25rem; +} + +nb-checkbox { + display: block; +} + +.open-window { + margin-top: 1rem; +} diff --git a/src/playground/with-layout/window/window-controls.component.ts b/src/playground/with-layout/window/window-controls.component.ts new file mode 100644 index 0000000000..4f904cf322 --- /dev/null +++ b/src/playground/with-layout/window/window-controls.component.ts @@ -0,0 +1,28 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { NbWindowControlButtonsConfig, NbWindowService } from '@nebular/theme'; + +import { FormComponent } from './components/form.component'; + +@Component({ + templateUrl: 'window-controls.component.html', + styleUrls: ['./window.scss', './window-controls.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class WindowControlsComponent { + + minimize = true; + maximize = true; + fullScreen = true; + + constructor(private windowService: NbWindowService) { } + + openWindow() { + const buttonsConfig: NbWindowControlButtonsConfig = { + minimize: this.minimize, + maximize: this.maximize, + fullScreen: this.fullScreen, + }; + + this.windowService.open(FormComponent, { title: `Window`, buttons: buttonsConfig }); + } +} diff --git a/src/playground/with-layout/window/window-routing.module.ts b/src/playground/with-layout/window/window-routing.module.ts index 3e72dbb6ff..5748ca2c99 100644 --- a/src/playground/with-layout/window/window-routing.module.ts +++ b/src/playground/with-layout/window/window-routing.module.ts @@ -9,6 +9,7 @@ import { RouterModule, Route} from '@angular/router'; import { TemplateWindowComponent } from './template-window.component'; import { WindowShowcaseComponent } from './window-showcase.component'; import { WindowsBackdropComponent } from './windows-backdrop.component'; +import { WindowControlsComponent } from './window-controls.component'; const routes: Route[] = [ { @@ -23,6 +24,10 @@ const routes: Route[] = [ path: 'windows-backdrop.component', component: WindowsBackdropComponent, }, + { + path: 'window-controls.component', + component: WindowControlsComponent, + }, ]; @NgModule({ diff --git a/src/playground/with-layout/window/window.module.ts b/src/playground/with-layout/window/window.module.ts index c4ab2bbe57..e527205c46 100644 --- a/src/playground/with-layout/window/window.module.ts +++ b/src/playground/with-layout/window/window.module.ts @@ -5,12 +5,14 @@ */ import { NgModule } from '@angular/core'; -import { NbButtonModule, NbInputModule, NbWindowModule } from '@nebular/theme'; +import { NbButtonModule, NbCardModule, NbCheckboxModule, NbInputModule, NbWindowModule } from '@nebular/theme'; + import { WindowRoutingModule } from './window-routing.module'; import { TemplateWindowComponent } from './template-window.component'; import { WindowShowcaseComponent } from './window-showcase.component'; import { WindowsBackdropComponent } from './windows-backdrop.component'; import { FormComponent } from './components/form.component'; +import { WindowControlsComponent } from './window-controls.component'; @NgModule({ declarations: [ @@ -18,11 +20,14 @@ import { FormComponent } from './components/form.component'; WindowShowcaseComponent, WindowsBackdropComponent, FormComponent, + WindowControlsComponent, ], imports: [ NbWindowModule.forRoot(), NbButtonModule, NbInputModule, + NbCheckboxModule, + NbCardModule, WindowRoutingModule, ], entryComponents: [ FormComponent ],