Add negation to search queries

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/4/head
trivernis 3 years ago
parent 5b0769dcd2
commit 329962dde2

@ -1581,7 +1581,7 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]] [[package]]
name = "mediarepo-api" name = "mediarepo-api"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=4600810fca96bf6b457adc39667245a46127e5e8#4600810fca96bf6b457adc39667245a46127e5e8" source = "git+https://github.com/Trivernis/mediarepo-api.git?rev=547947b05a28bb8a9191d3691d91dc7e3c68af0f#547947b05a28bb8a9191d3691d91dc7e3c68af0f"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"chrono", "chrono",

@ -30,7 +30,7 @@ features = ["env-filter"]
[dependencies.mediarepo-api] [dependencies.mediarepo-api]
git = "https://github.com/Trivernis/mediarepo-api.git" git = "https://github.com/Trivernis/mediarepo-api.git"
rev = "4600810fca96bf6b457adc39667245a46127e5e8" rev = "547947b05a28bb8a9191d3691d91dc7e3c68af0f"
features = ["tauri-plugin"] features = ["tauri-plugin"]
[features] [features]

@ -17,7 +17,6 @@ export class AppComponent implements OnInit{
private router: Router, private router: Router,
private snackBar: MatSnackBar, private snackBar: MatSnackBar,
private errorBroker: ErrorBrokerService, private errorBroker: ErrorBrokerService,
private dataloaderService: DataloaderService,
private repoService: RepositoryService, private repoService: RepositoryService,
) { ) {
} }
@ -25,7 +24,7 @@ export class AppComponent implements OnInit{
async ngOnInit() { async ngOnInit() {
this.errorBroker.errorCb = (err: { message: string }) => this.showError(err); this.errorBroker.errorCb = (err: { message: string }) => this.showError(err);
this.errorBroker.infoCb = (info: string) => this.showInfo(info); this.errorBroker.infoCb = (info: string) => this.showInfo(info);
await this.dataloaderService.loadData(); await this.repoService.loadRepositories();
if (this.repoService.selectedRepository.getValue() == undefined) { if (this.repoService.selectedRepository.getValue() == undefined) {
await this.router.navigate(["repositories"]) await this.router.navigate(["repositories"])
} }

@ -1,7 +1,7 @@
<mat-form-field class="full-width" #tagSearch appearance="fill"> <mat-form-field class="full-width" #tagSearch appearance="fill">
<mat-chip-list #chipList> <mat-chip-list #chipList>
<mat-chip *ngFor="let tag of searchTags" (removed)="removeSearchTag(tag)" [removable]="true"> <mat-chip *ngFor="let tag of searchTags" (removed)="removeSearchTag(tag)" [removable]="true">
{{tag}} {{tag.getNormalizedTag()}}
<button matChipRemove> <button matChipRemove>
<mat-icon>cancel</mat-icon> <mat-icon>cancel</mat-icon>
</button> </button>

@ -7,6 +7,7 @@ import {MatChipInputEvent} from "@angular/material/chips";
import {MatAutocompleteSelectedEvent} from "@angular/material/autocomplete"; import {MatAutocompleteSelectedEvent} from "@angular/material/autocomplete";
import {map, startWith} from "rxjs/operators"; import {map, startWith} from "rxjs/operators";
import {Observable} from "rxjs"; import {Observable} from "rxjs";
import {TagQuery} from "../../models/TagQuery";
@Component({ @Component({
selector: 'app-file-search', selector: 'app-file-search',
@ -17,7 +18,7 @@ export class FileSearchComponent {
public searchInputSeparators = [COMMA]; public searchInputSeparators = [COMMA];
public formControl = new FormControl(); public formControl = new FormControl();
public searchTags: string[] = []; public searchTags: TagQuery[] = [];
public suggestionTags: Observable<string[]>; public suggestionTags: Observable<string[]>;
private allTags: string[] = []; private allTags: string[] = [];
@ -29,7 +30,7 @@ export class FileSearchComponent {
this.suggestionTags = this.formControl.valueChanges.pipe(startWith(null), map( this.suggestionTags = this.formControl.valueChanges.pipe(startWith(null), map(
(tag: string | null) => tag ? this.allTags.filter( (tag: string | null) => tag ? this.allTags.filter(
(t: string) => t.includes(tag)).slice(0, 20) : this.allTags.slice(0, 20))); (t: string) => t.includes(tag.replace(/^-/g, ''))).map((t) => tag.startsWith("-")? "-" + t : t).slice(0, 20) : this.allTags.slice(0, 20)));
} }
public async searchForFiles() { public async searchForFiles() {
@ -37,10 +38,14 @@ export class FileSearchComponent {
} }
public addSearchTag(tag: string) { public addSearchTag(tag: string) {
this.searchTags.push(tag); if (tag.startsWith("-")) {
this.searchTags.push(new TagQuery(tag.replace(/^-/g, ''), true));
} else {
this.searchTags.push(new TagQuery(tag, false));
}
} }
async removeSearchTag(tag: string) { async removeSearchTag(tag: TagQuery) {
const index = this.searchTags.indexOf(tag); const index = this.searchTags.indexOf(tag);
if (index >= 0) { if (index >= 0) {
this.searchTags.splice(index, 1); this.searchTags.splice(index, 1);
@ -50,8 +55,8 @@ export class FileSearchComponent {
async addSearchTagByChip(event: MatChipInputEvent) { async addSearchTagByChip(event: MatChipInputEvent) {
const tag = event.value.trim(); const tag = event.value.trim();
if (tag.length > 0 && this.allTags.includes(tag)) { if (tag.length > 0 && this.allTags.includes(tag.replace(/-/g, ''))) {
this.searchTags.push(tag); this.addSearchTag(tag);
event.chipInput?.clear(); event.chipInput?.clear();
this.formControl.setValue(null); this.formControl.setValue(null);
await this.searchForFiles(); } await this.searchForFiles(); }
@ -59,7 +64,7 @@ export class FileSearchComponent {
async addSearchTagByAutocomplete(event: MatAutocompleteSelectedEvent) { async addSearchTagByAutocomplete(event: MatAutocompleteSelectedEvent) {
const tag = event.option.viewValue; const tag = event.option.viewValue;
this.searchTags.push(tag); this.addSearchTag(tag);
this.formControl.setValue(null); this.formControl.setValue(null);
this.tagInput.nativeElement.value = ''; this.tagInput.nativeElement.value = '';
await this.searchForFiles(); } await this.searchForFiles(); }

@ -0,0 +1,8 @@
export class TagQuery {
constructor(public name: string, public negate: boolean) {
}
public getNormalizedTag(): string {
return this.negate? "-" + this.name : this.name;
}
}

@ -13,14 +13,18 @@ import {Observable} from "rxjs";
import {map, startWith} from "rxjs/operators"; import {map, startWith} from "rxjs/operators";
import {FormControl} from "@angular/forms"; import {FormControl} from "@angular/forms";
import {FileSearchComponent} from "../../components/file-search/file-search.component"; import {FileSearchComponent} from "../../components/file-search/file-search.component";
import {DataloaderService} from "../../services/dataloader/dataloader.service";
@Component({ @Component({
selector: 'app-home', selector: 'app-home',
templateUrl: './home.component.html', templateUrl: './home.component.html',
styleUrls: ['./home.component.scss'] styleUrls: ['./home.component.scss']
}) })
export class HomeComponent { export class HomeComponent implements OnInit {
public async ngOnInit(): Promise<void> {
await this.dataloaderService.loadData();
}
constructor() {} constructor(private dataloaderService: DataloaderService) {}
} }

@ -12,13 +12,11 @@ export class DataloaderService {
constructor( constructor(
private erroBroker: ErrorBrokerService, private erroBroker: ErrorBrokerService,
private repositoryService: RepositoryService,
private fileService: FileService, private fileService: FileService,
private tagService: TagService) { } private tagService: TagService) { }
public async loadData() { public async loadData() {
try { try {
await this.repositoryService.loadRepositories();
await this.tagService.loadTags(); await this.tagService.loadTags();
await this.fileService.getFiles(); await this.fileService.getFiles();
} catch (err) { } catch (err) {

@ -4,6 +4,7 @@ import {File} from "../../models/File";
import {invoke} from "@tauri-apps/api/tauri"; import {invoke} from "@tauri-apps/api/tauri";
import {DomSanitizer, SafeResourceUrl} from "@angular/platform-browser"; import {DomSanitizer, SafeResourceUrl} from "@angular/platform-browser";
import {Thumbnail} from "../../models/Thumbnail"; import {Thumbnail} from "../../models/Thumbnail";
import {TagQuery} from "../../models/TagQuery";
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -21,7 +22,7 @@ export class FileService {
this.displayedFiles.next(all_files); this.displayedFiles.next(all_files);
} }
public async findFiles(tags: string[]) { public async findFiles(tags: TagQuery[]) {
let files = await invoke<File[]>("plugin:mediarepo|find_files", {tags}); let files = await invoke<File[]>("plugin:mediarepo|find_files", {tags});
this.displayedFiles.next(files); this.displayedFiles.next(files);
} }

@ -5,6 +5,7 @@ import {invoke} from "@tauri-apps/api/tauri";
import {listen} from "@tauri-apps/api/event"; import {listen} from "@tauri-apps/api/event";
import {Info} from "../../models/Info"; import {Info} from "../../models/Info";
import {ErrorBrokerService} from "../error-broker/error-broker.service"; import {ErrorBrokerService} from "../error-broker/error-broker.service";
import {DataloaderService} from "../dataloader/dataloader.service";
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -13,7 +14,7 @@ export class RepositoryService {
repositories = new BehaviorSubject<Repository[]>([]); repositories = new BehaviorSubject<Repository[]>([]);
public selectedRepository = new BehaviorSubject<Repository | undefined>(undefined); public selectedRepository = new BehaviorSubject<Repository | undefined>(undefined);
constructor(private errorBroker: ErrorBrokerService) { constructor(private errorBroker: ErrorBrokerService, private dataloaderService: DataloaderService) {
this.registerListener() this.registerListener()
} }
@ -35,6 +36,7 @@ export class RepositoryService {
public async setRepository(repo: Repository) { public async setRepository(repo: Repository) {
await invoke("plugin:mediarepo|select_repository", {name: repo.name}); await invoke("plugin:mediarepo|select_repository", {name: repo.name});
this.selectedRepository.next(repo); this.selectedRepository.next(repo);
await this.dataloaderService.loadData();
} }
public async addRepository(name: string, path: string) { public async addRepository(name: string, path: string) {

Loading…
Cancel
Save