From 1ed94de65f1a97ee4d15070e5eaeeecf22af78eb Mon Sep 17 00:00:00 2001 From: xBlade58 Date: Fri, 20 Jan 2023 22:10:47 +0100 Subject: [PATCH 1/5] Filtering by Tags and Search field working --- src/app.js | 1 + src/app/table-passwords/table-passwords.ts | 51 ++++++++++++---------- storage.json | 44 ++++++++----------- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/app.js b/src/app.js index e64f536..2e51a15 100644 --- a/src/app.js +++ b/src/app.js @@ -26,6 +26,7 @@ function createWindow () { slashes: true }) ); + mainWindow.webContents.openDevTools(); mainWindow.on('closed', function () { mainWindow = null diff --git a/src/app/table-passwords/table-passwords.ts b/src/app/table-passwords/table-passwords.ts index 5fc0db4..0b5150d 100644 --- a/src/app/table-passwords/table-passwords.ts +++ b/src/app/table-passwords/table-passwords.ts @@ -28,11 +28,13 @@ export class TablePassword { constructor(private fsService: FileSystemService, private router: Router) { const passwords: Password[] = [] this.dataSource=new MatTableDataSource(passwords); + this.dataSource.filterPredicate = this.getFilterPredicate(); this.loadCredentials(); } + ngAfterViewInit() { this.dataSource.sort=this.sort; } @@ -42,8 +44,7 @@ export class TablePassword { if(event.target != null){ const nTarget = event.target as HTMLInputElement; this.currSearchFilter= nTarget.value; - this.dataSource.filter = this.currSearchFilter.trim().toLowerCase(); - //this.filterByTags(); + this.filterByStringAndTag(); } } @@ -54,46 +55,48 @@ export class TablePassword { } else { this.selectedChips.push(chip); } - - console.log('this.selecteChips:' + this.selectedChips) - //this.filterByTags() - this.dataSource.filter = this.currSearchFilter.trim().toLowerCase(); - + this.filterByStringAndTag() } - filterByTags() { - this.dataSource.filterPredicate = this.getFilterPredicate(); - this.dataSource.filter=this.currSearchFilter; + filterByStringAndTag() { + if(this.currSearchFilter === '') { + this.dataSource.filter = 'empty' + } else { + this.dataSource.filter = this.currSearchFilter + } } getFilterPredicate(){ - console.log('Doing predicate..') return (data: Password, filter: string) => { - - const matchFilter = [] - let isChipTag = false - if(this.selectedChips.length != 0){ - //isChipTag = this.selectedChips.includes(data.tag); - //isChipTag = false + + //if no term inserted + if(filter === 'empty'){ + if(this.selectedChips.length === 0) return true; + return checkForTags(this.selectedChips, data.tag) } + const matchFilter = [] const colTitle = data.title; const colUsername = data.username; const colUrl = data.url; - const matchTitle = colTitle.toLowerCase().includes(filter) - const matchUsername = colUsername.toLowerCase().includes(filter) - const matchUrl = colUrl.toLowerCase().includes(filter) + const matchTitle = colTitle.toLowerCase().startsWith(filter.toLowerCase()) + const matchUsername = colUsername.toLowerCase().startsWith(filter.toLowerCase()) + const matchUrl = colUrl.toLowerCase().startsWith(filter.toLowerCase()) matchFilter.push(matchTitle, matchUsername, matchUrl); + const matchStrings = matchFilter.some((el)=> el == true); - return isChipTag && matchFilter.some((el)=> el == true); + //if key term but no tags + if(this.selectedChips.length === 0) { + return matchStrings + } + return checkForTags(this.selectedChips, data.tag) && matchStrings; } } loadCredentials() { this.fsService.loadCrendentials().then((data: Password[]) => { - console.log("length:" + data.length) this.dataSource.data = data; }) } @@ -110,3 +113,7 @@ export class TablePassword { } +function checkForTags(selectedChips: string[], tag: string) { + return selectedChips.includes(tag) +} + diff --git a/storage.json b/storage.json index 51a7574..4831780 100644 --- a/storage.json +++ b/storage.json @@ -1,34 +1,26 @@ [ { - "id": "b217ea30-bb57-4645-a359-b6a258e03007", - "title": "jakob", - "username": "jakob", - "password": "kblpc", - "url": "jakob", - "tag": "jakob" + "id": "179a5e38-6c36-4bb4-ab72-f390c81b1bee", + "title": "Netflix", + "username": "mert", + "password": "nfsu", + "url": "netflix.com", + "tag": "Streaming" }, { - "id": "3708e00c-617d-41d3-b433-adee5a93020f", - "title": "h", - "username": "h", - "password": "i", - "url": "h", - "tag": "h" + "id": "7199e1ce-bea4-48d7-ae54-fae77d385aca", + "title": "LoL", + "username": "mert", + "password": "nfsu", + "url": "lol.com", + "tag": "Games" }, { - "id": "3c64206e-dbe9-4215-8169-caa6b94c59f4", - "title": "everything", - "username": "everything", - "password": "fwfszuijoh", - "url": "everything", - "tag": "everything" - }, - { - "id": "1772c536-2ea5-4d16-a282-03e4303ff8c2", - "title": "", - "username": "", - "password": "", - "url": "", - "tag": "" + "id": "4e355c7e-d739-4a27-abd5-2b58251b0bc3", + "title": "Amazon", + "username": "mert", + "password": "nfsu", + "url": "amazon.com", + "tag": "Streaming" } ] \ No newline at end of file From 066c4e5e34aeb29030de2681b9d220299fcfd7c5 Mon Sep 17 00:00:00 2001 From: Jakob Date: Fri, 20 Jan 2023 23:16:26 +0100 Subject: [PATCH 2/5] added delete functionality --- src/app.js | 11 ++++++ src/app/@types/renderer.d.ts | 1 + src/app/edit-credential/edit-credential.html | 1 + src/app/edit-credential/edit-credential.ts | 9 +++++ src/app/filesystem.service.ts | 4 +++ src/preload.js | 4 +-- storage.json | 36 ++++---------------- 7 files changed, 34 insertions(+), 32 deletions(-) diff --git a/src/app.js b/src/app.js index e64f536..c1fd53d 100644 --- a/src/app.js +++ b/src/app.js @@ -37,6 +37,7 @@ app.on('ready', () => { ipcMain.handle('storage:fetchPasswordById', handlePasswordById); ipcMain.handle('storage:saveCredential', handleSaveCredential); ipcMain.handle('storage:editCredential', handleEditCredential); + ipcMain.handle('storage:deleteCredentialById', handleDeleteCredentialById); createWindow() }) @@ -94,4 +95,14 @@ async function handleEditCredential(event, updatedData) { }) } +async function handleDeleteCredentialById(event, id) { + var creds = await readFile('storage.json') + var jsArr = JSON.parse(creds); + jsArr = jsArr.filter(item => item.id !== id) + + writeFile('storage.json', JSON.stringify(jsArr, null, 4), function (err){ + if(err) throw err + }) +} + diff --git a/src/app/@types/renderer.d.ts b/src/app/@types/renderer.d.ts index 121e049..e7f3529 100644 --- a/src/app/@types/renderer.d.ts +++ b/src/app/@types/renderer.d.ts @@ -1,6 +1,7 @@ export interface IElectronAPI { saveCredential: (data:any) => Promise, editCredential: (toUpdate:any) => Promise, + deleteCredentialById: (id:string) => Promise, loadCredentials: () => Promise, loadPasswordById: (id:string) => Promise } diff --git a/src/app/edit-credential/edit-credential.html b/src/app/edit-credential/edit-credential.html index 0e4a26d..cd29d39 100644 --- a/src/app/edit-credential/edit-credential.html +++ b/src/app/edit-credential/edit-credential.html @@ -38,6 +38,7 @@

+
diff --git a/src/app/edit-credential/edit-credential.ts b/src/app/edit-credential/edit-credential.ts index b1c1025..19e1e66 100644 --- a/src/app/edit-credential/edit-credential.ts +++ b/src/app/edit-credential/edit-credential.ts @@ -50,6 +50,15 @@ export class EditCredential { this.router.navigate(['']) } + async delete(){ + this.loading = true; + var toDelteId = history.state.data.id; + this.fsService.deleteCredentialById(toDelteId).then(()=> { + this.loading = false; + this.router.navigate(['']); + }) + } + async edit(){ this.loading = true; var obj = { diff --git a/src/app/filesystem.service.ts b/src/app/filesystem.service.ts index 6561b7b..4444b6a 100644 --- a/src/app/filesystem.service.ts +++ b/src/app/filesystem.service.ts @@ -45,4 +45,8 @@ export class FileSystemService { async saveCredential(newCred: any): Promise { return await window.electronAPI.saveCredential(newCred) } + + async deleteCredentialById(id: string): Promise { + return await window.electronAPI.deleteCredentialById(id) + } } diff --git a/src/preload.js b/src/preload.js index 291a453..d831c43 100644 --- a/src/preload.js +++ b/src/preload.js @@ -4,6 +4,6 @@ contextBridge.exposeInMainWorld('electronAPI', { loadCredentials: () => ipcRenderer.invoke('storage:fetchAll'), loadPasswordById: (id) => ipcRenderer.invoke('storage:fetchPasswordById', id), saveCredential: (data) => ipcRenderer.invoke('storage:saveCredential', data), - editCredential: (toUpdate) => ipcRenderer.invoke('storage:editCredential', toUpdate) - + editCredential: (toUpdate) => ipcRenderer.invoke('storage:editCredential', toUpdate), + deleteCredentialById: (id) => ipcRenderer.invoke('storage:deleteCredentialById', id) }) diff --git a/storage.json b/storage.json index 51a7574..ed5d873 100644 --- a/storage.json +++ b/storage.json @@ -1,34 +1,10 @@ [ { - "id": "b217ea30-bb57-4645-a359-b6a258e03007", - "title": "jakob", - "username": "jakob", - "password": "kblpc", - "url": "jakob", - "tag": "jakob" - }, - { - "id": "3708e00c-617d-41d3-b433-adee5a93020f", - "title": "h", - "username": "h", - "password": "i", - "url": "h", - "tag": "h" - }, - { - "id": "3c64206e-dbe9-4215-8169-caa6b94c59f4", - "title": "everything", - "username": "everything", - "password": "fwfszuijoh", - "url": "everything", - "tag": "everything" - }, - { - "id": "1772c536-2ea5-4d16-a282-03e4303ff8c2", - "title": "", - "username": "", - "password": "", - "url": "", - "tag": "" + "id": "94e18905-e3e5-4528-9370-f7228ca234e5", + "title": "Netflix", + "username": "movieManica2", + "password": "ofugmjytvyyt", + "url": "netflix.com", + "tag": "Film" } ] \ No newline at end of file From d59f2891c70781aa0ccf5573b5d8b4ee0388d425 Mon Sep 17 00:00:00 2001 From: xBlade58 Date: Sat, 21 Jan 2023 11:15:09 +0100 Subject: [PATCH 3/5] Create & Edit multiple Tags --- .../Password.ts => @types/Credential.ts} | 5 +- src/app/@types/renderer.d.ts | 6 +- src/app/app.module.ts | 4 +- .../create-credential/create-credential.html | 32 ++++-- .../create-credential/create-credential.ts | 99 ++++++++++++++----- src/app/edit-credential/edit-credential.html | 27 ++++- src/app/edit-credential/edit-credential.ts | 61 ++++++++++-- src/app/filesystem.service.ts | 36 +++---- src/app/table-passwords/table-passwords.html | 8 +- src/app/table-passwords/table-passwords.ts | 48 ++++++--- storage.json | 36 ++++--- 11 files changed, 256 insertions(+), 106 deletions(-) rename src/app/{create-credential/Password.ts => @types/Credential.ts} (64%) diff --git a/src/app/create-credential/Password.ts b/src/app/@types/Credential.ts similarity index 64% rename from src/app/create-credential/Password.ts rename to src/app/@types/Credential.ts index dca3f09..3de053a 100644 --- a/src/app/create-credential/Password.ts +++ b/src/app/@types/Credential.ts @@ -1,8 +1,9 @@ -export interface Password { + +export interface Credential { id: string, title: string; username: string; password: string url: string; - tag: string + tags: string[] } diff --git a/src/app/@types/renderer.d.ts b/src/app/@types/renderer.d.ts index 121e049..0847416 100644 --- a/src/app/@types/renderer.d.ts +++ b/src/app/@types/renderer.d.ts @@ -1,6 +1,8 @@ +import { Credential } from "./Credential" + export interface IElectronAPI { - saveCredential: (data:any) => Promise, - editCredential: (toUpdate:any) => Promise, + saveCredential: (data:Credential) => Promise, + editCredential: (toUpdate:Credential) => Promise, loadCredentials: () => Promise, loadPasswordById: (id:string) => Promise } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 301a715..ada313a 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -18,6 +18,7 @@ import { MatInputModule } from '@angular/material/input'; import { MatChipsModule } from '@angular/material/chips'; import { MatIconModule } from '@angular/material/icon' import { CreateCredential } from './create-credential/create-credential'; +import {MatAutocompleteModule} from '@angular/material/autocomplete' @NgModule({ declarations: [ @@ -36,7 +37,8 @@ import { CreateCredential } from './create-credential/create-credential'; MatIconModule, FormsModule, MatProgressSpinnerModule, - ReactiveFormsModule + ReactiveFormsModule, + MatAutocompleteModule ], exports: [ MatFormFieldModule, diff --git a/src/app/create-credential/create-credential.html b/src/app/create-credential/create-credential.html index 764f44e..7632118 100644 --- a/src/app/create-credential/create-credential.html +++ b/src/app/create-credential/create-credential.html @@ -27,12 +27,29 @@

Create Credential

-
- - Tag - - -
+ + Tags + + + {{tag}} + + + + + + + + {{tag}} + + +
@@ -44,7 +61,4 @@

Create Credential

-
- -
diff --git a/src/app/create-credential/create-credential.ts b/src/app/create-credential/create-credential.ts index 86f657c..7531f3b 100644 --- a/src/app/create-credential/create-credential.ts +++ b/src/app/create-credential/create-credential.ts @@ -1,7 +1,13 @@ +import { COMMA, ENTER } from '@angular/cdk/keycodes'; import { Component, ElementRef, ViewChild } from '@angular/core'; -import { NgForm } from '@angular/forms'; +import { FormControl, NgForm } from '@angular/forms'; +import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; +import { MatChipInputEvent } from '@angular/material/chips'; import { Router } from '@angular/router'; +import { Observable } from 'rxjs'; +import { map, startWith } from 'rxjs/operators'; import { v4 as uuidv4 } from 'uuid'; +import { Credential } from '../@types/Credential'; import { FileSystemService } from '../filesystem.service'; @Component({ @@ -12,18 +18,20 @@ import { FileSystemService } from '../filesystem.service'; export class CreateCredential { hide=true; loading=false; - - @ViewChild('falseDiv') - falseDiv!: ElementRef; - - triggerFalseClick() { - console.log("clicking") - let el: HTMLElement = this.falseDiv.nativeElement; - el.click(); - } + currTags: string[] = [] + availableTags: string[] = [] + filteredTags: Observable; + tagCtrl = new FormControl('') + readonly seperatorKeyCodes = [ENTER, COMMA] as const; + addOnBlur = true; + + @ViewChild('tagInput') tagInput: ElementRef | undefined; constructor(private router: Router, private fsService: FileSystemService){ - + this.filteredTags = this.tagCtrl.valueChanges.pipe( + startWith(null), + map((tag:string | null) => (tag ? this._filter(tag) : this.availableTags.slice())) + ) } ngOnDestroy() { @@ -32,26 +40,22 @@ export class CreateCredential { } ngOnInit() { - console.log("I init") + this.availableTags = history.state.data.tags + console.log("Tags: " + this.availableTags) } async save(form: NgForm){ - const title = form.value.title; - const username = form.value.username; - const password = form.value.password; - const url = form.value.url; - const tag = form.value.tag; - const id = uuidv4(); - - var obj = { - id: id, - title: title, - username: username, - password: password, - url: url, - tag: tag + + const newCred: Credential = { + id: uuidv4(), + title: form.value.title, + username: form.value.username, + password: form.value.password, + url: form.value.url, + tags: this.currTags } - this.fsService.saveCredential(obj).then(() => { + + this.fsService.saveCredential(newCred).then(() => { this.loading = false; this.router.navigate(['']); }) @@ -61,5 +65,46 @@ export class CreateCredential { cancel(){ this.router.navigate(['']); } + + addTag(event: MatChipInputEvent) { + const value = (event.value || '').trim(); + if(value) { this.currTags.push(value)} + event.chipInput!.clear() + this.tagCtrl.setValue(null) + } + + removeTag(tag: string){ + const index = this.currTags.indexOf(tag); + if(index >= 0) { this.currTags.splice(index, 1)} + + } + /* may be inlcuded later + editTag(tag: string, event: MatChipEditedEvent) { + const value = event.value.trim(); + + //Remove tag if it no longer has a name + if(!value) { + this.removeTag(tag); + } + + //Edit existing tag + const index = this.currTags.indexOf(tag); + if(index >= 0) { + this.currTags[index] = value + } + }*/ + selected(event: MatAutocompleteSelectedEvent) { + this.currTags.push(event.option.viewValue); + if(this.tagInput) this.tagInput.nativeElement.value = ''; + this.tagCtrl.setValue(null) + } + + private _filter(value:string): string[] { + console.log("Value to filter: " + value) + const filterValue = value.toLowerCase() + return this.availableTags.filter(tag => tag.toLowerCase().includes(filterValue)) + } + + } diff --git a/src/app/edit-credential/edit-credential.html b/src/app/edit-credential/edit-credential.html index 0e4a26d..09c71aa 100644 --- a/src/app/edit-credential/edit-credential.html +++ b/src/app/edit-credential/edit-credential.html @@ -29,10 +29,29 @@

-
- - Tag - +
+ + Tags + + + {{tag}} + + + + + + + + {{tag}} + +
diff --git a/src/app/edit-credential/edit-credential.ts b/src/app/edit-credential/edit-credential.ts index b1c1025..ea4ccac 100644 --- a/src/app/edit-credential/edit-credential.ts +++ b/src/app/edit-credential/edit-credential.ts @@ -1,6 +1,12 @@ -import { Component } from "@angular/core"; +import { COMMA, ENTER } from "@angular/cdk/keycodes"; +import { Component, ElementRef, ViewChild } from "@angular/core"; import { FormControl, FormGroup } from "@angular/forms"; +import { MatAutocompleteSelectedEvent } from "@angular/material/autocomplete"; +import { MatChipInputEvent } from "@angular/material/chips"; import { Router } from "@angular/router"; +import { Observable } from "rxjs/internal/Observable"; +import { map, startWith } from "rxjs/operators"; +import { Credential } from "../@types/Credential"; import { FileSystemService } from "../filesystem.service"; @Component({ @@ -16,23 +22,35 @@ export class EditCredential { title: new FormControl(), username: new FormControl(), password: new FormControl(), - url: new FormControl(), - tag: new FormControl() + url: new FormControl() }) - constructor(private router: Router, private fsService: FileSystemService){ + currTags: string[] = [] + availableTags: string[] = [] + filteredTags: Observable; + tagCtrl = new FormControl('') + readonly seperatorKeyCodes = [ENTER, COMMA] as const; + addOnBlur = true; + + @ViewChild('tagInput') tagInput: ElementRef | undefined; + constructor(private router: Router, private fsService: FileSystemService){ + this.filteredTags = this.tagCtrl.valueChanges.pipe( + startWith(null), + map((tag:string | null) => (tag ? this._filter(tag) : this.availableTags.slice())) + ) } ngOnInit() { const data = history.state.data; + this.currTags = data.tags; + this.availableTags = data.avTags this.editForm.setValue({ id: data.id, title: data.title, username: data.username, password: "", - url: data.url, - tag: data.tag + url: data.url }) this.fsService.loadPasswordById(data.id).then((pd: string) => { @@ -52,22 +70,45 @@ export class EditCredential { async edit(){ this.loading = true; - var obj = { + const editedCred: Credential = { id: this.editForm.get('id')?.value, title: this.editForm.get('title')?.value, username: this.editForm.get('username')?.value, password: this.editForm.get('password')?.value, url: this.editForm.get('url')?.value, - tag: this.editForm.get('tag')?.value + tags: this.currTags } - console.log(JSON.stringify(obj)) - this.fsService.editCredential(obj).then(()=> { + this.fsService.editCredential(editedCred).then(()=> { this.loading = false; this.router.navigate(['']) }) } + addTag(event: MatChipInputEvent) { + const value = (event.value || '').trim(); + if(value) { this.currTags.push(value)} + event.chipInput!.clear() + this.tagCtrl.setValue(null) + } + + removeTag(tag: string){ + const index = this.currTags.indexOf(tag); + if(index >= 0) { this.currTags.splice(index, 1)} + + } + + selected(event: MatAutocompleteSelectedEvent) { + this.currTags.push(event.option.viewValue); + if(this.tagInput) this.tagInput.nativeElement.value = ''; + this.tagCtrl.setValue(null) + } + + private _filter(value:string): string[] { + console.log("Value to filter: " + value) + const filterValue = value.toLowerCase() + return this.availableTags.filter(tag => tag.toLowerCase().includes(filterValue)) + } } diff --git a/src/app/filesystem.service.ts b/src/app/filesystem.service.ts index 6561b7b..fe8daac 100644 --- a/src/app/filesystem.service.ts +++ b/src/app/filesystem.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { Password } from './create-credential/Password'; +import { Credential } from './@types/Credential'; @Injectable({ @@ -12,7 +12,6 @@ export class FileSystemService { } - async loadPasswordById(id: string): Promise { return await window.electronAPI.loadPasswordById(id) .then((password:any) => { @@ -20,29 +19,32 @@ export class FileSystemService { }); } - async loadCrendentials(): Promise{ + async loadCrendentials(): Promise{ const creds = await window.electronAPI.loadCredentials() - let res: Password[] = []; - creds.forEach((cred:any) => { - const pCred: Password = { - id: cred.id, - title: cred.title, - username: cred.username, - password: cred.password, - url: cred.url, - tag: cred.tag - } - res.push(pCred); - }) + let res: Credential[] = []; + if(creds && creds.length > 0){ + creds.forEach((cred:any) => { + const cTags:string[] = (cred.tags ? cred.tags : []) + const pCred: Credential = { + id: cred.id, + title: cred.title, + username: cred.username, + password: cred.password, + url: cred.url, + tags: cTags + } + res.push(pCred); + }) + } return res; } - async editCredential(toUpdate: any): Promise { + async editCredential(toUpdate: Credential): Promise { return await window.electronAPI.editCredential(toUpdate) } - async saveCredential(newCred: any): Promise { + async saveCredential(newCred: Credential): Promise { return await window.electronAPI.saveCredential(newCred) } } diff --git a/src/app/table-passwords/table-passwords.html b/src/app/table-passwords/table-passwords.html index 78a1900..135bfdb 100644 --- a/src/app/table-passwords/table-passwords.html +++ b/src/app/table-passwords/table-passwords.html @@ -8,7 +8,7 @@

Tags

- + {{tag}} @@ -44,9 +44,9 @@

Tags

- - Tag - {{row.tag}} + + Tags + {{row.tags}} diff --git a/src/app/table-passwords/table-passwords.ts b/src/app/table-passwords/table-passwords.ts index 0b5150d..a0f3a78 100644 --- a/src/app/table-passwords/table-passwords.ts +++ b/src/app/table-passwords/table-passwords.ts @@ -2,7 +2,7 @@ import { Component, ViewChild } from '@angular/core'; import { MatSort } from '@angular/material/sort'; import { MatTableDataSource } from '@angular/material/table'; import { Router } from '@angular/router'; -import { Password } from '../create-credential/Password'; +import { Credential } from '../@types/Credential'; import { FileSystemService } from '../filesystem.service'; @@ -12,12 +12,10 @@ import { FileSystemService } from '../filesystem.service'; templateUrl: 'table-passwords.html' }) export class TablePassword { - displayedColumns=['title', 'username', 'url', 'tag']; - dataSource: MatTableDataSource; + displayedColumns=['title', 'username', 'url', 'tags']; + dataSource: MatTableDataSource; selectedChips: string[] = []; - tags= ['music', 'Games', 'Streaming', 'Entertainment']; - currView: string = 'main'; - isMain: boolean = true + availableTags: string[] = [] currSearchFilter: string = ''; @ViewChild(MatSort) @@ -26,7 +24,7 @@ export class TablePassword { constructor(private fsService: FileSystemService, private router: Router) { - const passwords: Password[] = [] + const passwords: Credential[] = [] this.dataSource=new MatTableDataSource(passwords); this.dataSource.filterPredicate = this.getFilterPredicate(); this.loadCredentials(); @@ -66,12 +64,13 @@ export class TablePassword { } } getFilterPredicate(){ - return (data: Password, filter: string) => { + return (data: Credential, filter: string) => { //if no term inserted if(filter === 'empty'){ if(this.selectedChips.length === 0) return true; - return checkForTags(this.selectedChips, data.tag) + //return checkForTags(this.selectedChips, data.tag) + return true } const matchFilter = [] @@ -91,29 +90,46 @@ export class TablePassword { if(this.selectedChips.length === 0) { return matchStrings } - return checkForTags(this.selectedChips, data.tag) && matchStrings; + //return checkForTags(this.selectedChips, data.tag) && matchStrings; + return true } } loadCredentials() { - this.fsService.loadCrendentials().then((data: Password[]) => { + this.fsService.loadCrendentials().then((data: Credential[]) => { + this.availableTags = Array.from(extractTags(data)); this.dataSource.data = data; }) } showCreateForm() { - this.router.navigate(['/create-credential']); + this.router.navigate(['/create-credential'], { + state: {data: {tags: this.availableTags}} + }); } - editCred(row: Password){ - this.router.navigate(['/edit-credential'], {state: - {data: {id: row.id, title: row.title, username: row.username, url: row.url, tag: row.tag} - }}); + editCred(row: Credential){ + this.router.navigate(['/edit-credential'], {state: + {data: {id: row.id, title: row.title, username: row.username, url: row.url, tags: row.tags, avTags: this.availableTags} + }}); } } + function checkForTags(selectedChips: string[], tag: string) { return selectedChips.includes(tag) } +function extractTags(data: Credential[]): Set{ + let setOfTags = new Set(); + Array.prototype.forEach.call(data, cred => { + for(let i = 0; i < cred.tags.length; i++){ + setOfTags.add(cred.tags[i]) + } + }) + return setOfTags +} + + + diff --git a/storage.json b/storage.json index 4831780..3d015df 100644 --- a/storage.json +++ b/storage.json @@ -1,26 +1,34 @@ [ { - "id": "179a5e38-6c36-4bb4-ab72-f390c81b1bee", + "id": "afe4b6df-a878-4035-af50-8690d541aa9e", "title": "Netflix", - "username": "mert", + "username": "jakob", "password": "nfsu", "url": "netflix.com", - "tag": "Streaming" + "tags": [ + "Streaming", + "Entertainment", + "Activity" + ] }, { - "id": "7199e1ce-bea4-48d7-ae54-fae77d385aca", - "title": "LoL", - "username": "mert", - "password": "nfsu", - "url": "lol.com", - "tag": "Games" + "id": "7141b943-505b-4063-92f3-d05cef59832b", + "title": "Spotify", + "username": "mer", + "password": "qbtt", + "url": "spot.com", + "tags": [] }, { - "id": "4e355c7e-d739-4a27-abd5-2b58251b0bc3", - "title": "Amazon", + "id": "23985983-ee5a-4d45-af2c-3a802041fcba", + "title": "FHV", "username": "mert", - "password": "nfsu", - "url": "amazon.com", - "tag": "Streaming" + "password": "pnf", + "url": "fhv.at", + "tags": [ + "Streaming", + "Entertainment", + "University" + ] } ] \ No newline at end of file From 6cea36388652358ccea29e0c29543de8eca5fc36 Mon Sep 17 00:00:00 2001 From: xBlade58 Date: Sat, 21 Jan 2023 11:37:58 +0100 Subject: [PATCH 4/5] Filter by multiple tags --- .../create-credential/create-credential.ts | 1 - src/app/edit-credential/edit-credential.ts | 1 - src/app/table-passwords/table-passwords.ts | 11 ++--- storage.json | 48 +++++++++++-------- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/app/create-credential/create-credential.ts b/src/app/create-credential/create-credential.ts index 7531f3b..998ab91 100644 --- a/src/app/create-credential/create-credential.ts +++ b/src/app/create-credential/create-credential.ts @@ -100,7 +100,6 @@ export class CreateCredential { } private _filter(value:string): string[] { - console.log("Value to filter: " + value) const filterValue = value.toLowerCase() return this.availableTags.filter(tag => tag.toLowerCase().includes(filterValue)) } diff --git a/src/app/edit-credential/edit-credential.ts b/src/app/edit-credential/edit-credential.ts index ea4ccac..f6e1997 100644 --- a/src/app/edit-credential/edit-credential.ts +++ b/src/app/edit-credential/edit-credential.ts @@ -105,7 +105,6 @@ export class EditCredential { } private _filter(value:string): string[] { - console.log("Value to filter: " + value) const filterValue = value.toLowerCase() return this.availableTags.filter(tag => tag.toLowerCase().includes(filterValue)) } diff --git a/src/app/table-passwords/table-passwords.ts b/src/app/table-passwords/table-passwords.ts index a0f3a78..8e20f2b 100644 --- a/src/app/table-passwords/table-passwords.ts +++ b/src/app/table-passwords/table-passwords.ts @@ -69,8 +69,7 @@ export class TablePassword { //if no term inserted if(filter === 'empty'){ if(this.selectedChips.length === 0) return true; - //return checkForTags(this.selectedChips, data.tag) - return true + return checkForTags(this.selectedChips, data.tags) } const matchFilter = [] @@ -90,8 +89,7 @@ export class TablePassword { if(this.selectedChips.length === 0) { return matchStrings } - //return checkForTags(this.selectedChips, data.tag) && matchStrings; - return true + return checkForTags(this.selectedChips, data.tags) && matchStrings; } } @@ -117,8 +115,9 @@ export class TablePassword { } -function checkForTags(selectedChips: string[], tag: string) { - return selectedChips.includes(tag) +function checkForTags(selectedChips: string[], credTags: string[]) { + const hasTag = credTags.some(t => selectedChips.includes(t)) + return hasTag } function extractTags(data: Credential[]): Set{ diff --git a/storage.json b/storage.json index 3d015df..7ee7087 100644 --- a/storage.json +++ b/storage.json @@ -1,34 +1,44 @@ [ { - "id": "afe4b6df-a878-4035-af50-8690d541aa9e", + "id": "6836db0d-a69d-4bbf-ade7-0664fb4b270b", "title": "Netflix", - "username": "jakob", - "password": "nfsu", - "url": "netflix.com", + "username": "Jakob Feistenauer", + "password": "nbjo", + "url": "https://netflix.com", "tags": [ - "Streaming", - "Entertainment", - "Activity" + "Streaming" + ] + }, + { + "id": "fa7eb6fe-8861-425c-9642-8bbf6dbb64d1", + "title": "Amazon", + "username": "mert58", + "password": "uftuLMN", + "url": "https://amazon.com", + "tags": [ + "Shopping", + "Streaming" ] }, { - "id": "7141b943-505b-4063-92f3-d05cef59832b", + "id": "c8c8d2f9-f4d4-4e0d-a1ce-a48d0c1ba1bb", "title": "Spotify", - "username": "mer", - "password": "qbtt", - "url": "spot.com", - "tags": [] + "username": "Jaypan", + "password": "kbz", + "url": "https://spotify.com", + "tags": [ + "Streaming", + "Music" + ] }, { - "id": "23985983-ee5a-4d45-af2c-3a802041fcba", - "title": "FHV", + "id": "f2ffb3f9-40ca-4e29-b4f5-14a87df62d17", + "title": "LoL", "username": "mert", - "password": "pnf", - "url": "fhv.at", + "password": "kbz", + "url": "LeagueOfLegends.de", "tags": [ - "Streaming", - "Entertainment", - "University" + "Games" ] } ] \ No newline at end of file From 814cb87c6ef4f5e66735c02d6e0a496b308cea21 Mon Sep 17 00:00:00 2001 From: xBlade58 Date: Sat, 21 Jan 2023 14:18:58 +0100 Subject: [PATCH 5/5] View filter-tags vertically --- .../create-credential/create-credential.html | 2 +- src/app/create-credential/create-credential.ts | 18 ++---------------- src/app/table-passwords/table-passwords.html | 4 ++-- 3 files changed, 5 insertions(+), 19 deletions(-) diff --git a/src/app/create-credential/create-credential.html b/src/app/create-credential/create-credential.html index 7632118..0cd1b52 100644 --- a/src/app/create-credential/create-credential.html +++ b/src/app/create-credential/create-credential.html @@ -42,7 +42,7 @@

Create Credential

+ [matChipInputAddOnBlur]="true" (matChipInputTokenEnd)="addTag($event)"/> diff --git a/src/app/create-credential/create-credential.ts b/src/app/create-credential/create-credential.ts index 998ab91..7fc1cc8 100644 --- a/src/app/create-credential/create-credential.ts +++ b/src/app/create-credential/create-credential.ts @@ -78,24 +78,10 @@ export class CreateCredential { if(index >= 0) { this.currTags.splice(index, 1)} } - /* may be inlcuded later - editTag(tag: string, event: MatChipEditedEvent) { - const value = event.value.trim(); - - //Remove tag if it no longer has a name - if(!value) { - this.removeTag(tag); - } - - //Edit existing tag - const index = this.currTags.indexOf(tag); - if(index >= 0) { - this.currTags[index] = value - } - }*/ + selected(event: MatAutocompleteSelectedEvent) { this.currTags.push(event.option.viewValue); - if(this.tagInput) this.tagInput.nativeElement.value = ''; + this.tagInput!.nativeElement.value = ''; this.tagCtrl.setValue(null) } diff --git a/src/app/table-passwords/table-passwords.html b/src/app/table-passwords/table-passwords.html index 135bfdb..1eb31c0 100644 --- a/src/app/table-passwords/table-passwords.html +++ b/src/app/table-passwords/table-passwords.html @@ -7,8 +7,8 @@

Tags

- - + + {{tag}}