Cleaned up the code a bit and some UX

This commit is contained in:
Joseph Milazzo 2020-12-20 18:02:57 -06:00
parent 2c0921acc6
commit b47d2acac8
10 changed files with 73 additions and 20 deletions

View file

@ -5,5 +5,5 @@ export interface Member {
lastActive: string; // datetime lastActive: string; // datetime
created: string; // datetime created: string; // datetime
isAdmin: boolean; isAdmin: boolean;
libraries?: Library[]; libraries: Library[];
} }

View file

@ -11,6 +11,7 @@ import { User } from '../_models/user';
export class AccountService { export class AccountService {
baseUrl = environment.apiUrl; baseUrl = environment.apiUrl;
userKey = 'kavita-user';
// Stores values, when someone subscribes gives (1) of last values seen. // Stores values, when someone subscribes gives (1) of last values seen.
private currentUserSource = new ReplaySubject<User>(1); private currentUserSource = new ReplaySubject<User>(1);
@ -31,12 +32,12 @@ export class AccountService {
} }
setCurrentUser(user: User) { setCurrentUser(user: User) {
localStorage.setItem('user', JSON.stringify(user)); localStorage.setItem(this.userKey, JSON.stringify(user));
this.currentUserSource.next(user); this.currentUserSource.next(user);
} }
logout() { logout() {
localStorage.removeItem('user'); localStorage.removeItem(this.userKey);
this.currentUserSource.next(undefined); this.currentUserSource.next(undefined);
} }

View file

@ -29,4 +29,9 @@ export class LibraryService {
return this.httpClient.get<Library[]>(this.baseUrl + 'library/' + username); return this.httpClient.get<Library[]>(this.baseUrl + 'library/' + username);
} }
updateLibrariesForMember(username: string, selectedLibraries: Library[]) {
return this.httpClient.post(this.baseUrl + '/library/update-for', {username, selectedLibraries});
}
} }

View file

@ -7,16 +7,17 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="list-group"> <div class="list-group">
<li class="list-group-item"> <li class="list-group-item" *ngFor="let library of selectedLibraries; let i = index">
<div class="form-check"> <div class="form-check">
<input id="library1" type="checkbox" aria-label="Library 1" class="form-check-input"> <input id="library-{{i}}" type="checkbox" attr.aria-label="Library {{library.data.name}}" class="form-check-input"
<label for="library1" class="form-check-label">Library 1</label> [(ngModel)]="library.selected" name="library">
<label attr.for="library-{{i}}" class="form-check-label">{{library.data.name}}</label>
</div> </div>
</li> </li>
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-light" (click)="reset()">Cancel</button> <button type="button" class="btn btn-light" (click)="reset()">Reset</button>
<button type="button" class="btn btn-secondary" (click)="close()">Cancel</button> <button type="button" class="btn btn-secondary" (click)="close()">Cancel</button>
<button type="button" class="btn btn-primary" (click)="save()">Save</button> <button type="button" class="btn btn-primary" (click)="save()">Save</button>
</div> </div>

View file

@ -13,13 +13,26 @@ import { LibraryService } from 'src/app/_services/library.service';
export class LibraryAccessModalComponent implements OnInit { export class LibraryAccessModalComponent implements OnInit {
@Input() member: Member | undefined; @Input() member: Member | undefined;
libraries: Library[] = []; allLibraries: Library[] = [];
selectedLibraries: Array<{selected: boolean, data: Library}> = [];
constructor(public modal: NgbActiveModal, private libraryService: LibraryService, private fb: FormBuilder) { } constructor(public modal: NgbActiveModal, private libraryService: LibraryService, private fb: FormBuilder) { }
ngOnInit(): void { ngOnInit(): void {
this.libraryService.getLibrariesForMember(this.member?.username + '').subscribe(libs => { this.libraryService.getLibraries().subscribe(libs => {
this.libraries = libs; this.allLibraries = libs;
this.selectedLibraries = libs.map(item => {
return {selected: false, data: item};
});
if (this.member !== undefined) {
this.member.libraries.forEach(lib => {
const foundLibrary = this.selectedLibraries.filter(item => item.data.name === lib.name);
if (foundLibrary.length > 0) {
foundLibrary[0].selected = true;
}
});
}
}); });
} }
@ -28,11 +41,29 @@ export class LibraryAccessModalComponent implements OnInit {
} }
save() { save() {
if (this.member?.username === undefined) {
return;
}
this.libraryService.updateLibrariesForMember(this.member?.username, this.selectedLibraries.map(item => item.data)).subscribe(() => {
this.modal.close();
});
} }
reset() { reset() {
this.selectedLibraries = this.allLibraries.map(item => {
return {selected: false, data: item};
});
if (this.member !== undefined) {
this.member.libraries.forEach(lib => {
const foundLibrary = this.selectedLibraries.filter(item => item.data.name === lib.name);
if (foundLibrary.length > 0) {
foundLibrary[0].selected = true;
}
});
}
} }
} }

View file

@ -9,6 +9,7 @@ import { LibraryEditorModalComponent } from './_modals/library-editor-modal/libr
import { SharedModule } from '../shared/shared.module'; import { SharedModule } from '../shared/shared.module';
import { LibraryAccessModalComponent } from './_modals/library-access-modal/library-access-modal.component'; import { LibraryAccessModalComponent } from './_modals/library-access-modal/library-access-modal.component';
import { DirectoryPickerComponent } from './_modals/directory-picker/directory-picker.component'; import { DirectoryPickerComponent } from './_modals/directory-picker/directory-picker.component';
import { FormsModule } from '@angular/forms';
@ -25,7 +26,8 @@ import { DirectoryPickerComponent } from './_modals/directory-picker/directory-p
CommonModule, CommonModule,
AdminRoutingModule, AdminRoutingModule,
NgbNavModule, NgbNavModule,
SharedModule SharedModule,
FormsModule
], ],
providers: [] providers: []
}) })

View file

@ -7,11 +7,17 @@
<li *ngFor="let library of libraries" class="list-group-item"> <li *ngFor="let library of libraries" class="list-group-item">
<!-- We can move this into a view-member component --> <!-- We can move this into a view-member component -->
<div> <div>
<div>{{library.name}}</div> <h4>
{{library.name | titlecase}}
<div class="pull-right">
<button class="btn btn-danger mr-2 btn-sm"><i class="fa fa-trash" title="Delete {{library.name | titlecase}}"></i></button>
<button class="btn btn-primary btn-sm" ><i class="fa fa-pencil" title="Edit {{library.name | titlecase}}"></i></button>
</div>
</h4>
<!-- <div>Last Active: {{member.lastActive | date}}</div>
<div *ngIf="!member.isAdmin">Sharing: {{member?.libraries ? member?.libraries : 'None'}}</div> -->
</div> </div>
<!-- <button class="btn btn-primary pull-right" *ngIf="canEditMember(member)">Edit</button> -->
</li> </li>
</ul> </ul>
<ng-template #createLibrary> <ng-template #createLibrary>

View file

@ -12,13 +12,12 @@
<h4> <h4>
{{member.username | titlecase}} <span *ngIf="member.isAdmin" class="badge badge-pill badge-secondary">Admin</span> {{member.username | titlecase}} <span *ngIf="member.isAdmin" class="badge badge-pill badge-secondary">Admin</span>
<div class="pull-right" *ngIf="canEditMember(member)"> <div class="pull-right" *ngIf="canEditMember(member)">
<button class="btn btn-danger">Delete</button> <button class="btn btn-danger mr-2"><i class="fa fa-trash" title="Delete {{member.username | titlecase}}"></i></button>
<button class="btn btn-primary" (click)="openEditLibraryAccess(member)">Edit</button> <button class="btn btn-primary" (click)="openEditLibraryAccess(member)"><i class="fa fa-pencil" title="Edit {{member.username | titlecase}}"></i></button>
</div> </div>
</h4> </h4>
<div>Last Active: {{member.lastActive | date}}</div> <div>Last Active: {{member.lastActive | date}}</div>
<div *ngIf="!member.isAdmin">Sharing: {{member?.libraries ? member?.libraries : 'None'}}</div> <div *ngIf="!member.isAdmin">Sharing: {{formatLibraries(member)}}</div>
</div> </div>

View file

@ -56,4 +56,12 @@ export class ManageUsersComponent implements OnInit {
console.log('Closed Result', closeResult); console.log('Closed Result', closeResult);
}); });
} }
formatLibraries(member: Member) {
if (member.libraries.length === 0) {
return 'None';
}
return member.libraries.map(item => item.name + ', ');
}
} }

View file

@ -17,8 +17,8 @@ export class AppComponent implements OnInit {
setCurrentUser() { setCurrentUser() {
const userString = localStorage.getItem('user'); const userString = localStorage.getItem(this.accountService.userKey);
if (userString !== '' || localStorage.getItem('user') !== undefined) { if (userString !== '' || localStorage.getItem(this.accountService.userKey) !== undefined) {
const user: User = JSON.parse(userString + ''); const user: User = JSON.parse(userString + '');
this.accountService.setCurrentUser(user); this.accountService.setCurrentUser(user);
} }