Skip to content

Commit 258f018

Browse files
[MNT-24496] ADW Integration with APS Improvements - Re-assign Tasks (#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
1 parent 558ff71 commit 258f018

File tree

14 files changed

+434
-94
lines changed

14 files changed

+434
-94
lines changed

docs/core/components/card-view.component.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Title: Card View component
33
Added: v2.0.0
44
Status: Active
5-
Last reviewed: 2018-05-09
5+
Last reviewed: 2024-10-29
66
---
77

88
# [Card View component](../../../lib/core/src/lib/card-view/components/card-view/card-view.component.ts "Defined in card-view.component.ts")
@@ -353,6 +353,7 @@ const selectItemProperty = new CardViewSelectItemModel(options);
353353
| key\* | string | | Identifying key (important when editing the item) |
354354
| editable | boolean | false | Toggles whether the item is editable |
355355
| value | string | | The original data value for the item |
356+
| 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. |
356357
| 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 |
357358

358359
#### Card Array Item

docs/core/services/card-view-update.service.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Title: Card View Update service
33
Added: v2.0.0
44
Status: Active
5-
Last reviewed: 2022-11-25
5+
Last reviewed: 2024-10-29
66
---
77

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

140+
## Autocomplete Input Value
141+
142+
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.
143+
144+
### Example
145+
146+
You can subscribe to `autocompleteInputValue$` to get the current value of the autocomplete input field and update the options accordingly.
147+
148+
```ts
149+
this.cardViewUpdateService.autocompleteInputValue$.subscribe(value => {
150+
this.options$ = this.getOptions(value);
151+
});
152+
```
140153
## See also
141154

142155
- [Card view component](../components/card-view.component.md)

lib/core/src/lib/card-view/components/card-view-selectitem/card-view-selectitem.component.html

Lines changed: 74 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,80 @@
11
<ng-container *ngIf="!property.isEmpty() || isEditable">
2-
<div
3-
[attr.data-automation-id]="'card-select-label-' + property.key"
4-
class="adf-property-label"
5-
[ngClass]="{
6-
'adf-property-value-editable': isEditable,
7-
'adf-property-readonly-value': isReadonlyProperty
8-
}"
9-
>{{ property.label | translate }}</div>
10-
<div class="adf-property-field">
11-
<div
12-
*ngIf="!isEditable"
13-
class="adf-property-value adf-property-read-only"
14-
[attr.data-automation-id]="'select-readonly-value-' + property.key"
15-
data-automation-class="read-only-value">{{ (property.displayValue | async) | translate }}
2+
<div [ngSwitch]="templateType">
3+
<div *ngSwitchDefault>
4+
<div
5+
[attr.data-automation-id]="'card-select-label-' + property.key"
6+
class="adf-property-label"
7+
[ngClass]="{
8+
'adf-property-value-editable': isEditable,
9+
'adf-property-readonly-value': isReadonlyProperty
10+
}"
11+
>{{ property.label | translate }}
12+
</div>
13+
<div class="adf-property-field">
14+
<div
15+
*ngIf="!isEditable"
16+
class="adf-property-value adf-property-read-only"
17+
[attr.data-automation-id]="'select-readonly-value-' + property.key"
18+
data-automation-class="read-only-value">{{ (property.displayValue | async) | translate }}
19+
</div>
20+
<div *ngIf="isEditable">
21+
<mat-form-field class="adf-property-value" [ngClass]="{'adf-property-value-editable': isEditable}">
22+
<mat-select
23+
[(value)]="value"
24+
[ngClass]="{ 'adf-property-readonly-value': isReadonlyProperty }"
25+
panelClass="adf-select-filter"
26+
(selectionChange)="onChange($event)"
27+
data-automation-class="select-box"
28+
[aria-label]="property.label | translate">
29+
<adf-select-filter-input *ngIf="showInputFilter" (change)="onFilterInputChange($event)"/>
30+
<mat-option *ngIf="displayNoneOption">{{ 'CORE.CARDVIEW.NONE' | translate }}</mat-option>
31+
<mat-option
32+
*ngFor="let option of list$ | async"
33+
[value]="option.key">
34+
{{ option.label | translate }}
35+
</mat-option>
36+
</mat-select>
37+
</mat-form-field>
38+
</div>
39+
</div>
1640
</div>
17-
<div *ngIf="isEditable">
18-
<mat-form-field class="adf-property-value" [ngClass]="{'adf-property-value-editable': isEditable}">
19-
<mat-select
20-
[(value)]="value"
21-
[ngClass]="{ 'adf-property-readonly-value': isReadonlyProperty }"
22-
panelClass="adf-select-filter"
23-
(selectionChange)="onChange($event)"
24-
data-automation-class="select-box"
25-
[aria-label]="property.label | translate">
26-
<adf-select-filter-input *ngIf="showInputFilter" (change)="onFilterInputChange($event)" />
27-
<mat-option *ngIf="displayNoneOption">{{ 'CORE.CARDVIEW.NONE' | translate }}</mat-option>
28-
<mat-option
29-
*ngFor="let option of list$ | async"
30-
[value]="option.key">
31-
{{ option.label | translate }}
41+
<div *ngSwitchCase="'autocompleteBased'">
42+
<mat-form-field
43+
class="adf-property-field adf-card-selectitem-autocomplete"
44+
[ngClass]="{ 'adf-property-read-only': !isEditable }"
45+
[floatLabel]="'always'">
46+
<mat-label
47+
*ngIf="showProperty || isEditable"
48+
[attr.data-automation-id]="'card-autocomplete-based-selectitem-label-' + property.key"
49+
class="adf-property-label"
50+
[ngClass]="{
51+
'adf-property-value-editable': isEditable,
52+
'adf-property-readonly-value': isReadonlyProperty
53+
}">
54+
{{ property.label | translate }}
55+
</mat-label>
56+
<input
57+
matInput
58+
[matAutocomplete]="auto"
59+
class="adf-property-value"
60+
[ngClass]="{
61+
'adf-property-value-editable': isEditable,
62+
'adf-property-readonly-value': isReadonlyProperty
63+
}"
64+
title="{{ property.label | translate }}"
65+
[placeholder]="property.default"
66+
[attr.aria-label]="property.label | translate"
67+
[formControl]="autocompleteControl"
68+
[title]="'CORE.METADATA.ACTIONS.COPY_TO_CLIPBOARD' | translate"
69+
[attr.data-automation-id]="'card-autocomplete-based-selectitem-value-' + property.key"
70+
/>
71+
<mat-autocomplete autoActiveFirstOption #auto="matAutocomplete"
72+
(optionSelected)="onOptionSelected($event)">
73+
<mat-option *ngFor="let option of property.options$ | async" [value]="option.key"
74+
[attr.data-automation-id]="'card-autocomplete-based-selectitem-option-' + property.key">
75+
{{ option.label }}
3276
</mat-option>
33-
</mat-select>
77+
</mat-autocomplete>
3478
</mat-form-field>
3579
</div>
3680
</div>

lib/core/src/lib/card-view/components/card-view-selectitem/card-view-selectitem.component.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
}
4040
}
4141

42+
.adf-card-selectitem-autocomplete .adf-property-value-editable {
43+
padding-left: 10px;
44+
}
45+
4246
#{$mat-form-field-subscript-wrapper} {
4347
display: none;
4448
}

lib/core/src/lib/card-view/components/card-view-selectitem/card-view-selectitem.component.spec.ts

Lines changed: 104 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,17 @@ import { HarnessLoader } from '@angular/cdk/testing';
2525
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
2626
import { MatSelectHarness } from '@angular/material/select/testing';
2727
import { MatFormFieldHarness } from '@angular/material/form-field/testing';
28-
import { NoopTranslateModule } from '@alfresco/adf-core';
28+
import { CardViewUpdateService, NoopTranslateModule } from '@alfresco/adf-core';
2929
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
30+
import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
31+
import { MatAutocompleteHarness } from '@angular/material/autocomplete/testing';
3032

3133
describe('CardViewSelectItemComponent', () => {
3234
let loader: HarnessLoader;
3335
let fixture: ComponentFixture<CardViewSelectItemComponent>;
3436
let component: CardViewSelectItemComponent;
3537
let appConfig: AppConfigService;
38+
let cardViewUpdateService: CardViewUpdateService;
3639
const mockData = [
3740
{ key: 'one', label: 'One' },
3841
{ key: 'two', label: 'Two' },
@@ -65,6 +68,7 @@ describe('CardViewSelectItemComponent', () => {
6568
fixture = TestBed.createComponent(CardViewSelectItemComponent);
6669
component = fixture.componentInstance;
6770
appConfig = TestBed.inject(AppConfigService);
71+
cardViewUpdateService = TestBed.inject(CardViewUpdateService);
6872
component.property = new CardViewSelectItemModel(mockDefaultProps);
6973
loader = TestbedHarnessEnvironment.loader(fixture);
7074
});
@@ -91,7 +95,7 @@ describe('CardViewSelectItemComponent', () => {
9195
editable: false
9296
});
9397

94-
component.ngOnChanges();
98+
component.ngOnChanges({});
9599
fixture.detectChanges();
96100

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

114118
expect(component.value).toEqual('two');
@@ -131,7 +135,7 @@ describe('CardViewSelectItemComponent', () => {
131135
});
132136
component.editable = true;
133137
component.displayNoneOption = true;
134-
component.ngOnChanges();
138+
component.ngOnChanges({});
135139
fixture.detectChanges();
136140

137141
expect(component.value).toEqual(2);
@@ -155,7 +159,7 @@ describe('CardViewSelectItemComponent', () => {
155159
});
156160
component.editable = true;
157161
component.displayNoneOption = true;
158-
component.ngOnChanges();
162+
component.ngOnChanges({});
159163
fixture.detectChanges();
160164

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

170174
it('should render select box if editable property is TRUE', async () => {
171-
component.ngOnChanges();
175+
component.ngOnChanges({});
172176
component.editable = true;
173177
fixture.detectChanges();
174178

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

178182
it('should not have label twice', async () => {
179-
component.ngOnChanges();
183+
component.ngOnChanges({});
180184
component.editable = true;
181185
fixture.detectChanges();
182186

@@ -197,7 +201,7 @@ describe('CardViewSelectItemComponent', () => {
197201
});
198202
component.editable = true;
199203
component.displayNoneOption = false;
200-
component.ngOnChanges();
204+
component.ngOnChanges({});
201205
fixture.detectChanges();
202206

203207
const select = await loader.getHarness(MatSelectHarness);
@@ -225,7 +229,7 @@ describe('CardViewSelectItemComponent', () => {
225229
});
226230
component.editable = true;
227231
component.displayNoneOption = false;
228-
component.ngOnChanges();
232+
component.ngOnChanges({});
229233
fixture.detectChanges();
230234

231235
const select = await loader.getHarness(MatSelectHarness);
@@ -245,7 +249,7 @@ describe('CardViewSelectItemComponent', () => {
245249
});
246250
component.editable = true;
247251
component.displayNoneOption = false;
248-
component.ngOnChanges();
252+
component.ngOnChanges({});
249253
fixture.detectChanges();
250254

251255
const select = await loader.getHarness(MatSelectHarness);
@@ -255,4 +259,94 @@ describe('CardViewSelectItemComponent', () => {
255259
expect(filterInput).not.toBe(null);
256260
});
257261
});
262+
263+
describe('Autocomplete based', () => {
264+
beforeEach(() => {
265+
component.property = new CardViewSelectItemModel({
266+
label: 'Test Label',
267+
value: 'initial value',
268+
key: 'test-key',
269+
default: 'Placeholder',
270+
editable: true,
271+
autocompleteBased: true,
272+
options$: of([
273+
{ key: '1', label: 'Option 1' },
274+
{ key: '2', label: 'Option 2' }
275+
])
276+
});
277+
});
278+
279+
it('should set templateType to autocompleteBased', () => {
280+
component.property.autocompleteBased = true;
281+
fixture.detectChanges();
282+
expect(component.templateType).toBe('autocompleteBased');
283+
});
284+
285+
it('should set initial value to autocompleteControl', () => {
286+
component.ngOnChanges({});
287+
fixture.detectChanges();
288+
289+
expect(component.autocompleteControl.value).toBe('initial value');
290+
});
291+
292+
it('should emit autocompleteInputValue$ with new value on autocompleteControl change', async () => {
293+
const autocompleteValueSpy = spyOn(cardViewUpdateService.autocompleteInputValue$, 'next');
294+
component.editedValue = '';
295+
component.editable = true;
296+
component.ngOnChanges({ property: { firstChange: true } } as any);
297+
fixture.detectChanges();
298+
299+
component.autocompleteControl.setValue('new value');
300+
fixture.detectChanges();
301+
await fixture.whenStable();
302+
303+
expect(autocompleteValueSpy).toHaveBeenCalledWith('new value');
304+
});
305+
306+
it('should update value correctly on option selected', () => {
307+
cardViewUpdateService.update = jasmine.createSpy('update');
308+
const event: MatAutocompleteSelectedEvent = {
309+
option: {
310+
value: '1'
311+
}
312+
} as MatAutocompleteSelectedEvent;
313+
314+
component.ngOnChanges({});
315+
fixture.detectChanges();
316+
317+
component.onOptionSelected(event);
318+
fixture.detectChanges();
319+
320+
expect(component.autocompleteControl.value).toBe('Option 1');
321+
expect(cardViewUpdateService.update).toHaveBeenCalledWith(jasmine.objectContaining(component.property), '1');
322+
});
323+
324+
it('should disable the autocomplete control', () => {
325+
component.editable = false;
326+
component.ngOnChanges({ editable: { currentValue: false, previousValue: true, firstChange: false, isFirstChange: () => false } });
327+
fixture.detectChanges();
328+
expect(component.autocompleteControl.disabled).toBeTrue();
329+
});
330+
331+
it('should enable the autocomplete control', () => {
332+
component.editable = true;
333+
component.ngOnChanges({ editable: { currentValue: true, previousValue: false, firstChange: false, isFirstChange: () => false } });
334+
fixture.detectChanges();
335+
expect(component.autocompleteControl.enabled).toBeTrue();
336+
});
337+
338+
it('should populate options for autocomplete', async () => {
339+
component.ngOnChanges({});
340+
fixture.detectChanges();
341+
342+
const autocomplete = await loader.getHarness(MatAutocompleteHarness);
343+
await autocomplete.enterText('Op');
344+
fixture.detectChanges();
345+
346+
const options = await autocomplete.getOptions();
347+
expect(options.length).toBe(2);
348+
expect(await options[0].getText()).toContain('Option 1');
349+
expect(await options[1].getText()).toContain('Option 2');
350+
});
351+
});
258352
});

0 commit comments

Comments
 (0)