[ADF-4755][CardViewDate&SelectItemComponent] Provide a way to reset date and none option as default. (#4955)

* [ADF-4755] [CardViewDateItemComponent] Provide a way to reset date.

* Added clear icon to reset date to empty.
* Added Translation key to the new icon.

* * Added displayClearAction flag to toggle clear action.* Added None as default for the selectItem components.* Added displayNoneOption flag to toggle the default none option.

* * Fixed comments.

* * Added translation key for 'none'  option.

* * Updated dateItem css to the match recent changes.

* * Fixed failing unit tests* Updated TaskHeader components with the displayClearAction.

* * Updated demo shell card-view component to test the latest changes
This commit is contained in:
siva kumar 2019-07-26 16:52:45 +05:30 committed by Maurizio Vitale
parent 525f0a06db
commit 05e73a8aa1
18 changed files with 161 additions and 8 deletions

View File

@ -4,7 +4,9 @@
<mat-card class="adf-card-view"> <mat-card class="adf-card-view">
<adf-card-view <adf-card-view
[properties]="properties" [properties]="properties"
[editable]="true"> [editable]="true"
[displayClearAction]="showClearDateAction"
[displayNoneOption]="showNoneOption">
</adf-card-view> </adf-card-view>
</mat-card> </mat-card>
@ -22,6 +24,20 @@
(change)="toggleEditable()" (change)="toggleEditable()"
[checked]="isEditable"> [checked]="isEditable">
Editable Editable
</mat-slide-toggle><br>
<mat-slide-toggle
id="adf-toggle-clear-date"
[color]="'primary'"
(change)="toggleClearDate()"
[checked]="showClearDateAction">
Show clear date icon
</mat-slide-toggle><br>
<mat-slide-toggle
id="adf-toggle-none-option"
[color]="'primary'"
(change)="toggleNoneOption()"
[checked]="showNoneOption">
Show none option
</mat-slide-toggle> </mat-slide-toggle>
</p> </p>

View File

@ -44,6 +44,8 @@ export class CardViewComponent implements OnInit, OnDestroy {
isEditable = true; isEditable = true;
properties: any; properties: any;
logs: string[]; logs: string[];
showClearDateAction = false;
showNoneOption = false;
private onDestroy$ = new Subject<boolean>(); private onDestroy$ = new Subject<boolean>();
@ -166,6 +168,14 @@ export class CardViewComponent implements OnInit, OnDestroy {
this.createCard(); this.createCard();
} }
toggleClearDate() {
this.showClearDateAction = !this.showClearDateAction;
}
toggleNoneOption() {
this.showNoneOption = !this.showNoneOption;
}
reset() { reset() {
this.isEditable = true; this.isEditable = true;
this.createCard(); this.createCard();

View File

@ -97,7 +97,9 @@ Defining properties from Typescript:
| Name | Type | Default value | Description | | Name | Type | Default value | Description |
| ---- | ---- | ------------- | ----------- | | ---- | ---- | ------------- | ----------- |
| displayClearAction | `boolean` | true | Toggles whether or not to display clear action. |
| displayEmpty | `boolean` | true | Toggles whether or not to show empty items in non-editable mode. | | displayEmpty | `boolean` | true | Toggles whether or not to show empty items in non-editable mode. |
| displayNoneOption | `boolean` | true | Toggles whether or not to display none option. |
| editable | `boolean` | | Toggles whether or not the items can be edited. | | editable | `boolean` | | Toggles whether or not the items can be edited. |
| properties | [`CardViewItem`](../../../lib/core/card-view/interfaces/card-view-item.interface.ts)`[]` | | (**required**) Items to show in the card view. | | properties | [`CardViewItem`](../../../lib/core/card-view/interfaces/card-view-item.interface.ts)`[]` | | (**required**) Items to show in the card view. |

View File

@ -13,6 +13,15 @@
(click)="showDatePicker()"> (click)="showDatePicker()">
<span [attr.data-automation-id]="'card-' + property.type + '-value-' + property.key" *ngIf="showProperty(); else elseEmptyValueBlock">{{ property.displayValue }}</span> <span [attr.data-automation-id]="'card-' + property.type + '-value-' + property.key" *ngIf="showProperty(); else elseEmptyValueBlock">{{ property.displayValue }}</span>
</span> </span>
<mat-icon *ngIf="showClearAction()"
class="adf-date-reset-icon"
(click)="onDateClear()"
[attr.title]="'CORE.METADATA.ACTIONS.CLEAR' | translate"
[attr.data-automation-id]="'datepicker-date-clear-' + property.key">
clear
</mat-icon>
<mat-datetimepicker-toggle <mat-datetimepicker-toggle
[attr.title]="'CORE.METADATA.ACTIONS.EDIT' | translate" [attr.title]="'CORE.METADATA.ACTIONS.EDIT' | translate"
[attr.data-automation-id]="'datepickertoggle-' + property.key" [attr.data-automation-id]="'datepickertoggle-' + property.key"

View File

@ -35,6 +35,24 @@
&:hover mat-icon { &:hover mat-icon {
opacity: 1; opacity: 1;
} }
.adf-datepicker-toggle {
flex: 1 0 auto;
}
mat-icon.adf-date-reset-icon {
line-height: 10px;
font-size: 16px;
width: 16px;
height: 16px;
position: relative;
top: 4px;
padding-left: 8px;
opacity: 0.3;
}
&:hover mat-icon.adf-date-reset-icon {
opacity: 1;
}
} }
} }
} }

View File

@ -116,6 +116,7 @@ describe('CardViewDateItemComponent', () => {
}); });
it('should render value when editable:true', () => { it('should render value when editable:true', () => {
component.displayClearAction = false;
component.editable = true; component.editable = true;
component.property.editable = true; component.property.editable = true;
fixture.detectChanges(); fixture.detectChanges();
@ -203,4 +204,50 @@ describe('CardViewDateItemComponent', () => {
} }
); );
})); }));
it('should render the clear icon in case of editable:true', () => {
component.editable = true;
component.property.editable = true;
component.property.value = 'Jul 10 2017';
fixture.detectChanges();
const datePickerClearToggle = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-date-clear-${component.property.key}"]`));
expect(datePickerClearToggle).not.toBeNull('Clean Icon should be in DOM');
});
it('should not render the clear icon in case of property value empty', () => {
component.editable = true;
component.property.editable = true;
component.property.value = null;
fixture.detectChanges();
const datePickerClearToggle = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-date-clear--${component.property.key}"]`));
expect(datePickerClearToggle).toBeNull('Clean Icon should not be in DOM');
});
it('should not render the clear icon in case displayClearAction is set false', () => {
component.editable = true;
component.property.editable = true;
component.displayClearAction = false;
component.property.value = 'Jul 10 2017';
fixture.detectChanges();
const datePickerClearToggle = fixture.debugElement.query(By.css(`[data-automation-id="datepicker-date-clear--${component.property.key}"]`));
expect(datePickerClearToggle).toBeNull('Clean Icon should not be in DOM');
});
it('should remove the property value after a successful clear attempt', async(() => {
component.editable = true;
component.property.editable = true;
component.property.value = 'Jul 10 2017';
fixture.detectChanges();
component.onDateClear();
fixture.whenStable().then(
(updateNotification) => {
expect(component.property.value).toBeNull();
}
);
}));
}); });

View File

@ -52,6 +52,9 @@ export class CardViewDateItemComponent implements OnInit, OnDestroy {
@Input() @Input()
displayEmpty: boolean = true; displayEmpty: boolean = true;
@Input()
displayClearAction: boolean = true;
@ViewChild('datetimePicker') @ViewChild('datetimePicker')
public datepicker: MatDatetimepicker<any>; public datepicker: MatDatetimepicker<any>;
@ -92,6 +95,10 @@ export class CardViewDateItemComponent implements OnInit, OnDestroy {
return this.displayEmpty || !this.property.isEmpty(); return this.displayEmpty || !this.property.isEmpty();
} }
showClearAction() {
return !this.property.isEmpty() && this.displayClearAction;
}
isEditable() { isEditable() {
return this.editable && this.property.editable; return this.editable && this.property.editable;
} }
@ -111,4 +118,10 @@ export class CardViewDateItemComponent implements OnInit, OnDestroy {
} }
} }
onDateClear() {
this.valueDate = null;
this.cardViewUpdateService.update(this.property, null);
this.property.value = null;
}
} }

View File

@ -119,13 +119,17 @@ describe('CardViewItemDispatcherComponent', () => {
const expectedEditable = false, const expectedEditable = false,
expectedDisplayEmpty = true, expectedDisplayEmpty = true,
expectedProperty = <CardViewItem> {}, expectedProperty = <CardViewItem> {},
expectedCustomInput = 1; expectedCustomInput = 1,
expectedDisplayNoneOption = false,
expectedDisplayClearAction = false;
component.ngOnChanges({ component.ngOnChanges({
editable: new SimpleChange(true, expectedEditable, false), editable: new SimpleChange(true, expectedEditable, false),
displayEmpty: new SimpleChange(false, expectedDisplayEmpty, false), displayEmpty: new SimpleChange(false, expectedDisplayEmpty, false),
property: new SimpleChange(null, expectedProperty, false), property: new SimpleChange(null, expectedProperty, false),
customInput: new SimpleChange(0, expectedCustomInput, false) customInput: new SimpleChange(0, expectedCustomInput, false),
displayNoneOption: new SimpleChange(true, expectedDisplayNoneOption, false),
displayClearAction: new SimpleChange(true, expectedDisplayClearAction, false)
}); });
const shinyCustomElementItemComponent = fixture.debugElement.query(By.css('whatever-you-want-to-have')).componentInstance; const shinyCustomElementItemComponent = fixture.debugElement.query(By.css('whatever-you-want-to-have')).componentInstance;
@ -133,6 +137,8 @@ describe('CardViewItemDispatcherComponent', () => {
expect(shinyCustomElementItemComponent.editable).toBe(expectedEditable); expect(shinyCustomElementItemComponent.editable).toBe(expectedEditable);
expect(shinyCustomElementItemComponent.displayEmpty).toBe(expectedDisplayEmpty); expect(shinyCustomElementItemComponent.displayEmpty).toBe(expectedDisplayEmpty);
expect(shinyCustomElementItemComponent.customInput).toBe(expectedCustomInput); expect(shinyCustomElementItemComponent.customInput).toBe(expectedCustomInput);
expect(shinyCustomElementItemComponent.displayNoneOption).toBe(expectedDisplayNoneOption);
expect(shinyCustomElementItemComponent.displayClearAction).toBe(expectedDisplayClearAction);
}); });
}); });

View File

@ -42,6 +42,12 @@ export class CardViewItemDispatcherComponent implements OnChanges {
@Input() @Input()
displayEmpty: boolean = true; displayEmpty: boolean = true;
@Input()
displayNoneOption: boolean = true;
@Input()
displayClearAction: boolean = true;
@ViewChild(CardViewContentProxyDirective) @ViewChild(CardViewContentProxyDirective)
private content: CardViewContentProxyDirective; private content: CardViewContentProxyDirective;
@ -92,6 +98,8 @@ export class CardViewItemDispatcherComponent implements OnChanges {
this.componentReference.instance.editable = this.editable; this.componentReference.instance.editable = this.editable;
this.componentReference.instance.property = this.property; this.componentReference.instance.property = this.property;
this.componentReference.instance.displayEmpty = this.displayEmpty; this.componentReference.instance.displayEmpty = this.displayEmpty;
this.componentReference.instance.displayNoneOption = this.displayNoneOption;
this.componentReference.instance.displayClearAction = this.displayClearAction;
} }
private proxy(methodName, ...args) { private proxy(methodName, ...args) {

View File

@ -4,6 +4,7 @@
<div *ngIf="isEditable()"> <div *ngIf="isEditable()">
<mat-form-field> <mat-form-field>
<mat-select [(value)]="value" (selectionChange)="onChange($event)" data-automation-class="select-box"> <mat-select [(value)]="value" (selectionChange)="onChange($event)" data-automation-class="select-box">
<mat-option *ngIf="showNoneOption()">{{ 'CORE.CARDVIEW.NONE' | translate }}</mat-option>
<mat-option *ngFor="let option of getOptions() | async" [value]="option.key"> <mat-option *ngFor="let option of getOptions() | async" [value]="option.key">
{{ option.label | translate }} {{ option.label | translate }}
</mat-option> </mat-option>

View File

@ -34,6 +34,9 @@ export class CardViewSelectItemComponent implements OnChanges {
@Input() options$: Observable<CardViewSelectItemOption<string>[]>; @Input() options$: Observable<CardViewSelectItemOption<string>[]>;
@Input()
displayNoneOption: boolean = true;
value: string; value: string;
constructor(private cardViewUpdateService: CardViewUpdateService) {} constructor(private cardViewUpdateService: CardViewUpdateService) {}
@ -51,7 +54,12 @@ export class CardViewSelectItemComponent implements OnChanges {
} }
onChange(event: MatSelectChange): void { onChange(event: MatSelectChange): void {
this.cardViewUpdateService.update(this.property, event.value); const selectedOption = event.value !== undefined ? event.value : null;
this.property.value = event.value; this.cardViewUpdateService.update(this.property, selectedOption);
this.property.value = selectedOption;
}
showNoneOption() {
return this.displayNoneOption;
} }
} }

View File

@ -4,7 +4,9 @@
<adf-card-view-item-dispatcher <adf-card-view-item-dispatcher
[property]="property" [property]="property"
[editable]="editable" [editable]="editable"
[displayEmpty]="displayEmpty"> [displayEmpty]="displayEmpty"
[displayNoneOption]="displayNoneOption"
[displayClearAction]="displayClearAction">
</adf-card-view-item-dispatcher> </adf-card-view-item-dispatcher>
</div> </div>
</div> </div>

View File

@ -35,4 +35,12 @@ export class CardViewComponent {
/** Toggles whether or not to show empty items in non-editable mode. */ /** Toggles whether or not to show empty items in non-editable mode. */
@Input() @Input()
displayEmpty: boolean = true; displayEmpty: boolean = true;
/** Toggles whether or not to display none option. */
@Input()
displayNoneOption: boolean = true;
/** Toggles whether or not to display clear action. */
@Input()
displayClearAction: boolean = true;
} }

View File

@ -161,6 +161,7 @@
"NAME": "Name", "NAME": "Name",
"VALUE": "Value" "VALUE": "Value"
}, },
"NONE": "None",
"VALIDATORS": { "VALIDATORS": {
"FLOAT_VALIDATION_ERROR": "Use a number format", "FLOAT_VALIDATION_ERROR": "Use a number format",
"INT_VALIDATION_ERROR": "Use an integer format" "INT_VALIDATION_ERROR": "Use an integer format"
@ -184,6 +185,7 @@
"EDIT": "Edit", "EDIT": "Edit",
"SAVE": "Save", "SAVE": "Save",
"CANCEL": "Cancel", "CANCEL": "Cancel",
"CLEAR": "Clear",
"TOGGLE": "Toggle value" "TOGGLE": "Toggle value"
} }
} }

View File

@ -5,7 +5,8 @@
<mat-card-content> <mat-card-content>
<adf-card-view <adf-card-view
[properties]="properties" [properties]="properties"
[editable]="isTaskEditable()"> [editable]="isTaskEditable()"
[displayClearAction]="displayDateClearAction">
</adf-card-view> </adf-card-view>
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>

View File

@ -62,6 +62,7 @@ export class TaskHeaderCloudComponent implements OnInit, OnDestroy {
parentTaskName: string; parentTaskName: string;
dateFormat: string; dateFormat: string;
dateLocale: string; dateLocale: string;
displayDateClearAction = false;
private onDestroy$ = new Subject<boolean>(); private onDestroy$ = new Subject<boolean>();

View File

@ -1,6 +1,6 @@
<mat-card *ngIf="taskDetails" class="adf-card-container"> <mat-card *ngIf="taskDetails" class="adf-card-container">
<mat-card-content> <mat-card-content>
<adf-card-view [properties]="properties" [editable]="!isCompleted()"></adf-card-view> <adf-card-view [properties]="properties" [editable]="!isCompleted()" [displayClearAction]="displayDateClearAction"></adf-card-view>
</mat-card-content> </mat-card-content>
<mat-card-actions class="adf-controls"> <mat-card-actions class="adf-controls">

View File

@ -58,6 +58,7 @@ export class TaskHeaderComponent implements OnChanges, OnInit {
properties: CardViewItem []; properties: CardViewItem [];
inEdit: boolean = false; inEdit: boolean = false;
displayDateClearAction = false;
dateFormat: string; dateFormat: string;
dateLocale: string; dateLocale: string;