mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
ACS-8238: Remove IsIncludedPipe and TabLabelsPipe (#9899)
This commit is contained in:
parent
709b291863
commit
c6b121a698
@ -1,28 +0,0 @@
|
|||||||
---
|
|
||||||
Title: Is Included pipe
|
|
||||||
Added: v6.1.0
|
|
||||||
Status: Active
|
|
||||||
Last reviewed: 2023-06-13
|
|
||||||
---
|
|
||||||
|
|
||||||
# [Is Included pipe](../../../lib/content-services/src/lib/pipes/is-included.pipe.ts "Defined in is-included.pipe.ts")
|
|
||||||
|
|
||||||
Checks if the provided value is contained in the provided array.
|
|
||||||
|
|
||||||
## Basic Usage
|
|
||||||
|
|
||||||
<!-- {% raw %} -->
|
|
||||||
|
|
||||||
```HTML
|
|
||||||
<mat-option [disabled]="value | adfIsIncluded: arrayOfValues : comparator"></mat-option>
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- {% endraw %} -->
|
|
||||||
|
|
||||||
## Details
|
|
||||||
|
|
||||||
The pipe takes the provided value and checks if that value is included in the provided array and returns the appropriate boolean value.
|
|
||||||
|
|
||||||
## See also
|
|
||||||
|
|
||||||
- [File upload error pipe](./file-upload-error.pipe.md)
|
|
@ -102,7 +102,6 @@ backend services have been tested with each released version of ADF.
|
|||||||
- [Search Logical Filter component](content-services/components/search-logical-filter.component.md)
|
- [Search Logical Filter component](content-services/components/search-logical-filter.component.md)
|
||||||
- [Search Chip Autocomplete Input component](content-services/components/search-chip-autocomplete-input.component.md)
|
- [Search Chip Autocomplete Input component](content-services/components/search-chip-autocomplete-input.component.md)
|
||||||
- [Search Filter Autocomplete Chips component](content-services/components/search-filter-autocomplete-chips.component.md)
|
- [Search Filter Autocomplete Chips component](content-services/components/search-filter-autocomplete-chips.component.md)
|
||||||
- [Is Included pipe](content-services/pipes/is-included.pipe.md)
|
|
||||||
|
|
||||||
<!--v610 end-->
|
<!--v610 end-->
|
||||||
|
|
||||||
|
@ -23,11 +23,6 @@ import { Pagination, PeopleApi, PersonBodyCreate, PersonBodyUpdate } from '@alfr
|
|||||||
import { EcmUserModel } from '../models/ecm-user.model';
|
import { EcmUserModel } from '../models/ecm-user.model';
|
||||||
import { ContentService } from './content.service';
|
import { ContentService } from './content.service';
|
||||||
|
|
||||||
// eslint-disable-next-line no-shadow
|
|
||||||
export enum ContentGroups {
|
|
||||||
ALFRESCO_ADMINISTRATORS = 'ALFRESCO_ADMINISTRATORS'
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PeopleContentQueryResponse {
|
export interface PeopleContentQueryResponse {
|
||||||
pagination: Pagination;
|
pagination: Pagination;
|
||||||
entries: EcmUserModel[];
|
entries: EcmUserModel[];
|
||||||
@ -56,11 +51,7 @@ export class PeopleContentService {
|
|||||||
return this._peopleApi;
|
return this._peopleApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(private apiService: AlfrescoApiService, authenticationService: AuthenticationService, private contentService: ContentService) {
|
||||||
private apiService: AlfrescoApiService,
|
|
||||||
authenticationService: AuthenticationService,
|
|
||||||
private contentService: ContentService
|
|
||||||
) {
|
|
||||||
authenticationService.onLogout.subscribe(() => {
|
authenticationService.onLogout.subscribe(() => {
|
||||||
this.resetLocalCurrentUser();
|
this.resetLocalCurrentUser();
|
||||||
});
|
});
|
||||||
@ -73,10 +64,7 @@ export class PeopleContentService {
|
|||||||
* @returns User information
|
* @returns User information
|
||||||
*/
|
*/
|
||||||
getPerson(personId: string): Observable<EcmUserModel> {
|
getPerson(personId: string): Observable<EcmUserModel> {
|
||||||
return from(this.peopleApi.getPerson(personId))
|
return from(this.peopleApi.getPerson(personId)).pipe(map((personEntry) => new EcmUserModel(personEntry.entry)));
|
||||||
.pipe(
|
|
||||||
map((personEntry) => new EcmUserModel(personEntry.entry))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentPerson(): Observable<EcmUserModel> {
|
getCurrentPerson(): Observable<EcmUserModel> {
|
||||||
@ -92,7 +80,7 @@ export class PeopleContentService {
|
|||||||
if (this.currentUser) {
|
if (this.currentUser) {
|
||||||
return of(this.currentUser);
|
return of(this.currentUser);
|
||||||
}
|
}
|
||||||
return this.getPerson('-me-').pipe(tap(user => (this.currentUser = user)));
|
return this.getPerson('-me-').pipe(tap((user) => (this.currentUser = user)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,7 +106,7 @@ export class PeopleContentService {
|
|||||||
* @returns Response containing pagination and list of entries
|
* @returns Response containing pagination and list of entries
|
||||||
*/
|
*/
|
||||||
listPeople(requestQuery?: PeopleContentQueryRequestModel): Observable<PeopleContentQueryResponse> {
|
listPeople(requestQuery?: PeopleContentQueryRequestModel): Observable<PeopleContentQueryResponse> {
|
||||||
const requestQueryParams = {skipCount: requestQuery?.skipCount, maxItems: requestQuery?.maxItems};
|
const requestQueryParams = { skipCount: requestQuery?.skipCount, maxItems: requestQuery?.maxItems };
|
||||||
const orderBy = this.buildOrderArray(requestQuery?.sorting);
|
const orderBy = this.buildOrderArray(requestQuery?.sorting);
|
||||||
if (orderBy.length) {
|
if (orderBy.length) {
|
||||||
requestQueryParams['orderBy'] = orderBy;
|
requestQueryParams['orderBy'] = orderBy;
|
||||||
@ -126,7 +114,7 @@ export class PeopleContentService {
|
|||||||
|
|
||||||
const promise = this.peopleApi.listPeople(requestQueryParams);
|
const promise = this.peopleApi.listPeople(requestQueryParams);
|
||||||
return from(promise).pipe(
|
return from(promise).pipe(
|
||||||
map(response => ({
|
map((response) => ({
|
||||||
pagination: response.list.pagination,
|
pagination: response.list.pagination,
|
||||||
entries: response.list.entries.map((person) => person.entry as EcmUserModel)
|
entries: response.list.entries.map((person) => person.entry as EcmUserModel)
|
||||||
}))
|
}))
|
||||||
@ -141,9 +129,7 @@ export class PeopleContentService {
|
|||||||
* @returns Created new person
|
* @returns Created new person
|
||||||
*/
|
*/
|
||||||
createPerson(newPerson: PersonBodyCreate, opts?: any): Observable<EcmUserModel> {
|
createPerson(newPerson: PersonBodyCreate, opts?: any): Observable<EcmUserModel> {
|
||||||
return from(this.peopleApi.createPerson(newPerson, opts)).pipe(
|
return from(this.peopleApi.createPerson(newPerson, opts)).pipe(map((res) => res?.entry as EcmUserModel));
|
||||||
map((res) => res?.entry as EcmUserModel)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -155,9 +141,7 @@ export class PeopleContentService {
|
|||||||
* @returns Updated person model
|
* @returns Updated person model
|
||||||
*/
|
*/
|
||||||
updatePerson(personId: string, details: PersonBodyUpdate, opts?: any): Observable<EcmUserModel> {
|
updatePerson(personId: string, details: PersonBodyUpdate, opts?: any): Observable<EcmUserModel> {
|
||||||
return from(this.peopleApi.updatePerson(personId, details, opts)).pipe(
|
return from(this.peopleApi.updatePerson(personId, details, opts)).pipe(map((res) => res?.entry as EcmUserModel));
|
||||||
map((res) => res?.entry as EcmUserModel)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,10 +17,8 @@
|
|||||||
|
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { NodeNameTooltipPipe } from './node-name-tooltip.pipe';
|
import { NodeNameTooltipPipe } from './node-name-tooltip.pipe';
|
||||||
import { IsIncludedPipe } from './is-included.pipe';
|
|
||||||
import { TabLabelsPipe } from './tab-labels.pipe';
|
|
||||||
|
|
||||||
export const CONTENT_PIPES = [NodeNameTooltipPipe, IsIncludedPipe, TabLabelsPipe] as const;
|
export const CONTENT_PIPES = [NodeNameTooltipPipe] as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use the individual pipe modules instead.
|
* @deprecated Use the individual pipe modules instead.
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @license
|
|
||||||
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { IsIncludedPipe } from './is-included.pipe';
|
|
||||||
|
|
||||||
describe('IsIncludedPipe', () => {
|
|
||||||
|
|
||||||
let pipe: IsIncludedPipe<any>;
|
|
||||||
const array = [1, 2, 'test', [null], {}];
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
pipe = new IsIncludedPipe();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return true if the string is contained in an array', () => {
|
|
||||||
expect(pipe.transform('test', array)).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false if the string is not contained in an array', () => {
|
|
||||||
expect(pipe.transform('test 1', array)).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return true if the number is in the array', () => {
|
|
||||||
expect(pipe.transform(2, array)).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false if the number is not contained in an array', () => {
|
|
||||||
expect(pipe.transform(50, array)).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use provided comparator to check if value contains in the provided array', () => {
|
|
||||||
const arrayOfObjects = [{id: 'id-1', value: 'value-1'}, {id: 'id-2', value: 'value-2'}];
|
|
||||||
const filterFunction = (extension1, extension2) => extension1.value === extension2.value;
|
|
||||||
expect(pipe.transform({id: 'id-1', value: 'value-1'}, arrayOfObjects, filterFunction)).toBeTruthy();
|
|
||||||
expect(pipe.transform({id: 'id-1', value: 'value-3'}, arrayOfObjects, filterFunction)).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,28 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @license
|
|
||||||
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Pipe, PipeTransform } from '@angular/core';
|
|
||||||
|
|
||||||
@Pipe({
|
|
||||||
name: 'adfIsIncluded',
|
|
||||||
standalone: true
|
|
||||||
})
|
|
||||||
export class IsIncludedPipe<T> implements PipeTransform {
|
|
||||||
transform(value: T, array: T[], compare?: (value1: T, value2: T) => boolean): boolean {
|
|
||||||
return compare ? array.some((arrayValue) => compare(value, arrayValue)) : array.includes(value);
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,6 +16,4 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './node-name-tooltip.pipe';
|
export * from './node-name-tooltip.pipe';
|
||||||
export * from './is-included.pipe';
|
|
||||||
export * from './tab-labels.pipe';
|
|
||||||
export * from './content-pipe.module';
|
export * from './content-pipe.module';
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @license
|
|
||||||
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { TabLabelsPipe } from './tab-labels.pipe';
|
|
||||||
import {
|
|
||||||
mockSearchFilterWithoutDisplayedLabelsByField,
|
|
||||||
mockSearchFilterWithWrongDisplayedLabelsByField,
|
|
||||||
mockSearchFilterWithDisplayedLabelsByField
|
|
||||||
} from '../mock/date-range-search-filter.mock';
|
|
||||||
|
|
||||||
describe('TabLabelsPipe', () => {
|
|
||||||
const pipe = new TabLabelsPipe();
|
|
||||||
|
|
||||||
it('should default to field name when there are no settings available', () => {
|
|
||||||
expect(pipe.transform('test', null)).toBe('test');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should default to field name when settings do not contain "displayedLabelsByField" property', () => {
|
|
||||||
expect(pipe.transform('test', mockSearchFilterWithoutDisplayedLabelsByField.component.settings)).toBe('test');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should default to field name when settings with "displayedLabelsByField" property are available but do not contain field', () => {
|
|
||||||
expect(pipe.transform('test', mockSearchFilterWithWrongDisplayedLabelsByField.component.settings)).toBe('test');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display correct label when settings with "displayedLabelsByField" property are available and do contain field', () => {
|
|
||||||
expect(pipe.transform('test', mockSearchFilterWithDisplayedLabelsByField.component.settings)).toBe('test-tab-label');
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,29 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @license
|
|
||||||
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Pipe, PipeTransform } from '@angular/core';
|
|
||||||
import { SearchWidgetSettings } from '../search/models/search-widget-settings.interface';
|
|
||||||
|
|
||||||
@Pipe({
|
|
||||||
name: 'tabLabels',
|
|
||||||
standalone: true
|
|
||||||
})
|
|
||||||
export class TabLabelsPipe implements PipeTransform {
|
|
||||||
transform(field: string, settings?: SearchWidgetSettings): string {
|
|
||||||
return settings?.displayedLabelsByField?.[field] ? settings.displayedLabelsByField[field] : field;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +1,14 @@
|
|||||||
<mat-form-field class="adf-chip-list" appearance="outline">
|
<mat-form-field class="adf-chip-list" appearance="outline">
|
||||||
<mat-chip-list #chipList [attr.aria-label]="'SEARCH.FILTER.ARIA-LABEL.OPTIONS-SELECTION' | translate">
|
<mat-chip-list #chipList [attr.aria-label]="'SEARCH.FILTER.ARIA-LABEL.OPTIONS-SELECTION' | translate">
|
||||||
<mat-chip
|
<mat-chip class="adf-option-chips adf-autocomplete-added-option-chips" *ngFor="let option of selectedOptions" (removed)="remove(option)">
|
||||||
class="adf-option-chips adf-autocomplete-added-option-chips"
|
<span [title]="option.fullPath ? ('SEARCH.RESULTS.WILL_CONTAIN' | translate : { searchTerm: option.fullPath }) : undefined">
|
||||||
*ngFor="let option of selectedOptions"
|
|
||||||
(removed)="remove(option)">
|
|
||||||
<span [title]="option.fullPath ? ('SEARCH.RESULTS.WILL_CONTAIN' | translate:{searchTerm: option.fullPath}) : undefined">
|
|
||||||
{{ option.value }}
|
{{ option.value }}
|
||||||
</span>
|
</span>
|
||||||
<button matChipRemove class="adf-option-chips-delete-button adf-autocomplete-added-option-chips-delete-button"
|
<button
|
||||||
[title]="'SEARCH.FILTER.BUTTONS.REMOVE' | translate">
|
matChipRemove
|
||||||
|
class="adf-option-chips-delete-button adf-autocomplete-added-option-chips-delete-button"
|
||||||
|
[title]="'SEARCH.FILTER.BUTTONS.REMOVE' | translate"
|
||||||
|
>
|
||||||
<mat-icon class="adf-option-chips-delete-icon adf-autocomplete-added-option-chips-delete-icon">close</mat-icon>
|
<mat-icon class="adf-option-chips-delete-icon adf-autocomplete-added-option-chips-delete-icon">close</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</mat-chip>
|
</mat-chip>
|
||||||
@ -29,12 +29,14 @@
|
|||||||
(optionActivated)="activeAnyOption = true" (closed)="activeAnyOption = false">
|
(optionActivated)="activeAnyOption = true" (closed)="activeAnyOption = false">
|
||||||
<ng-container *ngIf="optionInput.value.length > 0">
|
<ng-container *ngIf="optionInput.value.length > 0">
|
||||||
<mat-option
|
<mat-option
|
||||||
[disabled]="option | adfIsIncluded: selectedOptions : compareOption"
|
*ngFor="let option of filteredOptions"
|
||||||
*ngFor="let option of filteredOptions" [value]="option"
|
[value]="option"
|
||||||
[attr.data-automation-id]="'option-' + (option.value)"
|
[disabled]="isOptionSelected(option)"
|
||||||
[title]="option.fullPath ? ('SEARCH.RESULTS.WILL_CONTAIN' | translate:{searchTerm: option.fullPath || option.value}): undefined"
|
[attr.data-automation-id]="'option-' + option.value"
|
||||||
|
[title]="option.fullPath ? ('SEARCH.RESULTS.WILL_CONTAIN' | translate : { searchTerm: option.fullPath || option.value }) : undefined"
|
||||||
class="adf-search-chip-autocomplete-added-option"
|
class="adf-search-chip-autocomplete-added-option"
|
||||||
[ngClass]="(option | adfIsIncluded: selectedOptions : compareOption) && 'adf-autocomplete-added-option'">
|
[ngClass]="isOptionSelected(option) && 'adf-autocomplete-added-option'"
|
||||||
|
>
|
||||||
{{ option.fullPath || option.value }}
|
{{ option.fullPath || option.value }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@ -294,4 +294,46 @@ describe('SearchChipAutocompleteInputComponent', () => {
|
|||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
expect(inputChangedSpy).toHaveBeenCalledOnceWith('test-value');
|
expect(inputChangedSpy).toHaveBeenCalledOnceWith('test-value');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('isOptionSelected', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
component.autocompleteOptions = [{ value: 'option1' }, { value: 'option2' }];
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true if option is already selected', () => {
|
||||||
|
const option = { value: 'option1' };
|
||||||
|
component.selectedOptions = [option];
|
||||||
|
expect(component.isOptionSelected(option)).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if option is not selected', () => {
|
||||||
|
component.selectedOptions = [{ value: 'option1' }];
|
||||||
|
expect(component.isOptionSelected({ value: 'option2' })).toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true if custom compare function finds a match', () => {
|
||||||
|
component.compareOption = (option1, option2) => option1.value.charAt(0) === option2.value.charAt(0);
|
||||||
|
component.selectedOptions = [{ value: 'apple' }];
|
||||||
|
expect(component.isOptionSelected({ value: 'apricot' })).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if custom compare function does not find a match', () => {
|
||||||
|
component.compareOption = (option1, option2) => option1.value.charAt(0) === option2.value.charAt(0);
|
||||||
|
component.selectedOptions = [{ value: 'banana' }];
|
||||||
|
expect(component.isOptionSelected({ value: 'cherry' })).toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if there are no selected options', () => {
|
||||||
|
component.selectedOptions = [];
|
||||||
|
expect(component.isOptionSelected({ value: 'option1' })).toBeFalse();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle undefined compareOption gracefully', () => {
|
||||||
|
component.compareOption = undefined;
|
||||||
|
const option = { value: 'option1' };
|
||||||
|
component.selectedOptions = [option];
|
||||||
|
expect(component.isOptionSelected(option)).toBeTrue();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -153,6 +153,23 @@ export class SearchChipAutocompleteInputComponent implements OnInit, OnDestroy,
|
|||||||
this.optionsChanged.emit(this.selectedOptions);
|
this.optionsChanged.emit(this.selectedOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a given option is already selected.
|
||||||
|
*
|
||||||
|
* This method checks if the provided `option` is present in the `selectedOptions` array.
|
||||||
|
* If a custom comparison function (`compareOption`) is provided, it uses this function to determine equality.
|
||||||
|
* Otherwise, it falls back to using strict equality comparison.
|
||||||
|
*
|
||||||
|
* @param option - The option to check for selection.
|
||||||
|
* @returns `true` if the option is selected, `false` otherwise.
|
||||||
|
*/
|
||||||
|
isOptionSelected(option: AutocompleteOption): boolean {
|
||||||
|
const compare = this.compareOption;
|
||||||
|
const array = this.selectedOptions;
|
||||||
|
|
||||||
|
return compare ? array.some((arrayValue) => compare(option, arrayValue)) : array.includes(option);
|
||||||
|
}
|
||||||
|
|
||||||
private isAdded(value: string): boolean {
|
private isAdded(value: string): boolean {
|
||||||
const valueLowerCase = value.toLowerCase();
|
const valueLowerCase = value.toLowerCase();
|
||||||
return this.selectedOptions.some((option) => option.value.toLowerCase() === valueLowerCase);
|
return this.selectedOptions.some((option) => option.value.toLowerCase() === valueLowerCase);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<adf-search-filter-tabbed>
|
<adf-search-filter-tabbed>
|
||||||
<ng-container *ngFor="let field of fields">
|
<ng-container *ngFor="let field of fields">
|
||||||
<adf-search-date-range
|
<adf-search-date-range
|
||||||
*adf-search-filter-tab="field | tabLabels: settings"
|
*adf-search-filter-tab="getTabLabel(field)"
|
||||||
[dateFormat]="settings.dateFormat"
|
[dateFormat]="settings.dateFormat"
|
||||||
[maxDate]="settings.maxDate"
|
[maxDate]="settings.maxDate"
|
||||||
[field]="field"
|
[field]="field"
|
||||||
|
@ -51,6 +51,7 @@ export class MockSearchDateRangeComponent {
|
|||||||
@Output()
|
@Output()
|
||||||
valid = new EventEmitter<boolean>();
|
valid = new EventEmitter<boolean>();
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('SearchDateRangeTabbedComponent', () => {
|
describe('SearchDateRangeTabbedComponent', () => {
|
||||||
let component: SearchDateRangeTabbedComponent;
|
let component: SearchDateRangeTabbedComponent;
|
||||||
let fixture: ComponentFixture<SearchDateRangeTabbedComponent>;
|
let fixture: ComponentFixture<SearchDateRangeTabbedComponent>;
|
||||||
@ -225,4 +226,41 @@ describe('SearchDateRangeTabbedComponent', () => {
|
|||||||
expect(component.context.queryFragments['dateRange']).toEqual('');
|
expect(component.context.queryFragments['dateRange']).toEqual('');
|
||||||
expect(component.context.update).toHaveBeenCalled();
|
expect(component.context.update).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('SearchDateRangeTabbedComponent getTabLabel', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
component.settings = {
|
||||||
|
displayedLabelsByField: {
|
||||||
|
createdDate: 'Created Date',
|
||||||
|
modifiedDate: 'Modified Date'
|
||||||
|
}
|
||||||
|
} as any;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the custom label if it is defined in settings', () => {
|
||||||
|
const label = component.getTabLabel('createdDate');
|
||||||
|
expect(label).toEqual('Created Date');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the field name if no custom label is defined in settings', () => {
|
||||||
|
const label = component.getTabLabel('someOtherField');
|
||||||
|
expect(label).toEqual('someOtherField');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle undefined settings gracefully', () => {
|
||||||
|
component.settings = undefined;
|
||||||
|
const label = component.getTabLabel('createdDate');
|
||||||
|
expect(label).toEqual('createdDate');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle null field input gracefully', () => {
|
||||||
|
const label = component.getTabLabel(null);
|
||||||
|
expect(label).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle undefined field input gracefully', () => {
|
||||||
|
const label = component.getTabLabel(undefined);
|
||||||
|
expect(label).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -24,25 +24,14 @@ import { SearchWidgetSettings } from '../../models/search-widget-settings.interf
|
|||||||
import { SearchQueryBuilderService } from '../../services/search-query-builder.service';
|
import { SearchQueryBuilderService } from '../../services/search-query-builder.service';
|
||||||
import { InLastDateType } from './search-date-range/in-last-date-type';
|
import { InLastDateType } from './search-date-range/in-last-date-type';
|
||||||
import { TranslationService } from '@alfresco/adf-core';
|
import { TranslationService } from '@alfresco/adf-core';
|
||||||
import {
|
import { endOfDay, endOfToday, format, formatISO, startOfDay, startOfMonth, startOfWeek, subDays, subMonths, subWeeks } from 'date-fns';
|
||||||
endOfDay,
|
|
||||||
endOfToday,
|
|
||||||
format,
|
|
||||||
formatISO,
|
|
||||||
startOfDay,
|
|
||||||
startOfMonth,
|
|
||||||
startOfWeek,
|
|
||||||
subDays,
|
|
||||||
subMonths,
|
|
||||||
subWeeks
|
|
||||||
} from 'date-fns';
|
|
||||||
|
|
||||||
const DEFAULT_DATE_DISPLAY_FORMAT = 'dd-MMM-yy';
|
const DEFAULT_DATE_DISPLAY_FORMAT = 'dd-MMM-yy';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-search-date-range-tabbed',
|
selector: 'adf-search-date-range-tabbed',
|
||||||
templateUrl: './search-date-range-tabbed.component.html',
|
templateUrl: './search-date-range-tabbed.component.html',
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class SearchDateRangeTabbedComponent implements SearchWidget, OnInit {
|
export class SearchDateRangeTabbedComponent implements SearchWidget, OnInit {
|
||||||
displayValue$ = new Subject<string>();
|
displayValue$ = new Subject<string>();
|
||||||
@ -68,7 +57,7 @@ export class SearchDateRangeTabbedComponent implements SearchWidget, OnInit {
|
|||||||
constructor(private translateService: TranslationService) {}
|
constructor(private translateService: TranslationService) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.fields = this.settings?.field.split(',').map(field => field.trim());
|
this.fields = this.settings?.field.split(',').map((field) => field.trim());
|
||||||
this.setDefaultDateFormatSettings();
|
this.setDefaultDateFormatSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,6 +88,10 @@ export class SearchDateRangeTabbedComponent implements SearchWidget, OnInit {
|
|||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTabLabel(field: string): string {
|
||||||
|
return this.settings?.displayedLabelsByField?.[field] ? this.settings.displayedLabelsByField[field] : field;
|
||||||
|
}
|
||||||
|
|
||||||
submitValues() {
|
submitValues() {
|
||||||
this.context.queryFragments[this.id] = this.combinedQuery;
|
this.context.queryFragments[this.id] = this.combinedQuery;
|
||||||
this.displayValue$.next(this.combinedDisplayValue);
|
this.displayValue$.next(this.combinedDisplayValue);
|
||||||
@ -118,7 +111,7 @@ export class SearchDateRangeTabbedComponent implements SearchWidget, OnInit {
|
|||||||
let endDate: Date;
|
let endDate: Date;
|
||||||
if (value.dateRangeType === DateRangeType.IN_LAST) {
|
if (value.dateRangeType === DateRangeType.IN_LAST) {
|
||||||
if (value.inLastValue) {
|
if (value.inLastValue) {
|
||||||
switch(value.inLastValueType) {
|
switch (value.inLastValueType) {
|
||||||
case InLastDateType.DAYS:
|
case InLastDateType.DAYS:
|
||||||
startDate = startOfDay(subDays(new Date(), parseInt(value.inLastValue, 10)));
|
startDate = startOfDay(subDays(new Date(), parseInt(value.inLastValue, 10)));
|
||||||
break;
|
break;
|
||||||
@ -152,7 +145,10 @@ export class SearchDateRangeTabbedComponent implements SearchWidget, OnInit {
|
|||||||
value: value.inLastValue
|
value: value.inLastValue
|
||||||
});
|
});
|
||||||
} else if (value.dateRangeType === DateRangeType.BETWEEN && value.betweenStartDate && value.betweenEndDate) {
|
} else if (value.dateRangeType === DateRangeType.BETWEEN && value.betweenStartDate && value.betweenEndDate) {
|
||||||
displayValue = `${format(startOfDay(value.betweenStartDate), this.settings.dateFormat)} - ${format(endOfDay(value.betweenEndDate), this.settings.dateFormat)}`;
|
displayValue = `${format(startOfDay(value.betweenStartDate), this.settings.dateFormat)} - ${format(
|
||||||
|
endOfDay(value.betweenEndDate),
|
||||||
|
this.settings.dateFormat
|
||||||
|
)}`;
|
||||||
}
|
}
|
||||||
return displayValue;
|
return displayValue;
|
||||||
}
|
}
|
||||||
@ -172,13 +168,19 @@ export class SearchDateRangeTabbedComponent implements SearchWidget, OnInit {
|
|||||||
this.displayValueMapByField.set(field, this.generateDisplayValue(value));
|
this.displayValueMapByField.set(field, this.generateDisplayValue(value));
|
||||||
this.displayValueMapByField.forEach((displayValue: string, fieldForDisplayLabel: string) => {
|
this.displayValueMapByField.forEach((displayValue: string, fieldForDisplayLabel: string) => {
|
||||||
if (displayValue) {
|
if (displayValue) {
|
||||||
const displayLabelForField = `${this.translateService.instant(this.getDisplayLabelForField(fieldForDisplayLabel)).toUpperCase()}: ${displayValue}`;
|
const displayLabelForField = `${this.translateService
|
||||||
this.combinedDisplayValue = this.combinedDisplayValue ? `${this.combinedDisplayValue} ${displayLabelForField}` : `${displayLabelForField}`;
|
.instant(this.getDisplayLabelForField(fieldForDisplayLabel))
|
||||||
|
.toUpperCase()}: ${displayValue}`;
|
||||||
|
this.combinedDisplayValue = this.combinedDisplayValue
|
||||||
|
? `${this.combinedDisplayValue} ${displayLabelForField}`
|
||||||
|
: `${displayLabelForField}`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDisplayLabelForField(fieldForDisplayLabel: string): string {
|
private getDisplayLabelForField(fieldForDisplayLabel: string): string {
|
||||||
return this.settings?.displayedLabelsByField?.[fieldForDisplayLabel] ? this.settings.displayedLabelsByField[fieldForDisplayLabel] : fieldForDisplayLabel;
|
return this.settings?.displayedLabelsByField?.[fieldForDisplayLabel]
|
||||||
|
? this.settings.displayedLabelsByField[fieldForDisplayLabel]
|
||||||
|
: fieldForDisplayLabel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,20 +56,9 @@ import { SearchFilterTabDirective } from './components/search-filter-tabbed/sear
|
|||||||
import { SearchFacetChipTabbedComponent } from './components/search-filter-chips/search-facet-chip-tabbed/search-facet-chip-tabbed.component';
|
import { SearchFacetChipTabbedComponent } from './components/search-filter-chips/search-facet-chip-tabbed/search-facet-chip-tabbed.component';
|
||||||
import { SearchFacetTabbedContentComponent } from './components/search-filter-chips/search-facet-chip-tabbed/search-facet-tabbed-content.component';
|
import { SearchFacetTabbedContentComponent } from './components/search-filter-chips/search-facet-chip-tabbed/search-facet-tabbed-content.component';
|
||||||
import { SearchInputComponent } from './components/search-input';
|
import { SearchInputComponent } from './components/search-input';
|
||||||
import { IsIncludedPipe, TabLabelsPipe } from '../pipes';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [CommonModule, FormsModule, ReactiveFormsModule, MaterialModule, CoreModule, SearchTextModule, SearchInputComponent],
|
||||||
CommonModule,
|
|
||||||
FormsModule,
|
|
||||||
ReactiveFormsModule,
|
|
||||||
MaterialModule,
|
|
||||||
CoreModule,
|
|
||||||
SearchTextModule,
|
|
||||||
SearchInputComponent,
|
|
||||||
IsIncludedPipe,
|
|
||||||
TabLabelsPipe
|
|
||||||
],
|
|
||||||
declarations: [
|
declarations: [
|
||||||
SearchComponent,
|
SearchComponent,
|
||||||
SearchControlComponent,
|
SearchControlComponent,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user