mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-26 20:26:13 +01:00
Support searching artifacts by specified tag name (#18175)
1.Fixes #18082 2.Update CSS Signed-off-by: AllForNothing <sshijun@vmware.com>
This commit is contained in:
parent
fdf93470c5
commit
9d30955607
@ -36,11 +36,13 @@
|
|||||||
<div class="clr-control-container" *ngIf="!selectedValue">
|
<div class="clr-control-container" *ngIf="!selectedValue">
|
||||||
<div class="clr-input-wrapper">
|
<div class="clr-input-wrapper">
|
||||||
<input
|
<input
|
||||||
readonly
|
[readonly]="filterByType !== 'tags'"
|
||||||
placeholder="{{
|
placeholder="{{
|
||||||
'ARTIFACT.FILTER_FOR_ARTIFACTS' | translate
|
'ARTIFACT.FILTER_FOR_ARTIFACTS' | translate
|
||||||
}}"
|
}}"
|
||||||
class="clr-input" />
|
[(ngModel)]="inputTag"
|
||||||
|
(keyup)="searchByInputTag()"
|
||||||
|
class="clr-input no-outline" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span *ngIf="selectedValue">
|
<span *ngIf="selectedValue">
|
||||||
|
@ -35,3 +35,8 @@
|
|||||||
.search-dropdown-toggle {
|
.search-dropdown-toggle {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.no-outline:focus {
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
@ -3,19 +3,23 @@ import {
|
|||||||
ElementRef,
|
ElementRef,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
Input,
|
Input,
|
||||||
|
OnDestroy,
|
||||||
|
OnInit,
|
||||||
Output,
|
Output,
|
||||||
Renderer2,
|
Renderer2,
|
||||||
ViewChild,
|
ViewChild,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { ArtifactFilterEvent, multipleFilter } from '../../../../artifact';
|
import { ArtifactFilterEvent, multipleFilter } from '../../../../artifact';
|
||||||
import { Label } from '../../../../../../../../../../ng-swagger-gen/models/label';
|
import { Label } from '../../../../../../../../../../ng-swagger-gen/models/label';
|
||||||
|
import { Subject, Subscription } from 'rxjs';
|
||||||
|
import { debounceTime } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-artifact-filter',
|
selector: 'app-artifact-filter',
|
||||||
templateUrl: './artifact-filter.component.html',
|
templateUrl: './artifact-filter.component.html',
|
||||||
styleUrls: ['./artifact-filter.component.scss'],
|
styleUrls: ['./artifact-filter.component.scss'],
|
||||||
})
|
})
|
||||||
export class ArtifactFilterComponent {
|
export class ArtifactFilterComponent implements OnInit, OnDestroy {
|
||||||
@Input()
|
@Input()
|
||||||
withDivider: boolean = false;
|
withDivider: boolean = false;
|
||||||
@ViewChild('filterArea')
|
@ViewChild('filterArea')
|
||||||
@ -31,6 +35,9 @@ export class ArtifactFilterComponent {
|
|||||||
filterEvent = new EventEmitter<ArtifactFilterEvent>();
|
filterEvent = new EventEmitter<ArtifactFilterEvent>();
|
||||||
readonly searchId: string = 'search-btn';
|
readonly searchId: string = 'search-btn';
|
||||||
readonly typeSelectId: string = 'type-select';
|
readonly typeSelectId: string = 'type-select';
|
||||||
|
inputTag: string;
|
||||||
|
private _keyupEventSubject: Subject<string> = new Subject();
|
||||||
|
private _keyupEventSubscription: Subscription;
|
||||||
constructor(private renderer: Renderer2) {
|
constructor(private renderer: Renderer2) {
|
||||||
// click outside, then close dropdown
|
// click outside, then close dropdown
|
||||||
this.renderer.listen('window', 'click', (e: Event) => {
|
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() {
|
selectFilterType() {
|
||||||
this.selectedValue = null;
|
this.selectedValue = null;
|
||||||
@ -87,4 +114,7 @@ export class ArtifactFilterComponent {
|
|||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
searchByInputTag() {
|
||||||
|
this._keyupEventSubject.next(this.inputTag);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -816,7 +816,12 @@ export class ArtifactListTabComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (e?.stringValue) {
|
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();
|
this.refresh();
|
||||||
|
@ -130,5 +130,6 @@ export interface ArtifactFilterEvent {
|
|||||||
type?: string;
|
type?: string;
|
||||||
stringValue?: string;
|
stringValue?: string;
|
||||||
isLabel?: boolean;
|
isLabel?: boolean;
|
||||||
|
isInputTag?: boolean;
|
||||||
label?: Label;
|
label?: Label;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user