Skip to content

Commit

Permalink
Merge pull request #7 from xBlade58/feature/filtering
Browse files Browse the repository at this point in the history
Add Filtering by multiple Tags
  • Loading branch information
yescob authored Jan 21, 2023
2 parents 3275c4f + d9e6fbb commit 5d82f7b
Show file tree
Hide file tree
Showing 13 changed files with 308 additions and 139 deletions.
12 changes: 12 additions & 0 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ function createWindow () {
slashes: true
})
);
mainWindow.webContents.openDevTools();

mainWindow.on('closed', function () {
mainWindow = null
Expand All @@ -37,6 +38,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()
})

Expand Down Expand Up @@ -94,4 +96,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
})
}


Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
export interface Password {

export interface Credential {
id: string,
title: string;
username: string;
password: string
url: string;
tag: string
tags: string[]
}
7 changes: 5 additions & 2 deletions src/app/@types/renderer.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Credential } from "./Credential"

export interface IElectronAPI {
saveCredential: (data:any) => Promise<void>,
editCredential: (toUpdate:any) => Promise<void>,
deleteCredentialById: (id:string) => Promise<void>,
saveCredential: (data:Credential) => Promise<void>,
editCredential: (toUpdate:Credential) => Promise<void>,
loadCredentials: () => Promise<any>,
loadPasswordById: (id:string) => Promise<string>
}
Expand Down
4 changes: 3 additions & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand All @@ -36,7 +37,8 @@ import { CreateCredential } from './create-credential/create-credential';
MatIconModule,
FormsModule,
MatProgressSpinnerModule,
ReactiveFormsModule
ReactiveFormsModule,
MatAutocompleteModule
],
exports: [
MatFormFieldModule,
Expand Down
32 changes: 23 additions & 9 deletions src/app/create-credential/create-credential.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,29 @@ <h1>Create Credential</h1>
<input matInput required ngModel name="url">
</mat-form-field>
</div>
<div #falseDiv>
<mat-form-field class="field">
<mat-label>Tag</mat-label>
<input matInput required ngModel name="tag">
</mat-form-field>
</div>
<mat-form-field class="field" appearance="fill">
<mat-label>Tags</mat-label>
<mat-chip-grid #chipGrid>
<mat-chip-row
*ngFor="let tag of currTags"
(removed)="removeTag(tag)"
[editable]="false">
{{tag}}
<button matChipRemove>
<mat-icon>cancel</mat-icon>
</button>
</mat-chip-row>
</mat-chip-grid>
<input name="tag" placeholder="New Tag..." #tagInput [formControl]="tagCtrl"
[matChipInputFor]="chipGrid" [matAutocomplete]="auto" [matChipInputSeparatorKeyCodes]="seperatorKeyCodes"
[matChipInputAddOnBlur]="true" (matChipInputTokenEnd)="addTag($event)"/>

<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">
<mat-option *ngFor="let tag of filteredTags | async" [value]="tag">
{{tag}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<div>
<button type="submit" (click)="save(createCredForm)">Save</button>
<button (click)="cancel()">Cancel</button>
Expand All @@ -44,7 +61,4 @@ <h1>Create Credential</h1>


</div>
<div>

</div>

84 changes: 57 additions & 27 deletions src/app/create-credential/create-credential.ts
Original file line number Diff line number Diff line change
@@ -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({
Expand All @@ -12,18 +18,20 @@ import { FileSystemService } from '../filesystem.service';
export class CreateCredential {
hide=true;
loading=false;

@ViewChild('falseDiv')
falseDiv!: ElementRef<HTMLElement>;

triggerFalseClick() {
console.log("clicking")
let el: HTMLElement = this.falseDiv.nativeElement;
el.click();
}
currTags: string[] = []
availableTags: string[] = []
filteredTags: Observable<string[]>;
tagCtrl = new FormControl('')
readonly seperatorKeyCodes = [ENTER, COMMA] as const;
addOnBlur = true;

@ViewChild('tagInput') tagInput: ElementRef<HTMLInputElement> | 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() {
Expand All @@ -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(['']);
})
Expand All @@ -61,5 +65,31 @@ 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)}

}

selected(event: MatAutocompleteSelectedEvent) {
this.currTags.push(event.option.viewValue);
this.tagInput!.nativeElement.value = '';
this.tagCtrl.setValue(null)
}

private _filter(value:string): string[] {
const filterValue = value.toLowerCase()
return this.availableTags.filter(tag => tag.toLowerCase().includes(filterValue))
}


}

28 changes: 24 additions & 4 deletions src/app/edit-credential/edit-credential.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,35 @@ <h1>
<input matInput required ngModel name="url">
</mat-form-field>
</div>
<div #falseDiv>
<mat-form-field class="field">
<mat-label>Tag</mat-label>
<input matInput required ngModel name="tag">
<div>
<mat-form-field class="field" appearance="fill">
<mat-label>Tags</mat-label>
<mat-chip-grid #chipGrid>
<mat-chip-row
*ngFor="let tag of currTags"
(removed)="removeTag(tag)"
[editable]="false">
{{tag}}
<button matChipRemove>
<mat-icon>cancel</mat-icon>
</button>
</mat-chip-row>
</mat-chip-grid>
<input required name="tag" placeholder="New Tag..." #tagInput [formControl]="tagCtrl"
[matChipInputFor]="chipGrid" [matAutocomplete]="auto" [matChipInputSeparatorKeyCodes]="seperatorKeyCodes"
[matChipInputAddOnBlur]="addOnBlur" (matChipInputTokenEnd)="addTag($event)"/>

<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">
<mat-option *ngFor="let tag of filteredTags | async" [value]="tag">
{{tag}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</div>
<div>
<button type="submit" (click)="edit()">Save</button>
<button (click)="cancel()">Cancel</button>
<button (click)="delete()">Delete</button>
</div>
</form>
<div *ngIf='loading'>
Expand Down
69 changes: 59 additions & 10 deletions src/app/edit-credential/edit-credential.ts
Original file line number Diff line number Diff line change
@@ -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({
Expand All @@ -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<string[]>;
tagCtrl = new FormControl('')
readonly seperatorKeyCodes = [ENTER, COMMA] as const;
addOnBlur = true;

@ViewChild('tagInput') tagInput: ElementRef<HTMLInputElement> | 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) => {
Expand All @@ -50,24 +68,55 @@ 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 = {
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[] {
const filterValue = value.toLowerCase()
return this.availableTags.filter(tag => tag.toLowerCase().includes(filterValue))
}
}


Loading

0 comments on commit 5d82f7b

Please sign in to comment.