[ACS-5551] property panel design

This commit is contained in:
Anukriti Singh
2023-10-13 16:29:16 +05:30
parent cb6462bd59
commit 4500e25062
20 changed files with 177 additions and 107 deletions
@@ -141,13 +141,6 @@ describe('Metadata component', () => {
await expect(await viewerPage.getActiveTab()).toEqual(METADATA.PROPERTY_TAB);
await metadataViewPage.clickEditIconGeneral();
await metadataViewPage.editPropertyIconIsDisplayed('properties.cm:name');
await metadataViewPage.editPropertyIconIsDisplayed('properties.cm:title');
await metadataViewPage.editPropertyIconIsDisplayed('properties.cm:description');
await expect(await metadataViewPage.getPropertyIconTooltip('properties.cm:name')).toEqual('Edit');
await expect(await metadataViewPage.getPropertyIconTooltip('properties.cm:title')).toEqual('Edit');
await expect(await metadataViewPage.getPropertyIconTooltip('properties.cm:description')).toEqual('Edit');
await metadataViewPage.enterPropertyText('properties.cm:name', 'exampleText');
await metadataViewPage.clickResetMetadata();
-5
View File
@@ -167,11 +167,6 @@ export class MetadataViewPage {
return BrowserActions.getInputValue(textField);
}
async getPropertyIconTooltip(propertyName: string): Promise<string> {
const editPropertyIcon = $('[data-automation-id="header-' + propertyName + '"] .adf-textitem-edit-icon');
return BrowserActions.getAttribute(editPropertyIcon, 'title');
}
async clickMetadataGroup(groupName: string): Promise<void> {
const group = await this.getMetadataGroupLocator(groupName);
await BrowserActions.click(group);
@@ -25,6 +25,15 @@
.mat-expansion-panel:not([class*='mat-elevation-z']) {
box-shadow: none;
border: 1px solid var(--adf-metadata-property-panel-border-color);
border-radius: 12px;
margin: 24px;
}
.mat-expansion-panel-body {
align-items: center;
justify-content: center;
font-size: 15px;
}
.adf-mat-divider {
@@ -69,7 +78,7 @@
justify-content: space-between;
align-items: center;
font-size: 15px;
height: 68px;
height: 56px;
}
adf-tags-creator {
@@ -107,7 +116,7 @@
justify-content: space-between;
align-items: center;
font-size: 15px;
height: 64px;
height: 56px;
button {
margin-right: -14px;
@@ -45,6 +45,7 @@ import { CardViewKeyValuePairsItemComponent } from './components/card-view-keyva
import { CardViewSelectItemComponent } from './components/card-view-selectitem/card-view-selectitem.component';
import { CardViewArrayItemComponent } from './components/card-view-arrayitem/card-view-arrayitem.component';
import { SelectFilterInputComponent } from './components/card-view-selectitem/select-filter-input/select-filter-input.component';
import { MatDividerModule } from '@angular/material/divider';
@NgModule({
imports: [
@@ -66,7 +67,8 @@ import { SelectFilterInputComponent } from './components/card-view-selectitem/se
MatDatetimepickerModule,
MatNativeDatetimeModule,
MatSlideToggleModule,
MatTooltipModule
MatTooltipModule,
MatDividerModule
],
declarations: [
CardViewComponent,
@@ -1,10 +1,12 @@
<label class="adf-property-label"
[attr.data-automation-id]="'card-dateitem-label-' + property.key"
[ngClass]="{'adf-property-label-not-editable' : !isEditable() && editable}"
*ngIf="showProperty() || isEditable()"
[attr.for]="'card-view-dateitem-' + property.key">
{{ property.label | translate }}
</label>
<div class="adf-property-value adf-property-value-padding-top">
<div class="adf-property-value adf-property-value-padding-top"
[ngClass]="{'adf-property-dateitem-edit-mode' : editable, 'adf-property-label-not-editable' : !isEditable() && editable}">
<span *ngIf="!isEditable() && !property.multivalued"
[attr.data-automation-id]="'card-' + property.type + '-value-' + property.key">
<span *ngIf="showProperty()"
@@ -98,3 +100,4 @@
</mat-form-field>
</div>
</div>
<mat-divider *ngIf="showProperty() && !editable"></mat-divider>
@@ -11,6 +11,23 @@
float: right;
}
&-property-label{
color: var(--theme-metadata-property-panel-text-color);
display: flex;
padding: 6px 0;
line-height: 20px;
}
&-property-dateitem-edit-mode{
background-color: var(--theme-metadata-buttons-background-color);
border-radius: 6px;
padding-left: 12px;
.mat-select-value{
color: var(--theme-metadata-property-panel-text-color);
}
}
&-dateitem-chip-list-container.adf-property-field {
margin-bottom: -7px !important;
border-bottom: 0;
@@ -2,6 +2,7 @@
<div
[attr.data-automation-id]="'card-select-label-' + property.key"
class="adf-property-label"
[ngClass]="{'adf-property-label-not-editable' : !isEditable() && editable}"
>{{ property.label | translate }}</div>
<div class="adf-property-field">
<div
@@ -15,6 +16,7 @@
<mat-select
[(value)]="value"
panelClass="adf-select-filter"
[ngClass]="{'adf-property-select-edit-mode' : isEditable(),'adf-property-normal-mode':!isEditable(),'adf-property-label-not-editable' : !isEditable() && editable}"
(selectionChange)="onChange($event)"
data-automation-class="select-box"
[aria-label]="property.label | translate"
@@ -2,14 +2,8 @@
width: 100%;
}
.adf-select-item-padding {
padding-top: 6px;
padding-bottom: 20px;
}
.adf-select-item-padding-editable {
padding-top: 6px;
padding-bottom: 6px;
padding: 6px 0;
}
.adf-select-filter-input {
@@ -2,14 +2,16 @@
<div *ngSwitchDefault>
<mat-form-field class="adf-property-field adf-card-textitem-field"
[ngClass]="{ 'adf-property-read-only': !isEditable, 'adf-property-field-has-error mat-form-field-invalid': isEditable && hasErrors }"
[floatLabel]="'never'"
[floatLabel]="'always'"
appearance="standard">
<mat-label *ngIf="showProperty || isEditable" [attr.data-automation-id]="'card-textitem-label-' + property.key" class="adf-property-label">
<mat-label *ngIf="showProperty || isEditable" [attr.data-automation-id]="'card-textitem-label-' + property.key" class="adf-property-label"
[ngClass]="{'adf-property-label-not-editable' : !isEditable && editable}">
{{ property.label | translate }}
</mat-label>
<input matInput
*ngIf="!property.multiline"
class="adf-property-value"
[ngClass]="{'adf-property-edit-mode' : editable,'adf-property-normal-mode':!editable, 'adf-property-label-not-editable' : !isEditable && editable}"
title="{{property.label | translate }}"
[placeholder]="property.default"
[attr.aria-label]="property.label | translate"
@@ -27,34 +29,21 @@
[cdkAutosizeMaxRows]="1"
[cdkAutosizeMaxRows]="5"
class="adf-property-value"
[ngClass]="{'adf-property-edit-mode' : editable,'adf-property-normal-mode':!editable, 'adf-property-label-not-editable' : !isEditable && editable}"
[placeholder]="property.default"
[attr.aria-label]="property.label | translate"
[formControl]="textInput"
[attr.data-automation-id]="'card-textitem-value-' + property.key">
</textarea>
<button
*ngIf="isEditable"
matSuffix
class="adf-textitem-clear-icon"
[attr.aria-label]="'CORE.METADATA.ACTIONS.CLEAR' | translate"
(click)="clearValue()">
<mat-icon>cancel</mat-icon>
</button>
<button
*ngIf="isEditable"
matSuffix
class="adf-textitem-edit-icon"
[attr.title]="'CORE.METADATA.ACTIONS.EDIT' | translate">
<mat-icon>mode_edit</mat-icon>
</button>
</mat-form-field>
<mat-divider *ngIf="showProperty && !editable"></mat-divider>
</div>
<div *ngSwitchCase="'chipsTemplate'"
class="adf-property-field adf-textitem-chip-list-container">
<mat-label *ngIf="showLabelForChips" [attr.data-automation-id]="'card-textitem-label-' + property.key" class="adf-property-label">
<mat-label *ngIf="showLabelForChips" [attr.data-automation-id]="'card-textitem-label-' + property.key" class="adf-property-label"
[ngClass]="{'adf-property-label-not-editable' : !isEditable && editable}">
{{ property.label | translate }}
</mat-label>
<mat-chip-list #chipList
@@ -74,6 +63,7 @@
[floatLabel]="'never'">
<input matInput
class="adf-property-value"
[ngClass]="{'adf-property-edit-mode' : editable,'adf-property-normal-mode':!editable, 'adf-property-label-not-editable' : !isEditable && editable}"
title="{{property.label | translate }}"
[placeholder]="editedValue ? '' : property.default | translate"
[attr.aria-label]="property.label | translate"
@@ -81,9 +71,8 @@
[matChipInputAddOnBlur]="true"
(matChipInputTokenEnd)="addValueToList($event)"
[attr.data-automation-id]="'card-textitem-editchipinput-' + property.key">
<mat-icon matSuffix
class="adf-textitem-edit-icon">mode_edit</mat-icon>
</mat-form-field>
<mat-divider *ngIf="showProperty && !editable"></mat-divider>
</div>
<div *ngSwitchCase="'clickableTemplate'"
@@ -94,14 +83,15 @@
(click)="clicked()">
<mat-form-field class="adf-property-field adf-card-textitem-field" appearance="standard"
[floatLabel]="'never'">
<mat-label *ngIf="showProperty || isEditable" [attr.data-automation-id]="'card-textitem-label-' + property.key" class="adf-property-label">
<mat-label *ngIf="showProperty || isEditable" [attr.data-automation-id]="'card-textitem-label-' + property.key" class="adf-property-label"
[ngClass]="{'adf-property-label-not-editable' : !isEditable && editable}">
{{ property.label | translate }}
</mat-label>
<input matInput
[type]=property.inputType
class="adf-property-value"
title="{{property.label | translate }}"
[ngClass]="{ 'adf-textitem-clickable-value': !isEditable }"
[ngClass]="{ 'adf-textitem-clickable-value': !isEditable,'adf-property-edit-mode' : editable,'adf-property-normal-mode':!editable, 'adf-property-label-not-editable' : !isEditable && editable }"
[placeholder]="property.default"
[attr.aria-label]="property.label | translate"
[(ngModel)]="editedValue"
@@ -1,4 +1,9 @@
.adf {
&-property-field .mat-form-field-underline {
display: none;
}
&-textitem-edit-icon.mat-icon {
font-size: var(--theme-subheading-2-font-size);
width: 16px;
@@ -185,24 +185,6 @@ describe('CardViewTextItemComponent', () => {
});
it('should render the edit icon in case of editable:true', () => {
component.editable = true;
component.property.editable = true;
fixture.detectChanges();
const editIcon = fixture.debugElement.query(By.css('.adf-textitem-edit-icon'));
expect(editIcon).not.toBeNull('Edit icon should be shown');
});
it('should NOT render the edit icon in case of editable:false', async () => {
component.editable = false;
fixture.detectChanges();
await fixture.whenStable();
const editIcon = fixture.debugElement.query(By.css('.adf-textitem-edit-icon'));
expect(editIcon).toBeNull('Edit icon should NOT be shown');
});
it('should NOT render the picker and toggle in case of editable:true but (general) editable:false', async () => {
component.editable = false;
component.property.editable = true;
@@ -492,27 +474,7 @@ describe('CardViewTextItemComponent', () => {
fixture.detectChanges();
expect(clipboardService.copyContentToClipboard).toHaveBeenCalledWith('myValueToCopy', 'CORE.METADATA.ACCESSIBILITY.COPY_TO_CLIPBOARD_MESSAGE');
});
it('should clear value when clear value icon is clicked', async () => {
spyOn(component, 'update');
component.property.value = 'testValue';
component.property.icon = 'FAKE_ICON';
component.property.clickable = true;
component.property.editable = true;
component.editable = true;
component.property.isValid = () => true;
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();
const clickEl = fixture.debugElement.query(By.css(`.adf-textitem-clear-icon`));
clickEl.triggerEventHandler('click', new MouseEvent('click'));
fixture.detectChanges();
const elementValue = fixture.debugElement.query(By.css(`[data-automation-id="card-textitem-value-${component.property.key}"]`));
expect(elementValue.nativeElement.textContent).toEqual('');
expect(component.update).toHaveBeenCalled();
});
});
describe('Update', () => {
@@ -6,23 +6,80 @@
border-radius: var(--adf-card-view-border-radius);
.adf-property {
margin-bottom: 20px;
.adf-property-value-padding-top {
margin-top: 6px;
display: flex;
flex-direction: column;
padding-bottom: 6px;
line-height: 20px;
}
.adf-property-label-not-editable {
color: var(--theme-metadata-property-panel-label-color) !important;
}
.adf-property-field {
width: 100%;
margin-bottom: -25px;
.mat-form-field-infix {
display: flex;
border-top-width: 0;
padding: 0;
}
.mat-form-field-label {
margin-top: 6px;
padding: 6px 0;
justify-content: center;
display: flex;
flex-direction: column;
height: 20px;
transform: translateY(-1.34373em) scale(1);
}
.mat-form-field-label-wrapper {
padding-top: 0;
top: -1px;
}
.mat-input-element.adf-property-normal-mode {
color: var(--theme-metadata-property-panel-title-color);
margin-top: 32px;
padding: 6px 0;
line-height: 20px;
}
.mat-input-element.adf-property-edit-mode {
padding: 6px 0 6px 12px;
margin-top: 32px;
line-height: 20px;
background-color: var(--theme-metadata-buttons-background-color);
color: var(--theme-metadata-property-panel-text-color);
border-radius: 6px;
}
.mat-select.adf-property-select-edit-mode {
padding: 6px 0 6px 12px;
margin-top: 0;
line-height: 20px;
background-color: var(--theme-metadata-buttons-background-color);
border-radius: 6px;
.mat-select-min-line{
color: var(--theme-metadata-property-panel-text-color);
}
}
}
}
}
.mat-form-field-wrapper {
padding-bottom: 0;
}
.mat-form-field-appearance-standard .mat-form-field-flex {
padding-top: 0 !important;
}
.mat-form-field-appearance-legacy .mat-form-field-wrapper {
padding-bottom: 0 !important;
}
+3
View File
@@ -569,5 +569,8 @@
"ADF_DROPDOWN": {
"LOADING": "Loading...",
"SELECTION_ARIA_LABEL": "{{placeholder}} combobox {{selectedOption}}"
},
"INFO_DRAWER": {
"ICON": "Node Icon"
}
}
@@ -1,4 +1,7 @@
<div *ngIf="showHeader" class="adf-info-drawer-layout-header">
<div class="adf-info-drawer-layout-header-icon">
<ng-content select="[info-drawer-node-icon]"></ng-content>
</div>
<div class="adf-info-drawer-layout-header-title">
<ng-content select="[info-drawer-title]"></ng-content>
</div>
@@ -14,7 +14,7 @@ $adf-info-drawer-icon-size-half: 24px !default;
overflow: auto;
width: 100%;
background-color: var(--theme-background-color);
background-color:var(--theme-card-background-color);
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.27);
& .mat-tab-label {
@@ -32,7 +32,6 @@ $adf-info-drawer-icon-size-half: 24px !default;
&-header {
padding: 13px 0 0 23px;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 40px;
@@ -55,8 +54,8 @@ $adf-info-drawer-icon-size-half: 24px !default;
& > div {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
color: var(--theme-metadata-property-panel-title-color);
}
}
}
@@ -33,6 +33,7 @@ export class InfoDrawerLayoutComponent {
/**
* Directive selectors without adf- prefix will be deprecated on 3.0.0
*/
@Directive({ selector: '[info-drawer-node-icon], [info-drawer-node-icon]' }) export class InfoDrawerNodeIconDirective {}
@Directive({ selector: '[adf-info-drawer-title], [info-drawer-title]' }) export class InfoDrawerTitleDirective {}
@Directive({ selector: '[adf-info-drawer-buttons], [info-drawer-buttons]' }) export class InfoDrawerButtonsDirective {}
@Directive({ selector: '[adf-info-drawer-content], [info-drawer-content]' }) export class InfoDrawerContentDirective {}
@@ -1,4 +1,6 @@
<adf-info-drawer-layout [showHeader]="showHeader">
<img class="adf-info-drawer-icon" *ngIf="nodeIcon" alt="{{ 'INFO_DRAWER.ICON' | translate }}" src="{{ nodeIcon }}" info-drawer-node-icon>
<div role="heading" aria-level="1" *ngIf="title" info-drawer-title>{{ title | translate }}</div>
<ng-content *ngIf="!title" info-drawer-title select="[info-drawer-title]"></ng-content>
@@ -1,12 +1,23 @@
.adf {
&-info-drawer {
display: block;
.adf-metadata-properties-panel{
display:block;
margin:0;
}
.mat-tab-label {
min-width: 0;
}
& &-layout {
.adf-info-drawer-icon{
display: inline-block;
vertical-align: middle;
margin-right: 10px;
}
&-content {
padding: 0;
@@ -42,7 +53,7 @@
}
.mat-tab-body {
padding: 10px;
overflow-y: hidden;
}
.mat-tab-body-content {
@@ -87,18 +87,19 @@ describe('InfoDrawerComponent', () => {
@Component({
template: `
<adf-info-drawer [selectedIndex]="tabIndex" title="Fake Title Custom">
<adf-info-drawer-tab label="Tab1">
</adf-info-drawer-tab>
<adf-info-drawer-tab label="Tab2">
</adf-info-drawer-tab>
<adf-info-drawer-tab label="Tab3" icon="tab-icon">
</adf-info-drawer-tab>
</adf-info-drawer>
`
<adf-info-drawer [selectedIndex]="tabIndex" nodeIcon="nodeIcon" title="Fake Title Custom">
<adf-info-drawer-tab label="Tab1">
</adf-info-drawer-tab>
<adf-info-drawer-tab label="Tab2">
</adf-info-drawer-tab>
<adf-info-drawer-tab label="Tab3" icon="tab-icon">
</adf-info-drawer-tab>
</adf-info-drawer>
`
})
class CustomInfoDrawerComponent extends InfoDrawerComponent {
tabIndex: number;
nodeIcon: string;
}
describe('Custom InfoDrawer', () => {
@@ -157,16 +158,26 @@ describe('Custom InfoDrawer', () => {
expect(tab[0].nativeElement.innerText).not.toBe('TAB3');
expect(tab[0].nativeElement.innerText).toContain('tab-icon');
});
it('should render a icon with title', () => {
component.nodeIcon = "/assets/images/ft_ic_miscellaneous.svg";
fixture.detectChanges();
const icon = fixture.debugElement.queryAll(By.css('[info-drawer-node-icon]'));
const srcAttribute = icon[0].nativeElement.getAttribute('src');
expect(icon.length).toBe(1);
expect(srcAttribute).toContain('/assets/images/ft_ic_miscellaneous.svg');
});
});
@Component({
template: `
<adf-info-drawer [showHeader]="showHeader" title="Fake Visibility Info Drawer Title">
<adf-info-drawer [showHeader]="showHeader" nodeIcon="nodeIcon" title="Fake Visibility Info Drawer Title">
</adf-info-drawer>
`
`
})
class VisibilityInfoDrawerComponent extends InfoDrawerComponent {
showHeader: boolean;
nodeIcon: string;
}
describe('Header visibility InfoDrawer', () => {
@@ -189,18 +200,24 @@ describe('Header visibility InfoDrawer', () => {
});
it('should show info drawer header by default', () => {
component.nodeIcon = "/assets/images/ft_ic_miscellaneous.svg";
fixture.detectChanges();
const title: any = fixture.debugElement.queryAll(By.css('[info-drawer-title]'));
const icon = fixture.debugElement.queryAll(By.css('[info-drawer-node-icon]'));
const srcAttribute = icon[0].nativeElement.getAttribute('src');
expect(title.length).toBe(1);
expect(icon.length).toBe(1);
expect(srcAttribute).toContain('/assets/images/ft_ic_miscellaneous.svg');
expect(title[0].nativeElement.innerText).toBe('Fake Visibility Info Drawer Title');
expect(component.showHeader).toEqual(true);
});
it('should not show info drawer header when showHeader is false', () => {
fixture.detectChanges();
it('should not show info drawer header with icon when showHeader is false', () => {
component.showHeader = false;
fixture.detectChanges();
const title: any = fixture.debugElement.queryAll(By.css('[info-drawer-title]'));
const icon = fixture.debugElement.queryAll(By.css('[info-drawer-node-icon]'));
expect(title.length).toBe(0);
expect(icon.length).toBe(0);
});
});
@@ -17,6 +17,7 @@
import { Component, ContentChildren, EventEmitter, HostListener, Input, Output, QueryList, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core';
import { MatTabChangeEvent } from '@angular/material/tabs';
@Component({
selector: 'adf-info-drawer-tab',
template: '<ng-template><ng-content></ng-content></ng-template>',
@@ -43,10 +44,14 @@ export class InfoDrawerTabComponent {
host: { class: 'adf-info-drawer' }
})
export class InfoDrawerComponent {
/** The title of the info drawer (string or translation key). */
@Input()
title: string|null = null;
@Input()
nodeIcon: string | null = null;
/** The selected index tab. */
@Input()
selectedIndex: number = 0;