diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.ts b/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.ts index 57fbea2eab..6210dbb838 100644 --- a/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.ts +++ b/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, ViewEncapsulation } from '@angular/core'; +import { Component, Input, OnChanges, SimpleChanges, ViewEncapsulation } from '@angular/core'; import { Node } from '@alfresco/js-api'; import { NodeAspectService } from '../../../aspect-list/services/node-aspect.service'; import { ContentMetadataCustomPanel, PresetConfig } from '../../interfaces/content-metadata.interfaces'; @@ -84,10 +84,6 @@ export class ContentMetadataCardComponent implements OnChanges { @Input() customPanels: ContentMetadataCustomPanel[]; - /** Emitted when content's editable state is changed. */ - @Output() - editableChange = new EventEmitter(); - private _displayDefaultProperties: boolean = true; /** diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.html b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.html index c3d7d306d0..5ce82dcf0e 100644 --- a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.html +++ b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.html @@ -18,7 +18,7 @@
diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.scss b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.scss index c477d9b755..0425d9035e 100644 --- a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.scss +++ b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.scss @@ -115,3 +115,8 @@ box-shadow: none; } } + +.adf-snackbar-message { + background-color: var(--adf-snackbar-message-background-color); + color: var(--adf-snackbar-message-color); +} diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts index c377c342f7..2a62e51646 100644 --- a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts +++ b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts @@ -432,53 +432,59 @@ describe('ContentMetadataComponent', () => { })); }); - describe('editable', () => { - it('should toggle general editable', () => { - const eventMock = new MouseEvent('click'); + describe('toggleEdit', () => { + let mockEvent: MouseEvent; + let mockGroup: CardViewGroup = { + editable: false, expanded: false, + title: '', + properties: [] + }; + beforeEach(() => { + mockEvent = new MouseEvent('click'); + component.editableGroup = mockGroup; + }); + + it('should toggle General Info editing mode', () => { component.editable = false; - component.toggleGeneralEdit(eventMock); - expect(component.editable).toBe(true); + component.toggleEdit(mockEvent, mockGroup, ButtonType.GeneralInfo); expect(component.editableTags).toBe(false); expect(component.editableCategories).toBe(false); + expect(component.editableGroup.editable).toBe(false); }); - it('should toggle tags editable', () => { - const eventMock = new MouseEvent('click'); + it('should toggle Tags editing mode', () => { component.editableTags = false; - component.toggleTagsEdit(eventMock); - expect(component.editableTags).toBe(true); + component.toggleEdit(mockEvent, mockGroup, ButtonType.Tags); + expect(component.tagsPanelState).toBe(component.editableTags); expect(component.tagNameControlVisible).toBe(true); - expect(component.tagsPanelState).toBe(true); - expect(component.editable).toBe(false); expect(component.editableCategories).toBe(false); + expect(component.editableGroup.editable).toBe(false); }); - it('should toggle categories editable', () => { - const eventMock = new MouseEvent('click'); + it('should toggle Categories editing mode', () => { component.editableCategories = false; - component.toggleCategoriesEdit(eventMock); - expect(component.editableCategories).toBe(true); + component.toggleEdit(mockEvent, mockGroup, ButtonType.Categories); + expect(component.categoriesPanelState).toBe(component.editableCategories); expect(component.categoryControlVisible).toBe(true); - expect(component.categoriesPanelState).toBe(true); - expect(component.editable).toBe(false); expect(component.editableTags).toBe(false); + expect(component.editableGroup.editable).toBe(false); }); - it('should toggle group editable', () => { - const eventMock = new MouseEvent('click'); - const group: CardViewGroup = { - editable: false, expanded: false, - title: '', - properties: [] - }; - component.editableGroup = null; - component.toggleEdit(eventMock, group); - expect(group.editable).toBe(true); - expect(group.expanded).toBe(true); - expect(component.editableGroup).toBe(group); + it('should toggle Group editing mode', () => { + component.toggleEdit(mockEvent, mockGroup, ButtonType.Group); expect(component.editable).toBe(false); - expect(component.editableTags).toBe(false); - expect(component.editableCategories).toBe(false); + expect(component.editableGroup).toBe(mockGroup.editable ? mockGroup : null); + if (mockGroup.editable) { + expect(mockGroup.expanded).toBe(true); + } + }); + + it('should show Snackbar when Editing Panel is Active', () => { + spyOn(component, 'isEditingPanel').and.returnValue(true); + spyOn(component, 'showSnackbar'); + component.toggleEdit(mockEvent, mockGroup, ButtonType.GeneralInfo); + expect(component.isEditingPanel).toHaveBeenCalled(); + expect(component.showSnackbar).toHaveBeenCalledWith('METADATA.BASIC.SNACKBAR_MESSAGE'); }); }); diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.ts b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.ts index 91421c4a05..0a2ed0d01b 100644 --- a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.ts +++ b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.ts @@ -47,6 +47,7 @@ import { CategoriesManagementMode } from '../../../category/categories-managemen import { MatExpansionPanel } from '@angular/material/expansion'; import { AllowableOperationsEnum, ContentService } from '../../../common'; import { ButtonType } from './button-type.enum'; +import { MatSnackBar } from '@angular/material/snack-bar'; const DEFAULT_SEPARATOR = ', '; @@ -176,7 +177,8 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy { private tagService: TagService, private categoryService: CategoryService, private cdr: ChangeDetectorRef, - private contentService: ContentService + private contentService: ContentService, + private snackBar: MatSnackBar ) { this.copyToClipboardAction = this.appConfig.get('content-metadata.copy-to-clipboard-action'); this.multiValueSeparator = this.appConfig.get('content-metadata.multi-value-pipe-separator') || DEFAULT_SEPARATOR; @@ -343,59 +345,79 @@ export class ContentMetadataComponent implements OnChanges, OnInit, OnDestroy { this.loadProperties(this.node); } - cancelEditChanges() { - this.revertChanges(); - this.loadProperties(this.node); + isEditingPanel(): boolean { + return ( + (this.editable && this.hasMetadataChanged) || + (this.editableTags && this.hasMetadataChanged ) || + (this.editableCategories && this.hasMetadataChanged) || + ((this.editableGroup && this.editableGroup.editable) && this.hasMetadataChanged) + ); } - toggleGeneralEdit(event: MouseEvent): void { - event.stopPropagation(); - this.editable = !this.editable; - this.editableChange.emit(this.editable); - this.cancelEditChanges(); - if (this.editable) { - this.panel.open(); - this.editableTags = false; - this.editableCategories = false; + showSnackbar(message: string): void { + this.snackBar.open(message, '', { + duration: 3000, + verticalPosition: 'bottom', + panelClass: ['adf-snackbar-message'] + }); + } + + toggleEdit(event: MouseEvent, group: CardViewGroup, buttonType: ButtonType): void { + if (this.isEditingPanel()) { + this.showSnackbar('METADATA.BASIC.SNACKBAR_MESSAGE'); + return; } - } - - toggleTagsEdit(event: MouseEvent): void { + event.stopPropagation(); - this.editableTags = !this.editableTags; - this.tagsPanelState = this.editableTags; - this.cancelEditChanges(); - this.tagNameControlVisible = true; - if (this.editableTags) { - this.editable = false; - this.editableCategories = false; + + switch (buttonType) { + case ButtonType.GeneralInfo: + this.editable = !this.editable; + this.panel.open(); + this.editableTags = false; + this.editableCategories = false; + this.editableGroup.editable = false; + break; + + case ButtonType.Tags: + this.editableTags = !this.editableTags; + this.tagsPanelState = this.editableTags; + this.tagNameControlVisible = true; + this.editableGroup.editable = false; + break; + + case ButtonType.Categories: + this.editableCategories = !this.editableCategories; + this.categoriesPanelState = this.editableCategories; + this.categoryControlVisible = true; + this.editableGroup.editable = false; + break; + + case ButtonType.Group: + if (this.editableGroup && this.editableGroup !== group) { + this.editableGroup.editable = false; + } + group.editable = !group.editable; + this.editableChange.emit(this.editable); + this.editableGroup = group.editable ? group : null; + if (group.editable) { + group.expanded = true; + } + break; + + default: + break; } - } - - toggleCategoriesEdit(event: MouseEvent): void { - event.stopPropagation(); - this.cancelEditChanges(); - this.editableCategories = !this.editableCategories; - this.categoriesPanelState = this.editableCategories; - this.categoryControlVisible = true; - if (this.editableCategories) { + + if (buttonType !== ButtonType.GeneralInfo) { this.editable = false; + } + + if (buttonType !== ButtonType.Tags) { this.editableTags = false; } - } - - toggleEdit(event: MouseEvent, group: CardViewGroup): void { - event.stopPropagation(); - if (this.editableGroup && this.editableGroup !== group) { - this.editableGroup.editable = false; - } - group.editable = !group.editable; - this.editableChange.emit(this.editable); - this.editableGroup = group.editable ? group : null; - if (group.editable) { - group.expanded = true; - this.editable = false; - this.editableTags = false; + + if (buttonType !== ButtonType.Categories) { this.editableCategories = false; } } diff --git a/lib/content-services/src/lib/i18n/en.json b/lib/content-services/src/lib/i18n/en.json index bb26077359..6345c76ce5 100644 --- a/lib/content-services/src/lib/i18n/en.json +++ b/lib/content-services/src/lib/i18n/en.json @@ -489,7 +489,8 @@ "ADD_TAG_TOOLTIP": "Add tag", "HEADER_TITLE": "General info", "NO_TAGS_ADDED": "There are currently no tags added", - "NO_ITEMS_MESSAGE": "There are currently no {{ groupTitle }} added" + "NO_ITEMS_MESSAGE": "There are currently no {{ groupTitle }} added", + "SNACKBAR_MESSAGE": "Save or discard changes to continue" }, "CONTENT_TYPE": { "DIALOG" :{ diff --git a/lib/core/src/lib/styles/_components-variables.scss b/lib/core/src/lib/styles/_components-variables.scss index d6a0029e59..61bc6009f4 100644 --- a/lib/core/src/lib/styles/_components-variables.scss +++ b/lib/core/src/lib/styles/_components-variables.scss @@ -46,7 +46,9 @@ --adf-identity-user-info-font-size: var(--theme-adf-picture-1-font-size), --adf-user-info-container-margin-right: $adf-ref-margin-right, --adf-metadata-property-panel-border-color: $adf-metadata-property-panel-border-color, - --adf-metadata-buttons-background-color: $adf-metadata-buttons-background-color + --adf-metadata-buttons-background-color: $adf-metadata-buttons-background-color, + --adf-snackbar-message-background-color: $adf-snackbar-message-background-color, + --adf-snackbar-message-color: $adf-snackbar-message-color ); // propagates SCSS variables into the CSS variables scope diff --git a/lib/core/src/lib/styles/_reference-variables.scss b/lib/core/src/lib/styles/_reference-variables.scss index e17cc25b5e..8b6a782016 100644 --- a/lib/core/src/lib/styles/_reference-variables.scss +++ b/lib/core/src/lib/styles/_reference-variables.scss @@ -29,3 +29,5 @@ $adf-ref-line-height: 40px; $adf-ref-margin-right: 8px; $adf-metadata-property-panel-border-color: rgba(0, 0, 0, 0.12); $adf-metadata-buttons-background-color: rgba(33, 33, 33, 0.05); +$adf-snackbar-message-background-color: #ba1b1b; +$adf-snackbar-message-color: #f8f8f8