Skip to content

Commit

Permalink
[MNT-24496] ADW Integration with APS Improvements - Re-assign Tasks (#…
Browse files Browse the repository at this point in the history
…10350)

* [MNT-24496] ADW Integration with APS Improvements - Re-assign Tasks

* [MNT-24496] code improvements

* [MNT-24496] remove duplications

* [MNT-24496] add unit test

* [MNT-24496] cr fixes

* [MNT-24496] empty commit [ci:force]

* [MNT-24496] fix unit test

* [MNT-24496] empty commit [ci:force]

* [MNT-24496] cr fix

* [MNT-24496] remove redundant import
  • Loading branch information
nikita-web-ua authored Nov 6, 2024
1 parent 558ff71 commit 258f018
Show file tree
Hide file tree
Showing 14 changed files with 434 additions and 94 deletions.
3 changes: 2 additions & 1 deletion docs/core/components/card-view.component.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Title: Card View component
Added: v2.0.0
Status: Active
Last reviewed: 2018-05-09
Last reviewed: 2024-10-29
---

# [Card View component](../../../lib/core/src/lib/card-view/components/card-view/card-view.component.ts "Defined in card-view.component.ts")
Expand Down Expand Up @@ -353,6 +353,7 @@ const selectItemProperty = new CardViewSelectItemModel(options);
| key\* | string | | Identifying key (important when editing the item) |
| editable | boolean | false | Toggles whether the item is editable |
| value | string | | The original data value for the item |
| autocompleteBased | boolean | false | Indicates whether the select item should use autocomplete functionality. If set to true, the select item will provide an autocomplete input field. |
| options$\* | [`Observable`](http://reactivex.io/documentation/observable.html)<[`CardViewSelectItemOption`](../../../lib/core/src/lib/card-view/interfaces/card-view-selectitem-properties.interface.ts)\[]> | | The original data value for the item |

#### Card Array Item
Expand Down
15 changes: 14 additions & 1 deletion docs/core/services/card-view-update.service.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Title: Card View Update service
Added: v2.0.0
Status: Active
Last reviewed: 2022-11-25
Last reviewed: 2024-10-29
---

# [Card View Update service](../../../lib/core/src/lib/card-view/services/card-view-update.service.ts "Defined in card-view-update.service.ts")
Expand Down Expand Up @@ -137,6 +137,19 @@ Example
this.cardViewUpdateService.updateElement(cardViewBaseItemModel)
```

## Autocomplete Input Value

The `autocompleteInputValue$` property is a Subject that emits the current value of the autocomplete input field. This can be used to track changes in the input field and respond accordingly.

### Example

You can subscribe to `autocompleteInputValue$` to get the current value of the autocomplete input field and update the options accordingly.

```ts
this.cardViewUpdateService.autocompleteInputValue$.subscribe(value => {
this.options$ = this.getOptions(value);
});
```
## See also

- [Card view component](../components/card-view.component.md)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,80 @@
<ng-container *ngIf="!property.isEmpty() || isEditable">
<div
[attr.data-automation-id]="'card-select-label-' + property.key"
class="adf-property-label"
[ngClass]="{
'adf-property-value-editable': isEditable,
'adf-property-readonly-value': isReadonlyProperty
}"
>{{ property.label | translate }}</div>
<div class="adf-property-field">
<div
*ngIf="!isEditable"
class="adf-property-value adf-property-read-only"
[attr.data-automation-id]="'select-readonly-value-' + property.key"
data-automation-class="read-only-value">{{ (property.displayValue | async) | translate }}
<div [ngSwitch]="templateType">
<div *ngSwitchDefault>
<div
[attr.data-automation-id]="'card-select-label-' + property.key"
class="adf-property-label"
[ngClass]="{
'adf-property-value-editable': isEditable,
'adf-property-readonly-value': isReadonlyProperty
}"
>{{ property.label | translate }}
</div>
<div class="adf-property-field">
<div
*ngIf="!isEditable"
class="adf-property-value adf-property-read-only"
[attr.data-automation-id]="'select-readonly-value-' + property.key"
data-automation-class="read-only-value">{{ (property.displayValue | async) | translate }}
</div>
<div *ngIf="isEditable">
<mat-form-field class="adf-property-value" [ngClass]="{'adf-property-value-editable': isEditable}">
<mat-select
[(value)]="value"
[ngClass]="{ 'adf-property-readonly-value': isReadonlyProperty }"
panelClass="adf-select-filter"
(selectionChange)="onChange($event)"
data-automation-class="select-box"
[aria-label]="property.label | translate">
<adf-select-filter-input *ngIf="showInputFilter" (change)="onFilterInputChange($event)"/>
<mat-option *ngIf="displayNoneOption">{{ 'CORE.CARDVIEW.NONE' | translate }}</mat-option>
<mat-option
*ngFor="let option of list$ | async"
[value]="option.key">
{{ option.label | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
<div *ngIf="isEditable">
<mat-form-field class="adf-property-value" [ngClass]="{'adf-property-value-editable': isEditable}">
<mat-select
[(value)]="value"
[ngClass]="{ 'adf-property-readonly-value': isReadonlyProperty }"
panelClass="adf-select-filter"
(selectionChange)="onChange($event)"
data-automation-class="select-box"
[aria-label]="property.label | translate">
<adf-select-filter-input *ngIf="showInputFilter" (change)="onFilterInputChange($event)" />
<mat-option *ngIf="displayNoneOption">{{ 'CORE.CARDVIEW.NONE' | translate }}</mat-option>
<mat-option
*ngFor="let option of list$ | async"
[value]="option.key">
{{ option.label | translate }}
<div *ngSwitchCase="'autocompleteBased'">
<mat-form-field
class="adf-property-field adf-card-selectitem-autocomplete"
[ngClass]="{ 'adf-property-read-only': !isEditable }"
[floatLabel]="'always'">
<mat-label
*ngIf="showProperty || isEditable"
[attr.data-automation-id]="'card-autocomplete-based-selectitem-label-' + property.key"
class="adf-property-label"
[ngClass]="{
'adf-property-value-editable': isEditable,
'adf-property-readonly-value': isReadonlyProperty
}">
{{ property.label | translate }}
</mat-label>
<input
matInput
[matAutocomplete]="auto"
class="adf-property-value"
[ngClass]="{
'adf-property-value-editable': isEditable,
'adf-property-readonly-value': isReadonlyProperty
}"
title="{{ property.label | translate }}"
[placeholder]="property.default"
[attr.aria-label]="property.label | translate"
[formControl]="autocompleteControl"
[title]="'CORE.METADATA.ACTIONS.COPY_TO_CLIPBOARD' | translate"
[attr.data-automation-id]="'card-autocomplete-based-selectitem-value-' + property.key"
/>
<mat-autocomplete autoActiveFirstOption #auto="matAutocomplete"
(optionSelected)="onOptionSelected($event)">
<mat-option *ngFor="let option of property.options$ | async" [value]="option.key"
[attr.data-automation-id]="'card-autocomplete-based-selectitem-option-' + property.key">
{{ option.label }}
</mat-option>
</mat-select>
</mat-autocomplete>
</mat-form-field>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
}
}

.adf-card-selectitem-autocomplete .adf-property-value-editable {
padding-left: 10px;
}

#{$mat-form-field-subscript-wrapper} {
display: none;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,17 @@ import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSelectHarness } from '@angular/material/select/testing';
import { MatFormFieldHarness } from '@angular/material/form-field/testing';
import { NoopTranslateModule } from '@alfresco/adf-core';
import { CardViewUpdateService, NoopTranslateModule } from '@alfresco/adf-core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
import { MatAutocompleteHarness } from '@angular/material/autocomplete/testing';

describe('CardViewSelectItemComponent', () => {
let loader: HarnessLoader;
let fixture: ComponentFixture<CardViewSelectItemComponent>;
let component: CardViewSelectItemComponent;
let appConfig: AppConfigService;
let cardViewUpdateService: CardViewUpdateService;
const mockData = [
{ key: 'one', label: 'One' },
{ key: 'two', label: 'Two' },
Expand Down Expand Up @@ -65,6 +68,7 @@ describe('CardViewSelectItemComponent', () => {
fixture = TestBed.createComponent(CardViewSelectItemComponent);
component = fixture.componentInstance;
appConfig = TestBed.inject(AppConfigService);
cardViewUpdateService = TestBed.inject(CardViewUpdateService);
component.property = new CardViewSelectItemModel(mockDefaultProps);
loader = TestbedHarnessEnvironment.loader(fixture);
});
Expand All @@ -91,7 +95,7 @@ describe('CardViewSelectItemComponent', () => {
editable: false
});

component.ngOnChanges();
component.ngOnChanges({});
fixture.detectChanges();

const readOnly = fixture.debugElement.query(By.css('[data-automation-class="read-only-value"]'));
Expand All @@ -108,7 +112,7 @@ describe('CardViewSelectItemComponent', () => {
});
component.editable = true;
component.displayNoneOption = true;
component.ngOnChanges();
component.ngOnChanges({});
fixture.detectChanges();

expect(component.value).toEqual('two');
Expand All @@ -131,7 +135,7 @@ describe('CardViewSelectItemComponent', () => {
});
component.editable = true;
component.displayNoneOption = true;
component.ngOnChanges();
component.ngOnChanges({});
fixture.detectChanges();

expect(component.value).toEqual(2);
Expand All @@ -155,7 +159,7 @@ describe('CardViewSelectItemComponent', () => {
});
component.editable = true;
component.displayNoneOption = true;
component.ngOnChanges();
component.ngOnChanges({});
fixture.detectChanges();

expect(component.isEditable).toBe(true);
Expand All @@ -168,15 +172,15 @@ describe('CardViewSelectItemComponent', () => {
});

it('should render select box if editable property is TRUE', async () => {
component.ngOnChanges();
component.ngOnChanges({});
component.editable = true;
fixture.detectChanges();

expect(await loader.hasHarness(MatSelectHarness)).toBe(true);
});

it('should not have label twice', async () => {
component.ngOnChanges();
component.ngOnChanges({});
component.editable = true;
fixture.detectChanges();

Expand All @@ -197,7 +201,7 @@ describe('CardViewSelectItemComponent', () => {
});
component.editable = true;
component.displayNoneOption = false;
component.ngOnChanges();
component.ngOnChanges({});
fixture.detectChanges();

const select = await loader.getHarness(MatSelectHarness);
Expand Down Expand Up @@ -225,7 +229,7 @@ describe('CardViewSelectItemComponent', () => {
});
component.editable = true;
component.displayNoneOption = false;
component.ngOnChanges();
component.ngOnChanges({});
fixture.detectChanges();

const select = await loader.getHarness(MatSelectHarness);
Expand All @@ -245,7 +249,7 @@ describe('CardViewSelectItemComponent', () => {
});
component.editable = true;
component.displayNoneOption = false;
component.ngOnChanges();
component.ngOnChanges({});
fixture.detectChanges();

const select = await loader.getHarness(MatSelectHarness);
Expand All @@ -255,4 +259,94 @@ describe('CardViewSelectItemComponent', () => {
expect(filterInput).not.toBe(null);
});
});

describe('Autocomplete based', () => {
beforeEach(() => {
component.property = new CardViewSelectItemModel({
label: 'Test Label',
value: 'initial value',
key: 'test-key',
default: 'Placeholder',
editable: true,
autocompleteBased: true,
options$: of([
{ key: '1', label: 'Option 1' },
{ key: '2', label: 'Option 2' }
])
});
});

it('should set templateType to autocompleteBased', () => {
component.property.autocompleteBased = true;
fixture.detectChanges();
expect(component.templateType).toBe('autocompleteBased');
});

it('should set initial value to autocompleteControl', () => {
component.ngOnChanges({});
fixture.detectChanges();

expect(component.autocompleteControl.value).toBe('initial value');
});

it('should emit autocompleteInputValue$ with new value on autocompleteControl change', async () => {
const autocompleteValueSpy = spyOn(cardViewUpdateService.autocompleteInputValue$, 'next');
component.editedValue = '';
component.editable = true;
component.ngOnChanges({ property: { firstChange: true } } as any);
fixture.detectChanges();

component.autocompleteControl.setValue('new value');
fixture.detectChanges();
await fixture.whenStable();

expect(autocompleteValueSpy).toHaveBeenCalledWith('new value');
});

it('should update value correctly on option selected', () => {
cardViewUpdateService.update = jasmine.createSpy('update');
const event: MatAutocompleteSelectedEvent = {
option: {
value: '1'
}
} as MatAutocompleteSelectedEvent;

component.ngOnChanges({});
fixture.detectChanges();

component.onOptionSelected(event);
fixture.detectChanges();

expect(component.autocompleteControl.value).toBe('Option 1');
expect(cardViewUpdateService.update).toHaveBeenCalledWith(jasmine.objectContaining(component.property), '1');
});

it('should disable the autocomplete control', () => {
component.editable = false;
component.ngOnChanges({ editable: { currentValue: false, previousValue: true, firstChange: false, isFirstChange: () => false } });
fixture.detectChanges();
expect(component.autocompleteControl.disabled).toBeTrue();
});

it('should enable the autocomplete control', () => {
component.editable = true;
component.ngOnChanges({ editable: { currentValue: true, previousValue: false, firstChange: false, isFirstChange: () => false } });
fixture.detectChanges();
expect(component.autocompleteControl.enabled).toBeTrue();
});

it('should populate options for autocomplete', async () => {
component.ngOnChanges({});
fixture.detectChanges();

const autocomplete = await loader.getHarness(MatAutocompleteHarness);
await autocomplete.enterText('Op');
fixture.detectChanges();

const options = await autocomplete.getOptions();
expect(options.length).toBe(2);
expect(await options[0].getText()).toContain('Option 1');
expect(await options[1].getText()).toContain('Option 2');
});
});
});
Loading

0 comments on commit 258f018

Please sign in to comment.