[Cherry-pick]Support searching artifacts by specified tag name (#18176)

Support searching artifacts by specified tag name
  1.Fixes #18082
  2.Update CSS

Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
Shijun Sun 2023-02-08 12:02:47 +08:00 committed by GitHub
parent dc931cfd2c
commit 7f0bd60a8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 4 deletions

View File

@ -36,11 +36,13 @@
<div class="clr-control-container" *ngIf="!selectedValue">
<div class="clr-input-wrapper">
<input
readonly
[readonly]="filterByType !== 'tags'"
placeholder="{{
'ARTIFACT.FILTER_FOR_ARTIFACTS' | translate
}}"
class="clr-input" />
[(ngModel)]="inputTag"
(keyup)="searchByInputTag()"
class="clr-input no-outline" />
</div>
</div>
<span *ngIf="selectedValue">

View File

@ -35,3 +35,8 @@
.search-dropdown-toggle {
margin-right: 5px;
}
.no-outline:focus {
border: none;
background: none;
}

View File

@ -3,19 +3,23 @@ import {
ElementRef,
EventEmitter,
Input,
OnDestroy,
OnInit,
Output,
Renderer2,
ViewChild,
} from '@angular/core';
import { ArtifactFilterEvent, multipleFilter } from '../../../../artifact';
import { Label } from '../../../../../../../../../../ng-swagger-gen/models/label';
import { Subject, Subscription } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
@Component({
selector: 'app-artifact-filter',
templateUrl: './artifact-filter.component.html',
styleUrls: ['./artifact-filter.component.scss'],
})
export class ArtifactFilterComponent {
export class ArtifactFilterComponent implements OnInit, OnDestroy {
@Input()
withDivider: boolean = false;
@ViewChild('filterArea')
@ -31,6 +35,9 @@ export class ArtifactFilterComponent {
filterEvent = new EventEmitter<ArtifactFilterEvent>();
readonly searchId: string = 'search-btn';
readonly typeSelectId: string = 'type-select';
inputTag: string;
private _keyupEventSubject: Subject<string> = new Subject();
private _keyupEventSubscription: Subscription;
constructor(private renderer: Renderer2) {
// click outside, then close dropdown
this.renderer.listen('window', 'click', (e: Event) => {
@ -45,6 +52,26 @@ export class ArtifactFilterComponent {
}
});
}
ngOnInit(): void {
if (!this._keyupEventSubscription) {
this._keyupEventSubscription = this._keyupEventSubject
.pipe(debounceTime(500))
.subscribe(inputTag => {
this.filterEvent.emit({
type: this.filterByType,
isLabel: false,
isInputTag: true,
stringValue: inputTag,
});
});
}
}
ngOnDestroy(): void {
if (this._keyupEventSubscription) {
this._keyupEventSubscription.unsubscribe();
this._keyupEventSubscription = null;
}
}
selectFilterType() {
this.selectedValue = null;
@ -87,4 +114,7 @@ export class ArtifactFilterComponent {
}
return [];
}
searchByInputTag() {
this._keyupEventSubject.next(this.inputTag);
}
}

View File

@ -816,7 +816,12 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
}
} else {
if (e?.stringValue) {
this.filters.push(`${e.type}=${e?.stringValue}`);
if (e?.isInputTag) {
// for input tag, use fuzzy match
this.filters.push(`${e.type}=~${e?.stringValue}`);
} else {
this.filters.push(`${e.type}=${e?.stringValue}`);
}
}
}
this.refresh();

View File

@ -130,5 +130,6 @@ export interface ArtifactFilterEvent {
type?: string;
stringValue?: string;
isLabel?: boolean;
isInputTag?: boolean;
label?: Label;
}