diff --git a/docs/README.md b/docs/README.md index fa84c22b40f..63b2bfa9863 100644 --- a/docs/README.md +++ b/docs/README.md @@ -342,6 +342,7 @@ for more information about installing and using the source code. | Name | Description | Source link | | ---- | ----------- | ----------- | +| [Dialog component](content-services/dialogs/dialog.md) | Dialog styled wrapper. | [Source](../lib/content-services/src/lib/dialogs/dialog/dialog.component.ts) | | [Confirm dialog component](content-services/dialogs/confirm.dialog.md) | Requests a yes/no choice from the user. | [Source](../lib/content-services/src/lib/dialogs/confirm.dialog.ts) | | [Library dialog component](content-services/dialogs/library.dialog.md) | Creates a new Content Services document library/site. | [Source](../lib/content-services/src/lib/dialogs/library/library.dialog.ts) | diff --git a/docs/content-services/dialogs/dialog.md b/docs/content-services/dialogs/dialog.md new file mode 100644 index 00000000000..1fbf21912da --- /dev/null +++ b/docs/content-services/dialogs/dialog.md @@ -0,0 +1,86 @@ +--- +Title: Dialog component +Added: v6.9.0 +Status: Active +Last reviewed: 2024-05-17 +--- + +# [Dialog component](../../../lib/content-services/src/lib/dialogs/dialog/ "Defined in dialog.component.ts") + +Dialog wrapper styled according to a consistent design system. + +## Dialog views + +### Large size and Medium + +Looks the same but have different sizes. +Max-width for Large dialog is `1075px`; +Max-width for Medium dialog is `778px`; + +![Large and Medium dialog component](../../docassets/images/adf-dialog.png) + +### Alert dialogs + +Standard: + +![Standard alert dialog component](../../docassets/images/adf-dialog-alert-standart.png) + +With icon: + +![Alert dialog component with icon](../../docassets/images/adf-dialog-alert-with-icon.png) + +### Dialog with additional buttons + +![Dialog with additional buttons](../../docassets/images/adf-dialog-with-additional-buttons.png) + +## Basic Usage + +```html + + + Lorem ipsum dolor sit amet consectetur adipisicing elit. Similique nihil, natus corrupti asperiores voluptas, incidunt veritatis. + + + + + + + +``` + +```ts +@ViewChild('contentDialogTemplate') contentDialogTemplate: TemplateRef; +@ViewChild('actionsDialogTemplate') actionsDialogTemplate: TemplateRef; + +constructor(private dialog: MatDialog) {} + +//... + +function openDialog() { + const data: DialogData = { + title: 'Dialog title', + dialogSize: DialogSize.Alert, + isConfirmButtonDisabled$: of(true), + contentTemplate: this.contentDialogTemplate, + actionsTemplate: this.actionsDialogTemplate + }; + + this.dialog.open(DialogComponent, { data }); +} +``` + +## Details + +This component lets the user reuse styled dialog wrapper. Use the +Angular [`MatDialog`](https://material.angular.io/components/dialog/overview) +service to open the dialog, as shown in the example, and pass a `data` object +with properties. + +## See also + +- [Dialog Data Interface](../interfaces/dialog.interface.md) +- [Dialog Model](../models/dialog.model.md) diff --git a/docs/content-services/interfaces/dialog.interface.md b/docs/content-services/interfaces/dialog.interface.md new file mode 100644 index 00000000000..45870e0a217 --- /dev/null +++ b/docs/content-services/interfaces/dialog.interface.md @@ -0,0 +1,51 @@ +--- +Title: Dialog Data Interface +Added: v6.9.0 +Status: Active +Last reviewed: 2024-05-17 +--- + +# [Dialog Data Interface](../../../lib/content-services/src/lib/dialogs/dialog/dialog-data.interface.ts "Defined in dialog-data.interface.ts") + +Specifies interface for [Dialog Component](../dialogs/dialog.md). + +## Basic usage + +```ts +interface DialogData { + title: string; + description?: string; + confirmButtonTitle?: string; + cancelButtonTitle?: string; + isConfirmButtonDisabled$?: Subject; + isCloseButtonHidden?: boolean; + isCancelButtonHidden?: boolean; + dialogSize?: DialogSizes; + contentTemplate?: TemplateRef; + actionsTemplate?: TemplateRef; + descriptionTemplate?: TemplateRef; + headerIcon?: string; +} +``` + +## Properties + +| Name | Type | Default value | Description | +| ---- | ---- | ------------- | ----------- | +| title | `string` | | It will be placed in the dialog title section. | +| headerIcon | `string` | | It will be placed in header section. Should be used with Alert dialogs. (optional) | +| description | `string` | | It will be placed first in the dialog content section. (optional) | +| confirmButtonTitle | `string` | `COMMON.APPLY` | Confirmation action. After this, the dialog is closed and the `isConfirmButtonDisabled$` is set to `true`. (optional) | +| cancelButtonTitle | `string` | `COMMON.CANCEL` | Cancellation action. After this, the dialog is closed | +| isCancelButtonHidden | `boolean` | `false` | Toggles cancel button visibility. (optional) | +| isCloseButtonHidden | `boolean` | `false` | Toggles close button visibility. (optional) | +| isConfirmButtonDisabled$ | `Subject` | `false` | Toggles confirm button disability. (optional) | +| dialogSize | `DialogSize` | `Medium` | Set dialog size. Can be `Large`, `Medium`, `Alert`. (optional) | +| contentTemplate | `TemplateRef` | | Inserts a content template. (optional) | +| actionsTemplate | `TemplateRef` | | Inserts a template styled on the left. Should be used for additional `mat-button` style buttons. (optional) | +| descriptionTemplate | `TemplateRef` | | Inserts a description template. (optional) | + +## See also + +- [Dialog Component](../dialogs/dialog.md) +- [Dialog Model](../models/dialog.model.md) diff --git a/docs/content-services/models/dialog.model.md b/docs/content-services/models/dialog.model.md new file mode 100644 index 00000000000..c0cc663d3b6 --- /dev/null +++ b/docs/content-services/models/dialog.model.md @@ -0,0 +1,52 @@ +--- +Title: Dialog Size Model +Added: v6.9.0 +Status: Active +Last reviewed: 2024-05-17 +--- + +# [Dialog Size model](../../../lib/content-services/src/lib/dialogs/dialog/dialog.model.ts "Defined in dialog.model.ts") + +Sets a specific CSS class to [Dialog Component](../dialogs/dialog.md). + +## Basic usage + +```ts +const DialogSize = { + Large: 'adf-large', + Medium: 'adf-medium', + Alert: 'adf-alert' +} as const; + +type DialogSizes = typeof DialogSize[keyof typeof DialogSize]; +``` + +## Properties + +| Name | Type | Default value | Description | +| ---- | ---- | ------------- | ----------- | +| Large | `string` | `adf-large` | Add `afd-large` class to Dialog container | +| Medium | `string` | `adf-medium` | Add `afd-medium` class to Dialog container | +| Alert | `string` | `adf-alert` | Add `afd-alert` class to Dialog container | + +### Examples + +```ts +constructor(private dialog: MatDialog) {} + +... + +function openDialog() { + const data: DialogData = { + title: 'Dialog title', + dialogSize: DialogSize.Large, + }; + + this.dialog.open(DialogComponent, { data }); +} +``` + +## See also + +- [Dialog Component](../dialogs/dialog.md) +- [Dialog Data Interface](../interfaces/dialog.interface.md) diff --git a/docs/docassets/images/adf-dialog-alert-standart.png b/docs/docassets/images/adf-dialog-alert-standart.png new file mode 100644 index 00000000000..e2c76f7ecbb Binary files /dev/null and b/docs/docassets/images/adf-dialog-alert-standart.png differ diff --git a/docs/docassets/images/adf-dialog-alert-with-icon.png b/docs/docassets/images/adf-dialog-alert-with-icon.png new file mode 100644 index 00000000000..6540f95c798 Binary files /dev/null and b/docs/docassets/images/adf-dialog-alert-with-icon.png differ diff --git a/docs/docassets/images/adf-dialog-with-additional-buttons.png b/docs/docassets/images/adf-dialog-with-additional-buttons.png new file mode 100644 index 00000000000..71b67d58c26 Binary files /dev/null and b/docs/docassets/images/adf-dialog-with-additional-buttons.png differ diff --git a/docs/docassets/images/adf-dialog.png b/docs/docassets/images/adf-dialog.png new file mode 100644 index 00000000000..d10cb2e626f Binary files /dev/null and b/docs/docassets/images/adf-dialog.png differ diff --git a/lib/content-services/src/lib/dialogs/dialog/dialog-data.interface.ts b/lib/content-services/src/lib/dialogs/dialog/dialog-data.interface.ts new file mode 100644 index 00000000000..9f2ce2bdcc9 --- /dev/null +++ b/lib/content-services/src/lib/dialogs/dialog/dialog-data.interface.ts @@ -0,0 +1,35 @@ +/*! + * @license + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { TemplateRef } from '@angular/core'; +import { Subject } from 'rxjs'; +import { DialogSizes } from './dialog.model'; + +export interface DialogData { + title: string; + description?: string; + confirmButtonTitle?: string; + cancelButtonTitle?: string; + isConfirmButtonDisabled$?: Subject; + isCloseButtonHidden?: boolean; + isCancelButtonHidden?: boolean; + dialogSize?: DialogSizes; + contentTemplate?: TemplateRef; + actionsTemplate?: TemplateRef; + descriptionTemplate?: TemplateRef; + headerIcon?: string; +} diff --git a/lib/content-services/src/lib/dialogs/dialog/dialog.component.html b/lib/content-services/src/lib/dialogs/dialog/dialog.component.html new file mode 100644 index 00000000000..c39f0839273 --- /dev/null +++ b/lib/content-services/src/lib/dialogs/dialog/dialog.component.html @@ -0,0 +1,68 @@ +
+
+
+ + {{data.headerIcon}} + +

{{data.title}}

+
+ +
+ +
+ {{data.description}} +
+ + + + + + +
+ +
+
+ + + +
+
+
diff --git a/lib/content-services/src/lib/dialogs/dialog/dialog.component.scss b/lib/content-services/src/lib/dialogs/dialog/dialog.component.scss new file mode 100644 index 00000000000..22ccaa35cb6 --- /dev/null +++ b/lib/content-services/src/lib/dialogs/dialog/dialog.component.scss @@ -0,0 +1,226 @@ +$dialog-large-l-width: 1075px; +$dialog-large-l-height: 907px; + +$dialog-medium-l-width: 691px; +$dialog-medium-l-height: 778px; + +$dialog-small-l-width: 461px; +$dialog-small-s-width: 346px; +$dialog-small-l-height: 432px; +$dialog-small-s-height: 360px; + +$l-screen: 1920px; +$m-screen: 1680px; +$s-screen: 1440px; +$xs-screen: 375px; + +$breakpoint-alert-with-additional-buttons-centered: 1469px; +$breakpoint-medium-with-additional-buttons-centered: 1469px; +$breakpoint-large-with-additional-buttons-centered: 642px; + +$dialog-padding: 24px; + +.adf-dialog-container { + min-width: calc(269px - $dialog-padding * 2); + min-height: calc(300px - $dialog-padding * 2); + position: relative; + display: flex; + flex-direction: column; + max-height: calc(84vh - $dialog-padding * 2); + + .adf-dialog-header, + .adf-dialog-content, + .adf-dialog-actions { + margin: 0; + padding: 0; + } + + .adf-dialog-header { + position: relative; + display: flex; + justify-content: space-between; + align-items: center; + padding-bottom: $dialog-padding; + + &.adf-centered-header { + align-items: flex-start; + } + + .adf-dialog-title { + font-size: large; + font-weight: 200; + margin: 0; + } + + .adf-dialog-header-icon { + width: 48px; + height: 48px; + font-size: 48px; + } + } + + .adf-description { + padding-top: $dialog-padding; + } + + .adf-dialog-content { + margin: $dialog-padding 0; + overflow: auto; + flex: 1; + max-height: none; + line-height: 20px; + } + + .adf-dialog-header, + .adf-dialog-actions { + &::after { + content: ' '; + position: absolute; + left: -$dialog-padding; + display: block; + height: 0; + border-bottom: 1px solid var(--adf-theme-foreground-divider-color); + width: calc(100% + $dialog-padding * 2); + } + } + + .adf-dialog-actions::after { + top: 0; + } + + .adf-dialog-header::after { + bottom: 0; + } + + .adf-dialog-actions { + position: relative; + display: flex; + justify-content: space-between; + padding-top: $dialog-padding; + text-transform: capitalize; + min-height: auto; + + // TODO: Update after migration to Angular 15 + /* stylelint-disable-next-line selector-class-pattern */ + .mat-button.mat-button-base + .mat-button-base { + margin-left: 16px; + } + + // TODO: Update after migration to Angular 15 + /* stylelint-disable-next-line selector-class-pattern */ + .mat-button { + text-transform: capitalize; + } + } + + // TODO: Update after migration to Angular 15 + /* stylelint-disable-next-line selector-class-pattern */ + .mat-dialog-container { + border-radius: 8px; + } + + &.adf-large { + max-width: calc(56vw - $dialog-padding * 2); + max-height: calc(84vh - $dialog-padding * 2); + + @media screen and (min-width: $l-screen) { + max-width: calc($dialog-large-l-width - $dialog-padding * 2); + } + + @media screen and (min-height: $dialog-large-l-width) { + max-height: calc($dialog-large-l-height - $dialog-padding * 2); + } + + @media screen and (max-width: $xs-screen) { + max-width: calc(100vw - $dialog-padding * 2); + max-height: calc(100vh - $dialog-padding * 2); + } + + @media screen and (max-width: $breakpoint-large-with-additional-buttons-centered) { + .adf-additional-actions { + justify-content: center; + } + } + } + + &.adf-medium { + max-width: calc(36vw - $dialog-padding * 2); + max-height: calc(72vh - $dialog-padding * 2); + + @media screen and (min-width: $l-screen) { + max-width: calc($dialog-medium-l-width - $dialog-padding * 2); + } + + @media screen and (max-width: $xs-screen) { + max-width: calc(100vw - $dialog-padding * 2); + max-height: calc(100vh - $dialog-padding * 2); + } + + @media screen and (min-height: $dialog-large-l-width) { + max-height: calc($dialog-medium-l-height - $dialog-padding * 2); + } + + @media screen and (max-width: $breakpoint-medium-with-additional-buttons-centered) { + .adf-additional-actions { + justify-content: center; + } + } + } + + &.adf-alert { + .adf-centered-title { + padding-left: 40px; + margin: auto; + text-align: center; + } + + .adf-dialog-content { + margin: 0; + } + + .adf-dialog-header { + padding: 0; + } + + .adf-dialog-header, + .adf-dialog-actions { + &::after { + display: none; + } + } + + max-width: calc(24vw - $dialog-padding * 2); + max-height: calc(40vh - $dialog-padding * 2); + + @media screen and (min-width: $m-screen) { + max-width: calc($dialog-small-l-width - $dialog-padding * 2); + max-height: calc($dialog-small-l-height - $dialog-padding * 2); + } + + @media screen and (max-width: $s-screen) { + max-width: calc($dialog-small-s-width - $dialog-padding * 2); + max-height: calc($dialog-small-s-height - $dialog-padding * 2); + } + + @media screen and (max-width: $xs-screen) { + max-width: calc(84vw - $dialog-padding * 2); + max-height: calc(41vh - $dialog-padding * 2); + } + + @media screen and (max-height: $dialog-small-l-height) { + max-height: calc(84vh - $dialog-padding * 2); + } + + @media screen and (max-width: $breakpoint-alert-with-additional-buttons-centered) { + .adf-additional-actions { + justify-content: center; + } + } + } + + @media screen and (max-width: $xs-screen) { + .adf-additional-actions { + justify-content: center; + } + } +} diff --git a/lib/content-services/src/lib/dialogs/dialog/dialog.component.spec.ts b/lib/content-services/src/lib/dialogs/dialog/dialog.component.spec.ts new file mode 100644 index 00000000000..403c72c9b66 --- /dev/null +++ b/lib/content-services/src/lib/dialogs/dialog/dialog.component.spec.ts @@ -0,0 +1,259 @@ +/*! + * @license + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ContentTestingModule } from '../../testing/content.testing.module'; +import { DialogComponent } from './dialog.component'; +import { DialogData } from './dialog-data.interface'; +import { DialogSize } from './dialog.model'; + +describe('DialogComponent', () => { + let component: DialogComponent; + let fixture: ComponentFixture; + let closeButton: HTMLButtonElement; + let cancelButton: HTMLButtonElement; + let confirmButton: HTMLButtonElement; + let dialogContainer: HTMLElement; + + const data: DialogData = { + title: 'Title', + description: 'Description that can be longer or shorter' + }; + + const dialogRef = { + close: jasmine.createSpy('close') + }; + + const setupBeforeEach = (dialogOptions: DialogData = data) => { + TestBed.configureTestingModule({ + imports: [ContentTestingModule], + providers: [ + { provide: MAT_DIALOG_DATA, useValue: dialogOptions }, + { provide: MatDialogRef, useValue: dialogRef } + ] + }).compileComponents(); + dialogRef.close.calls.reset(); + fixture = TestBed.createComponent(DialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + + confirmButton = fixture.nativeElement.querySelector('[data-automation-id="adf-dialog-actions-confirm"]'); + closeButton = fixture.nativeElement.querySelector('[data-automation-id="adf-dialog-close-button"]'); + cancelButton = fixture.nativeElement.querySelector( + '[data-automation-id="adf-dialog-actions-cancel"]'); + dialogContainer = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-dialog-container"]'); + }; + + describe('when init with default data', () => { + beforeEach(() => { + setupBeforeEach(); + }); + + it('should have default template elements', () => { + expect(dialogContainer).toBeDefined(); + expect(fixture.nativeElement.querySelector('.adf-dialog-header')).toBeDefined(); + expect(fixture.nativeElement.querySelector('.adf-dialog-content')).toBeDefined(); + expect(fixture.nativeElement.querySelector('.adf-dialog-actions')).toBeDefined(); + }); + + it('should have default values for the dialog', () => { + expect(closeButton).toBeDefined(); + + expect(dialogContainer.classList).toContain('adf-medium'); + + expect(confirmButton.innerText).toBe('COMMON.APPLY'); + + expect(cancelButton.innerText).toBe('COMMON.CANCEL'); + }); + }); + + describe('confirm action', () => { + const mockButtonTitle = 'mockTitle'; + beforeEach(() => { + setupBeforeEach({ ...data, confirmButtonTitle: mockButtonTitle}); + fixture.detectChanges(); + }); + + it('should disable confirm button after confirm button was clicked', (done) => { + expect(confirmButton.getAttribute('disabled')).toBeFalsy(); + + confirmButton.click(); + fixture.detectChanges(); + + expect(confirmButton.getAttribute('disabled')).toBeTruthy(); + component.isConfirmButtonDisabled$.subscribe((value) => { + expect(value).toBeTrue(); + done(); + }); + }); + + it('should disable confirm button with updated confirmButtonDisabled$', () => { + component.isConfirmButtonDisabled$.next(false); + + expect(confirmButton.getAttribute('disabled')).toBeFalsy(); + + component.isConfirmButtonDisabled$.next(true); + fixture.detectChanges(); + + expect(confirmButton.getAttribute('disabled')).toBeTruthy(); + }); + + it('should close dialog', () => { + component.onConfirm(); + expect(dialogRef.close).toHaveBeenCalled(); + }); + + it('should set correct button title', () => { + expect(component.confirmButtonTitle).toEqual(mockButtonTitle); + }); + }); + + describe('cancel action', () => { + beforeEach(() => { + setupBeforeEach(); + }); + + it('should close dialog when cancel button was clicked', () => { + cancelButton.click(); + fixture.detectChanges(); + expect(dialogRef.close).toHaveBeenCalled(); + }); + + it('should close dialog when close button was clicked', () => { + closeButton.click(); + fixture.detectChanges(); + expect(dialogRef.close).toHaveBeenCalled(); + }); + }); + + describe('when isCloseButtonHidden and isCancelButtonHidden set to true', () => { + beforeEach(() => { + setupBeforeEach({ + ...data, + isCloseButtonHidden: true, + isCancelButtonHidden: true + }); + }); + + it ('should hide close button', () => { + expect(closeButton).toBeNull(); + }); + + + it ('should hide close button', () => { + expect(cancelButton).toBeNull(); + }); + }); + + describe('when dialog has large size', () => { + beforeEach(() => { + setupBeforeEach({ ...data, dialogSize: DialogSize.Large}); + }); + + it('should have correct dialogSize value', () => { + expect(component.dialogSize).toEqual(DialogSize.Large); + }); + + it(`should contain ${DialogSize.Large} class`, () => { + expect(dialogContainer.classList).toContain(DialogSize.Large); + }); + + it('should not have header and actions border', () => { + const headerBorder = fixture.nativeElement.querySelector('.adf-alert .adf-dialog-header::after'); + const actionsBorder = fixture.nativeElement.querySelector('.adf-alert .adf-dialog-actions::after'); + + expect(headerBorder).toBeDefined(); + expect(actionsBorder).toBeDefined(); + }); + }); + + describe('when dialog has medium size', () => { + beforeEach(() => { + setupBeforeEach({ ...data, dialogSize: DialogSize.Medium}); + }); + + it('should have correct dialogSize value', () => { + expect(component.dialogSize).toEqual(DialogSize.Medium); + }); + + it(`should contain ${DialogSize.Medium} class`, () => { + expect(dialogContainer.classList).toContain(DialogSize.Medium); + }); + + it('should not have header and actions border', () => { + const headerBorder = fixture.nativeElement.querySelector('.adf-alert .adf-dialog-header::after'); + const actionsBorder = fixture.nativeElement.querySelector('.adf-alert .adf-dialog-actions::after'); + + expect(headerBorder).toBeDefined(); + expect(actionsBorder).toBeDefined(); + }); + }); + + describe('when dialog has alert size', () => { + describe('when dialog has not an ican', () => { + beforeEach(() => { + setupBeforeEach({ ...data, dialogSize: DialogSize.Alert}); + }); + + it('should have correct dialogSize value', () => { + expect(component.dialogSize).toEqual(DialogSize.Alert); + }); + + it(`should contain ${DialogSize.Alert} class`, () => { + expect(dialogContainer.classList).toContain(DialogSize.Alert); + }); + + it('should not have header and actions border', () => { + const headerBorder = fixture.nativeElement.querySelector('.adf-alert .adf-dialog-header::after'); + const actionsBorder = fixture.nativeElement.querySelector('.adf-alert .adf-dialog-actions::after'); + + expect(headerBorder).toBeNull(); + expect(actionsBorder).toBeNull(); + }); + + it('should not center header content', () => { + const header = fixture.nativeElement.querySelector('.adf-centered-header'); + + expect(header).toBeNull(); + }); + }); + + describe('when header contains icon', () => { + beforeEach(() => { + setupBeforeEach({ + ...data, + dialogSize: DialogSize.Alert, + headerIcon: 'access_time' + }); + }); + + it('should have icon element', () => { + const headerIcon = fixture.nativeElement.querySelector('.adf-dialog-header-icon'); + + expect(headerIcon).toBeDefined(); + }); + + + it('should center header content', () => { + const header = fixture.nativeElement.querySelector('.adf-centered-header'); + + expect(header).toBeDefined(); + }); + }); + }); +}); diff --git a/lib/content-services/src/lib/dialogs/dialog/dialog.component.ts b/lib/content-services/src/lib/dialogs/dialog/dialog.component.ts new file mode 100644 index 00000000000..2f59abdf696 --- /dev/null +++ b/lib/content-services/src/lib/dialogs/dialog/dialog.component.ts @@ -0,0 +1,74 @@ +/*! + * @license + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Component, Inject, OnDestroy, ViewEncapsulation } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { DialogData } from './dialog-data.interface'; +import { BehaviorSubject, Subject } from 'rxjs'; +import { DialogSize, DialogSizes } from './dialog.model'; +import { MaterialModule } from '../../material.module'; +import { CommonModule } from '@angular/common'; +import { TranslateModule } from '@ngx-translate/core'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + standalone: true, + selector: 'adf-dialog', + templateUrl: './dialog.component.html', + styleUrls: ['./dialog.component.scss'], + imports: [CommonModule, MaterialModule, TranslateModule], + encapsulation: ViewEncapsulation.None +}) +export class DialogComponent implements OnDestroy { + isConfirmButtonDisabled$ = new BehaviorSubject(false); + isCloseButtonHidden: boolean; + isCancelButtonHidden: boolean; + dialogSize: DialogSizes; + confirmButtonTitle: string; + cancelButtonTitle: string; + disableSubmitButton = false; + + private onDestroy$ = new Subject(); + + constructor( + @Inject(MAT_DIALOG_DATA) + public data: DialogData, + public dialogRef: MatDialogRef + ) { + if (data) { + this.isCancelButtonHidden = data.isCancelButtonHidden || false; + this.isCloseButtonHidden = data.isCloseButtonHidden || false; + this.dialogSize = data.dialogSize || DialogSize.Medium; + this.confirmButtonTitle = data.confirmButtonTitle || 'COMMON.APPLY'; + this.cancelButtonTitle = data.cancelButtonTitle || 'COMMON.CANCEL'; + + if (data.isConfirmButtonDisabled$) { + data.isConfirmButtonDisabled$.pipe(takeUntil(this.onDestroy$)).subscribe((value) => this.isConfirmButtonDisabled$.next(value)); + } + } + } + + onConfirm() { + this.isConfirmButtonDisabled$.next(true); + this.dialogRef.close(); + } + + ngOnDestroy() { + this.onDestroy$.next(); + this.onDestroy$.complete(); + } +} diff --git a/lib/content-services/src/lib/dialogs/dialog/dialog.model.ts b/lib/content-services/src/lib/dialogs/dialog/dialog.model.ts new file mode 100644 index 00000000000..dc92124977f --- /dev/null +++ b/lib/content-services/src/lib/dialogs/dialog/dialog.model.ts @@ -0,0 +1,24 @@ +/*! + * @license + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const DialogSize = { + Large: 'adf-large', + Medium: 'adf-medium', + Alert: 'adf-alert' +} as const; + +export type DialogSizes = typeof DialogSize[keyof typeof DialogSize]; diff --git a/lib/content-services/src/lib/dialogs/dialog/index.ts b/lib/content-services/src/lib/dialogs/dialog/index.ts new file mode 100644 index 00000000000..365c2850ed2 --- /dev/null +++ b/lib/content-services/src/lib/dialogs/dialog/index.ts @@ -0,0 +1,20 @@ +/*! + * @license + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './dialog-data.interface'; +export * from './dialog.model'; +export * from './dialog.component'; diff --git a/lib/content-services/src/lib/dialogs/public-api.ts b/lib/content-services/src/lib/dialogs/public-api.ts index 05fc55c7983..85e8637d79e 100644 --- a/lib/content-services/src/lib/dialogs/public-api.ts +++ b/lib/content-services/src/lib/dialogs/public-api.ts @@ -22,9 +22,9 @@ export * from './category-selector.dialog'; export * from './dialog.module'; export * from './library/library.dialog'; +export * from './dialog'; export * from './download-zip/download-zip.dialog'; export * from './download-zip/download-zip.dialog.module'; - export * from './folder-name.validators'; diff --git a/lib/content-services/src/lib/i18n/ar.json b/lib/content-services/src/lib/i18n/ar.json index 1506518f5ce..2929c90c176 100644 --- a/lib/content-services/src/lib/i18n/ar.json +++ b/lib/content-services/src/lib/i18n/ar.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "تطبيق", + "CANCEL": "إلغاء" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "استعادة", diff --git a/lib/content-services/src/lib/i18n/cs.json b/lib/content-services/src/lib/i18n/cs.json index 84ebb27ee77..82afdd8b79c 100644 --- a/lib/content-services/src/lib/i18n/cs.json +++ b/lib/content-services/src/lib/i18n/cs.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "Použít", + "CANCEL": "Zrušit" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "Obnovit", diff --git a/lib/content-services/src/lib/i18n/da.json b/lib/content-services/src/lib/i18n/da.json index d7528f7fffd..4b273f46e82 100644 --- a/lib/content-services/src/lib/i18n/da.json +++ b/lib/content-services/src/lib/i18n/da.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "Anvend", + "CANCEL": "Annuller" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "Gendan", diff --git a/lib/content-services/src/lib/i18n/de.json b/lib/content-services/src/lib/i18n/de.json index 04d0fffce40..18025188b96 100644 --- a/lib/content-services/src/lib/i18n/de.json +++ b/lib/content-services/src/lib/i18n/de.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "Anwenden", + "CANCEL": "Abbrechen" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "Wiederherstellen", diff --git a/lib/content-services/src/lib/i18n/en.json b/lib/content-services/src/lib/i18n/en.json index 0e41436f955..df03cb26bcd 100644 --- a/lib/content-services/src/lib/i18n/en.json +++ b/lib/content-services/src/lib/i18n/en.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "Apply", + "CANCEL": "Cancel" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "Restore", diff --git a/lib/content-services/src/lib/i18n/es.json b/lib/content-services/src/lib/i18n/es.json index 1fa28efc131..877485549bd 100644 --- a/lib/content-services/src/lib/i18n/es.json +++ b/lib/content-services/src/lib/i18n/es.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "Aplicar", + "CANCEL": "Cancelar" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "Restaurar", diff --git a/lib/content-services/src/lib/i18n/fi.json b/lib/content-services/src/lib/i18n/fi.json index dc178597228..5f9b1b9f5c4 100644 --- a/lib/content-services/src/lib/i18n/fi.json +++ b/lib/content-services/src/lib/i18n/fi.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "Käytä", + "CANCEL": "Peruuta" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "Palauta", diff --git a/lib/content-services/src/lib/i18n/fr.json b/lib/content-services/src/lib/i18n/fr.json index 5c97a782f31..ff59434f4dc 100644 --- a/lib/content-services/src/lib/i18n/fr.json +++ b/lib/content-services/src/lib/i18n/fr.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "Appliquer", + "CANCEL": "Annuler" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "Restaurer", diff --git a/lib/content-services/src/lib/i18n/it.json b/lib/content-services/src/lib/i18n/it.json index c5f555a52e8..0e13291e20b 100644 --- a/lib/content-services/src/lib/i18n/it.json +++ b/lib/content-services/src/lib/i18n/it.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "Applica", + "CANCEL": "Annulla" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "Ripristina", diff --git a/lib/content-services/src/lib/i18n/ja.json b/lib/content-services/src/lib/i18n/ja.json index 0a8e372699c..ab30385ca00 100644 --- a/lib/content-services/src/lib/i18n/ja.json +++ b/lib/content-services/src/lib/i18n/ja.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "適用", + "CANCEL": "キャンセル" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "復元", diff --git a/lib/content-services/src/lib/i18n/nb.json b/lib/content-services/src/lib/i18n/nb.json index 80f5462ab4c..735c935bd29 100644 --- a/lib/content-services/src/lib/i18n/nb.json +++ b/lib/content-services/src/lib/i18n/nb.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "Bruk", + "CANCEL": "Avbryt" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "Gjenopprett", diff --git a/lib/content-services/src/lib/i18n/nl.json b/lib/content-services/src/lib/i18n/nl.json index 876d230814a..f8cf5c54e68 100644 --- a/lib/content-services/src/lib/i18n/nl.json +++ b/lib/content-services/src/lib/i18n/nl.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "Toepassen", + "CANCEL": "Annuleren" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "Herstellen", diff --git a/lib/content-services/src/lib/i18n/pl.json b/lib/content-services/src/lib/i18n/pl.json index c67ae3e13f6..5aec1dfff77 100644 --- a/lib/content-services/src/lib/i18n/pl.json +++ b/lib/content-services/src/lib/i18n/pl.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "Zastosuj", + "CANCEL": "Anuluj" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "Przywróć", diff --git a/lib/content-services/src/lib/i18n/pt-BR.json b/lib/content-services/src/lib/i18n/pt-BR.json index 0cf8770fd82..0662bec46fe 100644 --- a/lib/content-services/src/lib/i18n/pt-BR.json +++ b/lib/content-services/src/lib/i18n/pt-BR.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "Aplicar", + "CANCEL": "Cancelar" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "Restaurar", diff --git a/lib/content-services/src/lib/i18n/ru.json b/lib/content-services/src/lib/i18n/ru.json index ce09e0c6a26..06a28b2bc49 100644 --- a/lib/content-services/src/lib/i18n/ru.json +++ b/lib/content-services/src/lib/i18n/ru.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "Применить", + "CANCEL": "Отмена" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "Восстановить", diff --git a/lib/content-services/src/lib/i18n/sv.json b/lib/content-services/src/lib/i18n/sv.json index 94aa283dd0d..6c4958c008b 100644 --- a/lib/content-services/src/lib/i18n/sv.json +++ b/lib/content-services/src/lib/i18n/sv.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "Tillämpa", + "CANCEL": "Avbryt" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "Återställ", diff --git a/lib/content-services/src/lib/i18n/zh-CN.json b/lib/content-services/src/lib/i18n/zh-CN.json index 4ceb79981f0..fba99c2a068 100644 --- a/lib/content-services/src/lib/i18n/zh-CN.json +++ b/lib/content-services/src/lib/i18n/zh-CN.json @@ -1,4 +1,8 @@ { + "COMMON": { + "APPLY": "应用", + "CANCEL": "取消" + }, "ADF_VERSION_LIST": { "ACTIONS": { "RESTORE": "恢复",