[ACS-8065][ADF] Unify components in TagModule (#10226)

* [ACS-8065] tag creator unification

* [ACS-8065] test adjustments and after review fixes

* [ACS-8065] remove unnecessary style

* [ACS-8065] fix style selector

* [ACS-8065] remove transforming pipe and unnecessary styles

* [ACS-8065] fixes

* [ACS-8065] fixes

* [ACS-8065] fixes

* [ACS-8065] fix view more button placement

* [ACS-8065] fix view more button placement

* [ACS-8065] fix position of view more button for pagination

* [ACS-8065] Fix imports

* [ACS-8065] Unit test fixes

---------

Co-authored-by: MichalKinas <michal.kinas@hyland.com>
This commit is contained in:
tamaragruszka 2024-12-11 11:07:12 +01:00 committed by GitHub
parent 7fa92308f0
commit d6151308c9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 131 additions and 159 deletions

View File

@ -32,6 +32,7 @@ This component shows dynamic list of chips which render depending on free space.
|---------------------|---------------------------------------------------------------------------------|---------------|----------------------------------------------------------------|
| limitChipsDisplayed | `boolean` | false | Should limit number of chips displayed. |
| showDelete | `boolean` | true | Show delete button. |
| disableDelete | `boolean` | false | Disable delete button. |
| roundUpChips | `boolean` | false | Round up chips increasing the border radius of a chip to 20px. |
| pagination | [`Pagination`](../../../lib/js-api/src/api/content-rest-api/docs/Pagination.md) | | Provide if you want to use paginated chips. |
| chips | [`Chip`](../../../lib/core/src/lib/dynamic-chip-list/chip.ts)`[]` | | List of chips to display. |

View File

@ -98,10 +98,9 @@
</div>
</adf-content-metadata-header>
</mat-expansion-panel-header>
<div *ngIf="currentPanel.panelTitle === DefaultPanels.TAGS && !editing" class="adf-metadata-properties-tags">
<mat-chip-set>
<mat-chip *ngFor="let tag of tags" [disableRipple]="true" class="metadata-properties-tag-chip" data-automation-id="metadata-properties-tag-chip">{{ tag }}</mat-chip>
</mat-chip-set>
<div *ngIf="currentPanel.panelTitle === DefaultPanels.TAGS && !editing"
class="adf-metadata-properties-tags">
<adf-dynamic-chip-list [chips]="tagsToDisplay" [showDelete]="false" />
</div>
<div *ngIf="showEmptyTagMessage" class="adf-metadata-no-item-added">
{{ 'METADATA.BASIC.NO_TAGS_ADDED' | translate }}

View File

@ -84,18 +84,8 @@ $panel-properties-height: 56px !default;
}
&-tags {
adf-tags-creator {
.adf-tags-creation {
padding-right: 0;
}
&.adf-creator-with-existing-tags-panel {
background: var(--adf-theme-background-dialog-color);
}
}
[hidden] {
visibility: hidden;
.adf-dynamic-chip-list-chip {
padding: 0;
}
}
}

View File

@ -23,20 +23,20 @@ import { ContentMetadataComponent } from './content-metadata.component';
import { ContentMetadataService } from '../../services/content-metadata.service';
import { AppConfigService, CardViewBaseItemModel, CardViewComponent, NotificationService, UpdateNotification } from '@alfresco/adf-core';
import { NodesApiService } from '../../../common/services/nodes-api.service';
import { EMPTY, of, throwError } from 'rxjs';
import { CardViewContentUpdateService } from '../../../common/services/card-view-content-update.service';
import { PropertyGroup } from '../../interfaces/property-group.interface';
import { PropertyDescriptorsService } from '../../services/property-descriptors.service';
import { MatExpansionPanel } from '@angular/material/expansion';
import { MatDialogModule } from '@angular/material/dialog';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatChipHarness } from '@angular/material/chips/testing';
import { MatDialogModule } from '@angular/material/dialog';
import { MatExpansionPanel } from '@angular/material/expansion';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { EMPTY, of, throwError } from 'rxjs';
import { CategoriesManagementComponent, CategoriesManagementMode } from '../../../category';
import { TagsCreatorComponent, TagsCreatorMode } from '../../../tag';
import { ContentTestingModule } from '../../../testing/content.testing.module';
import { PropertyGroup } from '../../interfaces/property-group.interface';
import { PropertyDescriptorsService } from '../../services/property-descriptors.service';
import { TagService } from '../../../tag/services/tag.service';
import { CategoryService } from '../../../category/services/category.service';
import { TagsCreatorComponent, TagsCreatorMode } from '../../../tag';
import { CategoriesManagementComponent, CategoriesManagementMode } from '../../../category';
import { ContentTestingModule } from '../../../testing/content.testing.module';
import { CardViewContentUpdateService } from '../../../common/services/card-view-content-update.service';
describe('ContentMetadataComponent', () => {
let component: ContentMetadataComponent;
@ -71,11 +71,16 @@ describe('ContentMetadataComponent', () => {
const category1 = new Category({ id: 'test', name: 'testCat' });
const category2 = new Category({ id: 'test2', name: 'testCat2' });
const categoryPagingResponse: CategoryPaging = { list: { pagination: {}, entries: [{ entry: category1 }, { entry: category2 }] } };
const categoryPagingResponse: CategoryPaging = {
list: {
pagination: {},
entries: [{ entry: category1 }, { entry: category2 }]
}
};
const findTagElements = async (): Promise<string[]> => {
const matChipHarnessList = await TestbedHarnessEnvironment.loader(fixture).getAllHarnesses(
MatChipHarness.with({ selector: '[data-automation-id="metadata-properties-tag-chip"]' })
MatChipHarness.with({ selector: '.adf-dynamic-chip-list-chip' })
);
const tags = [];
for (const matChip of matChipHarnessList) {
@ -269,7 +274,11 @@ describe('ContentMetadataComponent', () => {
}));
it('nodeAspectUpdate', fakeAsync(() => {
const fakeNode = { id: 'fake-minimal-node', aspectNames: ['ft:a', 'ft:b', 'ft:c'], name: 'fake-node' } as Node;
const fakeNode = {
id: 'fake-minimal-node',
aspectNames: ['ft:a', 'ft:b', 'ft:c'],
name: 'fake-node'
} as Node;
getGroupedPropertiesSpy.and.stub();
spyOn(contentMetadataService, 'getBasicProperties').and.stub();
updateService.updateNodeAspect(fakeNode);
@ -1321,7 +1330,8 @@ describe('ContentMetadataComponent', () => {
toggleEditModeForTags();
fixture.detectChanges();
expect(await findTagElements()).toHaveSize(0);
const noEditableTagsContainer = fixture.debugElement.query(By.css('div.adf-metadata-properties-tags'));
expect(noEditableTagsContainer).toBeNull();
});
});

View File

@ -23,6 +23,8 @@ import {
CardViewBaseItemModel,
CardViewComponent,
CardViewItem,
Chip,
DynamicChipListComponent,
NotificationService,
TranslationService,
UpdateNotification
@ -39,17 +41,17 @@ import { CategoriesManagementMode } from '../../../category/categories-managemen
import { AllowableOperationsEnum } from '../../../common/models/allowable-operations.enum';
import { ContentService } from '../../../common/services/content.service';
import { CommonModule } from '@angular/common';
import { MatExpansionModule } from '@angular/material/expansion';
import { ContentMetadataHeaderComponent } from './content-metadata-header.component';
import { MatButtonModule } from '@angular/material/button';
import { TranslateModule } from '@ngx-translate/core';
import { MatIconModule } from '@angular/material/icon';
import { MatChipsModule } from '@angular/material/chips';
import { CategoriesManagementComponent } from '../../../category';
import { DynamicExtensionComponent } from '@alfresco/adf-extensions';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatIconModule } from '@angular/material/icon';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { TagsCreatorComponent } from '../../../tag';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { TranslateModule } from '@ngx-translate/core';
import { ContentMetadataHeaderComponent } from './content-metadata-header.component';
import { CategoriesManagementComponent } from '../../../category/categories-management/categories-management.component';
import { DynamicExtensionComponent } from '@alfresco/adf-extensions';
const DEFAULT_SEPARATOR = ', ';
@ -74,7 +76,8 @@ enum DefaultPanels {
DynamicExtensionComponent,
MatProgressBarModule,
TagsCreatorComponent,
CardViewComponent
CardViewComponent,
DynamicChipListComponent
],
templateUrl: './content-metadata.component.html',
styleUrls: ['./content-metadata.component.scss'],
@ -153,6 +156,7 @@ export class ContentMetadataComponent implements OnChanges, OnInit {
basicProperties$: Observable<CardViewItem[]>;
groupedProperties$: Observable<CardViewGroup[]>;
tagsToDisplay: Chip[];
changedProperties = {};
hasMetadataChanged = false;
assignedCategories: Category[] = [];
@ -215,6 +219,11 @@ export class ContentMetadataComponent implements OnChanges, OnInit {
return this._assignedTags;
}
set tags(tags: string[]) {
this._tags = tags;
this.tagsToDisplay = this.tags.map((tag) => ({ id: tag, name: tag }));
}
get tags(): string[] {
return this._tags;
}
@ -309,7 +318,8 @@ export class ContentMetadataComponent implements OnChanges, OnInit {
* @param tags array of tags to register, they are not saved yet until we click save button.
*/
storeTagsToAssign(tags: string[]) {
this._tags = tags;
this.tags = tags;
this._assignedTags = tags;
this.hasMetadataChanged = true;
}
@ -512,8 +522,8 @@ export class ContentMetadataComponent implements OnChanges, OnInit {
private loadTagsForNode(id: string) {
this.tagService.getTagsByNodeId(id).subscribe((tagPaging) => {
this.assignedTagsEntries = tagPaging.list.entries;
this._tags = tagPaging.list.entries.map((tagEntry) => tagEntry.entry.tag);
this._assignedTags = [...this._tags];
this.tags = tagPaging.list.entries.map((tagEntry) => tagEntry.entry.tag);
this._assignedTags = [...this.tags];
});
}

View File

@ -142,7 +142,7 @@
},
"TAGS_CREATOR": {
"EXISTING_TAGS": "Existing tags:",
"EXISTING_TAGS_SELECTION": "Select an existing tag:",
"EXISTING_TAGS_SELECTION": "Select an existing Tag:",
"NO_TAGS_CREATED": "No Tags Created",
"NO_EXISTING_TAGS": "No Existing Tags",
"TITLE": "Create Tags",
@ -152,7 +152,6 @@
"EXISTING_TAG": "Tag already exists",
"ALREADY_ADDED_TAG": "Tag is already added",
"EMPTY_TAG": "Tag name can't contain only spaces",
"REQUIRED": "Tag name is required",
"FETCH_TAGS": "Error while fetching the tags",
"CREATE_TAGS": "Error while creating the tags",
"SPECIAL_CHARACTERS": "Tag name cannot contain prohibited characters"
@ -172,7 +171,7 @@
"DELETE_CATEGORY": "Delete Category",
"EXISTING_CATEGORIES": "Existing Categories:",
"SELECT_EXISTING_CATEGORY": "Select an existing Category:",
"NO_EXISTING_CATEGORIES": "No existing Categories",
"NO_EXISTING_CATEGORIES": "No Existing Categories",
"GENERIC_CREATE": "Create: {{name}}",
"NAME": "Category name",
"LOADING": "Loading",

View File

@ -10,26 +10,21 @@
adf-auto-focus
placeholder="{{ 'TAG.TAGS_CREATOR.TAG_SEARCH_PLACEHOLDER' | translate }}"
/>
<mat-error *ngIf="tagNameControl.invalid && tagNameControl.touched">{{ tagNameErrorMessageKey | translate }} </mat-error>
<mat-error *ngIf="tagNameControl.invalid && tagNameControl.touched">
{{ tagNameErrorMessageKey | translate }}
</mat-error>
</div>
<p class="adf-no-tags-message" *ngIf="showEmptyTagMessage">
{{ 'TAG.TAGS_CREATOR.NO_TAGS_CREATED' | translate }}
</p>
<div class="adf-tags-list" [class.adf-tags-list-fixed]="!tagNameControlVisible" #tagsList>
<mat-chip-listbox *ngIf="tags.length > 0">
<mat-chip *ngFor="let tag of tags" [disableRipple]="true" [title]="tag" class="adf-tags-chip">
{{ tag }}
<button
data-automation-id="remove-tag-button"
mat-icon-button
(click)="removeTag(tag)"
[attr.title]="'TAG.TAGS_CREATOR.TOOLTIPS.DELETE_TAG' | translate"
[disabled]="disabledTagsRemoving"
matChipRemove>
<mat-icon>close</mat-icon>
</button>
</mat-chip>
</mat-chip-listbox>
<ng-container *ngIf="tags?.length > 0">
<adf-dynamic-chip-list
class="adf-tags-chips-container"
[chips]="tagsToDisplay"
[disableDelete]="disabledTagsRemoving"
(removedChip)="removeTag($event)" />
</ng-container>
</div>
</div>
<div class="adf-existing-tags-panel" *ngIf="existingTagsPanelVisible">
@ -40,7 +35,7 @@
role="button"
tabindex="0"
(keyup.enter)="addTag()"
[hidden]="tagNameControl.invalid || typing"
[hidden]="!tagNameControl.value || tagNameControl.invalid || typing"
>
{{ 'TAG.TAGS_CREATOR.CREATE_TAG' | translate : { tag: tagNameControl.value } }}
</span>
@ -49,7 +44,8 @@
</p>
<div class="adf-tags-list">
<mat-list *ngIf="!spinnerVisible && existingTags" [disabled]="isOnlyCreateMode()">
<mat-list-item *ngFor="let tagRow of existingTags" class="adf-tag" (click)="addExistingTagToTagsToAssign(tagRow)">
<mat-list-item *ngFor="let tagRow of existingTags" class="adf-tag"
(click)="addExistingTagToTagsToAssign(tagRow)">
{{ tagRow.entry.tag }}
</mat-list-item>
<p *ngIf="!existingTags?.length">{{ 'TAG.TAGS_CREATOR.NO_EXISTING_TAGS' | translate }}</p>

View File

@ -15,19 +15,19 @@
* limitations under the License.
*/
import { ComponentFixture, discardPeriodicTasks, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
import { TagsCreatorComponent } from './tags-creator.component';
import { NoopTranslateModule, NotificationService } from '@alfresco/adf-core';
import { By } from '@angular/platform-browser';
import { MatError } from '@angular/material/form-field';
import { TagsCreatorMode, TagService } from '@alfresco/adf-content-services';
import { EMPTY, of, throwError } from 'rxjs';
import { DebugElement } from '@angular/core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { NoopTranslateModule, NotificationService } from '@alfresco/adf-core';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
import { DebugElement } from '@angular/core';
import { ComponentFixture, discardPeriodicTasks, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
import { MatChipHarness } from '@angular/material/chips/testing';
import { MatError } from '@angular/material/form-field';
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { EMPTY, of, throwError } from 'rxjs';
import { TagsCreatorComponent } from './tags-creator.component';
describe('TagsCreatorComponent', () => {
let fixture: ComponentFixture<TagsCreatorComponent>;
@ -94,7 +94,7 @@ describe('TagsCreatorComponent', () => {
* @returns list of native elements
*/
function getRemoveTagButtons(): HTMLButtonElement[] {
const elements = fixture.debugElement.queryAll(By.css(`[data-automation-id="remove-tag-button"]`));
const elements = fixture.debugElement.queryAll(By.css(`.adf-dynamic-chip-list-delete-icon`));
return elements.map((el) => el.nativeElement);
}
@ -104,7 +104,7 @@ describe('TagsCreatorComponent', () => {
* @returns list of tags
*/
async function getAddedTags(): Promise<string[]> {
const matChipHarness = await loader.getAllHarnesses(MatChipHarness.with({ selector: '.adf-tags-chip' }));
const matChipHarness = await loader.getAllHarnesses(MatChipHarness.with({ selector: '.adf-dynamic-chip-list-chip' }));
const tagElements = [];
for (const matChip of matChipHarness) {
tagElements.push(await matChip.getText());
@ -337,22 +337,6 @@ describe('TagsCreatorComponent', () => {
expect(getFirstError()).toBe('TAG.TAGS_CREATOR.ERRORS.EMPTY_TAG');
}));
it('should show error for required', fakeAsync(() => {
typeTag('');
component.tagNameControl.markAsTouched();
fixture.detectChanges();
const error = getFirstError();
expect(error).toBe('TAG.TAGS_CREATOR.ERRORS.REQUIRED');
}));
it('should not show error for required if tags are changed', fakeAsync(() => {
typeTag('');
component.tagNameControl.markAsTouched();
component.tags = ['new tag 1', 'new tag 2'];
fixture.detectChanges();
expect(getFirstError()).toBeUndefined();
}));
it('should show error when duplicated already added tag', fakeAsync(() => {
const tag = 'Some tag';
@ -438,17 +422,6 @@ describe('TagsCreatorComponent', () => {
const error = getFirstError();
expect(error).toBe('TAG.TAGS_CREATOR.ERRORS.EXISTING_TAG');
}));
it('should error for required when not typed anything and blur input', fakeAsync(() => {
component.tagNameControlVisible = true;
component.tagNameControl.markAsTouched();
fixture.detectChanges();
const error = getFirstError();
expect(error).toBe('TAG.TAGS_CREATOR.ERRORS.REQUIRED');
flush();
}));
});
});

View File

@ -15,6 +15,7 @@
* limitations under the License.
*/
import { Chip, DynamicChipListComponent, NotificationService } from '@alfresco/adf-core';
import { TagEntry, TagPaging } from '@alfresco/js-api';
import {
Component,
@ -30,28 +31,26 @@ import {
ViewChild,
ViewEncapsulation
} from '@angular/core';
import { FormControl, ReactiveFormsModule, Validators } from '@angular/forms';
import { debounce, distinctUntilChanged, finalize, first, map, takeUntil, tap } from 'rxjs/operators';
import { EMPTY, forkJoin, Observable, Subject, timer } from 'rxjs';
import { NotificationService } from '@alfresco/adf-core';
import { TagsCreatorMode } from './tags-creator-mode';
import { TagService } from '../services/tag.service';
import { CommonModule } from '@angular/common';
import { MatInputModule } from '@angular/material/input';
import { AutoFocusDirective } from '../../directives';
import { TranslateModule } from '@ngx-translate/core';
import { MatChipsModule } from '@angular/material/chips';
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatChipsModule } from '@angular/material/chips';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatListModule } from '@angular/material/list';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { TranslateModule } from '@ngx-translate/core';
import { EMPTY, forkJoin, Observable, Subject, timer } from 'rxjs';
import { debounce, distinctUntilChanged, finalize, first, map, takeUntil, tap } from 'rxjs/operators';
import { AutoFocusDirective } from '../../directives';
import { TagService } from '../services/tag.service';
import { TagsCreatorMode } from './tags-creator-mode';
interface TagNameControlErrors {
duplicatedExistingTag?: boolean;
duplicatedAddedTag?: boolean;
emptyTag?: boolean;
required?: boolean;
specialCharacters?: boolean;
}
@ -76,7 +75,8 @@ const DEFAULT_TAGS_SORTING = {
MatButtonModule,
MatIconModule,
MatListModule,
MatProgressSpinnerModule
MatProgressSpinnerModule,
DynamicChipListComponent
],
templateUrl: './tags-creator.component.html',
styleUrls: ['./tags-creator.component.scss'],
@ -105,13 +105,11 @@ export class TagsCreatorComponent implements OnInit, OnDestroy {
@Input()
set tags(tags: string[]) {
this._tags = [...tags];
this.tagsToDisplay = this.tags.map((tag) => ({ id: tag, name: tag }));
this._initialExistingTags = null;
this._existingTags = null;
this.loadTags(this.tagNameControl.value);
this.tagNameControl.updateValueAndValidity();
if (this.tagNameControl.errors?.required) {
this.tagNameControl.markAsUntouched();
}
}
get tags(): string[] {
@ -130,9 +128,6 @@ export class TagsCreatorComponent implements OnInit, OnDestroy {
this._existingTagsPanelVisible = true;
setTimeout(() => {
this.tagNameInputElement?.nativeElement?.scrollIntoView();
if (!this.tags.length) {
this.tagNameInputElement?.nativeElement?.focus();
}
});
} else {
this._existingTagsPanelVisible = false;
@ -156,11 +151,12 @@ export class TagsCreatorComponent implements OnInit, OnDestroy {
@Output()
tagsChange = new EventEmitter<string[]>();
tagsToDisplay: Chip[] = [];
readonly nameErrorMessagesByErrors = new Map<keyof TagNameControlErrors, string>([
['duplicatedExistingTag', 'EXISTING_TAG'],
['duplicatedAddedTag', 'ALREADY_ADDED_TAG'],
['emptyTag', 'EMPTY_TAG'],
['required', 'REQUIRED'],
['specialCharacters', 'SPECIAL_CHARACTERS']
]);
@ -170,7 +166,7 @@ export class TagsCreatorComponent implements OnInit, OnDestroy {
private _tags: string[] = [];
private _tagNameControl = new FormControl<string>(
'',
[this.validateIfNotAlreadyAdded.bind(this), Validators.required, this.validateEmptyTag, this.validateSpecialCharacters],
[this.validateIfNotAlreadyAdded.bind(this), this.validateEmptyTag, this.validateSpecialCharacters],
this.validateIfNotExistingTag.bind(this)
);
private _tagNameControlVisible = false;
@ -276,7 +272,7 @@ export class TagsCreatorComponent implements OnInit, OnDestroy {
*/
addTag(): void {
if (!this._typing && !this.tagNameControl.invalid) {
this.tags.push(this.tagNameControl.value.trim());
this.tags = [...this.tags, this.tagNameControl.value.trim()];
this.clearTagNameInput();
this.checkScrollbarVisibility();
this.tagsChange.emit(this.tags);
@ -291,7 +287,8 @@ export class TagsCreatorComponent implements OnInit, OnDestroy {
*/
removeTag(tag: string): void {
this.removeTagFromArray(this.tags, tag);
this.tagNameControl.updateValueAndValidity({ emitEvent: false });
this.tags = [...this.tags];
this.tagNameControl.updateValueAndValidity();
this.updateExistingTagsListOnRemoveFromTagsToConfirm(tag);
this.exactTagSet$.next();
this.checkScrollbarVisibility();
@ -308,6 +305,7 @@ export class TagsCreatorComponent implements OnInit, OnDestroy {
this.tags.push(selectedTag.entry.tag);
this.removeTagFromArray(this.existingTags, selectedTag);
this.tagNameControl.updateValueAndValidity();
this.tags = [...this.tags];
this.exactTagSet$.next();
this.tagsChange.emit(this.tags);
}
@ -337,8 +335,8 @@ export class TagsCreatorComponent implements OnInit, OnDestroy {
takeUntil(this.cancelExistingTagsLoading$),
finalize(() => (this._typing = false))
)
.subscribe(
({ exactResult, searchedResult }: { exactResult: TagEntry; searchedResult: TagPaging }) => {
.subscribe({
next: ({ exactResult, searchedResult }: { exactResult: TagEntry; searchedResult: TagPaging }) => {
if (exactResult) {
this.existingExactTag = exactResult;
this.removeExactTagFromSearchedResult(searchedResult);
@ -352,11 +350,11 @@ export class TagsCreatorComponent implements OnInit, OnDestroy {
this.exactTagSet$.next();
this._spinnerVisible = false;
},
() => {
error: () => {
this.notificationService.showError('TAG.TAGS_CREATOR.ERRORS.FETCH_TAGS');
this._spinnerVisible = false;
}
);
});
} else {
this.existingExactTag = null;
this._spinnerVisible = false;

View File

@ -18,6 +18,7 @@
<mat-icon *ngIf="showDelete"
id="adf-dynamic-chip-list-delete-{{ chip.name }}"
class="adf-dynamic-chip-list-delete-icon"
[disabled]="disableDelete"
matChipRemove>
close
</mat-icon>
@ -26,9 +27,9 @@
<button
data-automation-id="adf-dynamic-chip-list-view-more-button"
mat-button
[hidden]="chipsToDisplay.length === 0 || !limitChipsDisplayed"
[hidden]="chipsToDisplay?.length === 0 || !limitChipsDisplayed"
[style.left.px]="viewMoreButtonLeftOffset"
[style.top.px]="viewMoreButtonTop"
[style.top.px]="!!pagination ? viewMoreButtonTop : ''"
class="adf-dynamic-chip-list-view-more-button"
[class.adf-dynamic-chip-list-hidden-btn]="!calculationsDone"
(click)="displayNextChips($event)">

View File

@ -10,7 +10,6 @@
.adf-dynamic-chip-list-view-more-button {
margin-left: 5px;
position: absolute;
width: auto;
padding: 0 16px;
&[hidden] {
@ -27,27 +26,14 @@
}
&.adf-dynamic-chip-list-paginated {
/* TODO(mdc-migration): The following rule targets internal classes of chips that may no longer apply for the MDC version. */
mat-chip-list {
width: 100%;
& > div {
width: 100%;
}
}
.adf-dynamic-chip-list-view-more-button {
margin: -2px 4px 4px 24px;
margin-left: 24px;
}
}
&.adf-dynamic-chip-list-button-in-next-line {
align-items: unset;
padding-bottom: 54px;
.adf-dynamic-chip-list-view-more-button {
margin-top: 4px;
}
}
&:not(.adf-dynamic-chip-list-paginated) {
@ -55,7 +41,6 @@
&:not(.adf-dynamic-chip-list-flex-column) {
.adf-dynamic-chip-list-view-more-button {
margin-top: 18px;
margin-left: 4px;
}
}
@ -70,7 +55,6 @@
}
.adf-dynamic-chip-list-chip {
height: auto;
word-break: break-word;
margin-top: 0;
margin-bottom: 0;
@ -84,14 +68,4 @@
}
}
}
.adf-dynamic-chip-list-delete-icon {
font-size: var(--theme-title-font-size);
background-repeat: no-repeat;
display: inline-block;
fill: currentcolor;
height: 20px;
width: 20px;
color: var(--theme-primary-color-default-contrast);
}
}

View File

@ -146,6 +146,19 @@ describe('DynamicChipListComponent', () => {
expect(getComputedStyle(chip.nativeElement).borderRadius).toBe('20px');
});
it('should disable the delete button if disableDelete is true', async () => {
component.disableDelete = true;
component.ngOnChanges({
chips: new SimpleChange(undefined, component.chips, true)
});
fixture.detectChanges();
await fixture.whenStable();
const chip = fixture.debugElement.query(By.css('.adf-dynamic-chip-list-delete-icon'));
expect(Object.keys(chip.attributes)).toContain('disabled');
});
it('should not render view more button by default', async () => {
component.ngOnChanges({
chips: new SimpleChange(undefined, component.chips, true)

View File

@ -65,6 +65,10 @@ export class DynamicChipListComponent implements OnChanges, OnInit, AfterViewIni
@Input()
showDelete = true;
/** Disable delete button. */
@Input()
disableDelete = false;
/** Should limit number of chips displayed. */
@Input()
limitChipsDisplayed = false;
@ -101,8 +105,10 @@ export class DynamicChipListComponent implements OnChanges, OnInit, AfterViewIni
private viewMoreButtonLeftOffsetBeforeFlexDirection: number;
private requestedDisplayingAllChips = false;
private resizeObserver = new ResizeObserver(() => {
this.calculateChipsToDisplay();
this.changeDetectorRef.detectChanges();
if (this.initialLimitChipsDisplayed && this.chipsToDisplay.length) {
this.calculateChipsToDisplay();
this.changeDetectorRef.detectChanges();
}
});
constructor(private changeDetectorRef: ChangeDetectorRef) {}
@ -117,10 +123,8 @@ export class DynamicChipListComponent implements OnChanges, OnInit, AfterViewIni
this.initialChips = this.chips;
this.chipsToDisplay = this.initialChips;
if (this.limitChipsDisplayed && this.chipsToDisplay.length) {
setTimeout(() => {
this.calculateChipsToDisplay();
this.changeDetectorRef.detectChanges();
});
this.calculateChipsToDisplay();
this.changeDetectorRef.detectChanges();
}
}
}
@ -230,5 +234,9 @@ export class DynamicChipListComponent implements OnChanges, OnInit, AfterViewIni
} else {
this.viewMoreButtonLeftOffset = this.columnFlexDirection ? 0 : this.viewMoreButtonLeftOffsetBeforeFlexDirection;
}
if (!this.pagination) {
this.viewMoreButtonTop = null;
}
}
}