<label class="form-label" for="tags" i18n>Tags</label>
<div class="input-group flex-nowrap">
- <ng-select name="tags" [items]="tags" bindLabel="name" bindValue="id" [(ngModel)]="value"
+ <ng-select #tagSelect name="tags" [items]="tags" bindLabel="name" bindValue="id" [(ngModel)]="value"
[disabled]="disabled"
[multiple]="true"
[closeOnSelect]="false"
[addTag]="allowCreate ? createTagRef : false"
addTagText="Add tag"
i18n-addTagText
- (change)="onChange(value)"
- (search)="onSearch($event)"
- (focus)="clearLastSearchTerm()"
- (clear)="clearLastSearchTerm()"
- (blur)="onBlur()">
+ (change)="onChange(value)">
<ng-template ng-label-tmp let-item="item">
<span class="tag-wrap tag-wrap-delete" (mousedown)="removeTag($event, item.id)">
DEFAULT_MATCHING_ALGORITHM,
MATCH_ALL,
} from 'src/app/data/matching-model'
-import { NgSelectModule } from '@ng-select/ng-select'
+import { NgSelectComponent, NgSelectModule } from '@ng-select/ng-select'
import { RouterTestingModule } from '@angular/router/testing'
import { HttpClientTestingModule } from '@angular/common/http/testing'
import { of } from 'rxjs'
import { TagService } from 'src/app/services/rest/tag.service'
import {
+ NgbAccordionModule,
NgbModal,
NgbModalModule,
NgbModalRef,
+ NgbPopoverModule,
} from '@ng-bootstrap/ng-bootstrap'
+import { TagEditDialogComponent } from '../../edit-dialog/tag-edit-dialog/tag-edit-dialog.component'
+import { CheckComponent } from '../check/check.component'
+import { IfOwnerDirective } from 'src/app/directives/if-owner.directive'
+import { TextComponent } from '../text/text.component'
+import { ColorComponent } from '../color/color.component'
+import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
+import { PermissionsFormComponent } from '../permissions/permissions-form/permissions-form.component'
+import { SelectComponent } from '../select/select.component'
+import { ColorSliderModule } from 'ngx-color/slider'
+import { By } from '@angular/platform-browser'
const tags: PaperlessTag[] = [
{
beforeEach(async () => {
TestBed.configureTestingModule({
- declarations: [TagsComponent],
+ declarations: [
+ TagsComponent,
+ TagEditDialogComponent,
+ TextComponent,
+ ColorComponent,
+ IfOwnerDirective,
+ SelectComponent,
+ TextComponent,
+ PermissionsFormComponent,
+ ColorComponent,
+ CheckComponent,
+ ],
providers: [
{
provide: TagService,
useValue: {
- listAll: () => of(tags),
+ listAll: () =>
+ of({
+ results: tags,
+ }),
+ create: () =>
+ of({
+ name: 'bar',
+ id: 99,
+ color: '#fff000',
+ }),
},
},
],
RouterTestingModule,
HttpClientTestingModule,
NgbModalModule,
+ NgbAccordionModule,
+ NgbPopoverModule,
],
}).compileComponents()
})
it('should support suggestions', () => {
- expect(component.value).toBeUndefined()
+ expect(component.value).toHaveLength(0)
component.value = []
component.tags = tags
component.suggestions = [1, 2]
it('should support create new using last search term and open a modal', () => {
let activeInstances: NgbModalRef[]
modalService.activeInstances.subscribe((v) => (activeInstances = v))
- component.onSearch({ term: 'bar' })
+ component.select.searchTerm = 'foobar'
component.createTag()
expect(modalService.hasOpenModals()).toBeTruthy()
- expect(activeInstances[0].componentInstance.object.name).toEqual('bar')
+ expect(activeInstances[0].componentInstance.object.name).toEqual('foobar')
+ const editDialog = activeInstances[0]
+ .componentInstance as TagEditDialogComponent
+ editDialog.save() // create is mocked
+ fixture.detectChanges()
+ fixture.whenStable().then(() => {
+ expect(fixture.debugElement.nativeElement.textContent).toContain('foobar')
+ })
})
- it('should clear search term on blur after delay', fakeAsync(() => {
- const clearSpy = jest.spyOn(component, 'clearLastSearchTerm')
- component.onBlur()
- tick(3000)
- expect(clearSpy).toHaveBeenCalled()
- }))
-
it('support remove tags', () => {
component.tags = tags
component.value = [1, 2]
})
it('should get tags', () => {
+ component.tags = null
expect(component.getTag(2)).toBeNull()
component.tags = tags
expect(component.getTag(2)).toEqual(tags[1])
Input,
OnInit,
Output,
+ ViewChild,
} from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { TagEditDialogComponent } from '../../edit-dialog/tag-edit-dialog/tag-edit-dialog.component'
import { TagService } from 'src/app/services/rest/tag.service'
import { EditDialogMode } from '../../edit-dialog/edit-dialog.component'
+import { first, firstValueFrom, tap } from 'rxjs'
+import { NgSelectComponent } from '@ng-select/ng-select'
@Component({
providers: [
@Output()
filterDocuments = new EventEmitter<PaperlessTag[]>()
- value: number[]
+ @ViewChild('tagSelect') select: NgSelectComponent
- tags: PaperlessTag[]
+ value: number[] = []
- public createTagRef: (name) => void
+ tags: PaperlessTag[] = []
- private _lastSearchTerm: string
+ public createTagRef: (name) => void
getTag(id: number) {
if (this.tags) {
})
modal.componentInstance.dialogMode = EditDialogMode.CREATE
if (name) modal.componentInstance.object = { name: name }
- else if (this._lastSearchTerm)
- modal.componentInstance.object = { name: this._lastSearchTerm }
- modal.componentInstance.succeeded.subscribe((newTag) => {
- this.tagService.listAll().subscribe((tags) => {
- this.tags = tags.results
- this.value = [...this.value, newTag.id]
- this.onChange(this.value)
- })
- })
+ else if (this.select.searchTerm)
+ modal.componentInstance.object = { name: this.select.searchTerm }
+ this.select.searchTerm = null
+ this.select.detectChanges()
+ return firstValueFrom(
+ (modal.componentInstance as TagEditDialogComponent).succeeded.pipe(
+ first(),
+ tap(() => {
+ this.tagService.listAll().subscribe((tags) => {
+ this.tags = tags.results
+ })
+ })
+ )
+ )
}
getSuggestions() {
this.onChange(this.value)
}
- clearLastSearchTerm() {
- this._lastSearchTerm = null
- }
-
- onSearch($event) {
- this._lastSearchTerm = $event.term
- }
-
- onBlur() {
- setTimeout(() => {
- this.clearLastSearchTerm()
- }, 3000)
- }
-
get hasPrivate(): boolean {
return this.value.some(
(t) => this.tags?.find((t2) => t2.id === t) === undefined