- {{member.username | titlecase}} Admin
+ {{member.username | titlecase}} Admin
diff --git a/UI/Web/src/app/admin/manage-users/manage-users.component.scss b/UI/Web/src/app/admin/manage-users/manage-users.component.scss
index e69de29bb..04f1c6b73 100644
--- a/UI/Web/src/app/admin/manage-users/manage-users.component.scss
+++ b/UI/Web/src/app/admin/manage-users/manage-users.component.scss
@@ -0,0 +1,3 @@
+.presence {
+ font-size: 12px;
+}
\ No newline at end of file
diff --git a/UI/Web/src/app/admin/manage-users/manage-users.component.ts b/UI/Web/src/app/admin/manage-users/manage-users.component.ts
index 15078cce1..f54967540 100644
--- a/UI/Web/src/app/admin/manage-users/manage-users.component.ts
+++ b/UI/Web/src/app/admin/manage-users/manage-users.component.ts
@@ -1,6 +1,6 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, OnDestroy, OnInit } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
-import { take } from 'rxjs/operators';
+import { take, takeUntil } from 'rxjs/operators';
import { MemberService } from 'src/app/_services/member.service';
import { Member } from 'src/app/_models/member';
import { User } from 'src/app/_models/user';
@@ -10,13 +10,15 @@ import { ToastrService } from 'ngx-toastr';
import { ResetPasswordModalComponent } from '../_modals/reset-password-modal/reset-password-modal.component';
import { ConfirmService } from 'src/app/shared/confirm.service';
import { EditRbsModalComponent } from '../_modals/edit-rbs-modal/edit-rbs-modal.component';
+import { PresenceHubService } from 'src/app/_services/presence-hub.service';
+import { Subject } from 'rxjs';
@Component({
selector: 'app-manage-users',
templateUrl: './manage-users.component.html',
styleUrls: ['./manage-users.component.scss']
})
-export class ManageUsersComponent implements OnInit {
+export class ManageUsersComponent implements OnInit, OnDestroy {
members: Member[] = [];
loggedInUsername = '';
@@ -25,20 +27,29 @@ export class ManageUsersComponent implements OnInit {
createMemberToggle = false;
loadingMembers = false;
+ private onDestroy = new Subject();
+
constructor(private memberService: MemberService,
private accountService: AccountService,
private modalService: NgbModal,
private toastr: ToastrService,
- private confirmService: ConfirmService) {
+ private confirmService: ConfirmService,
+ public presence: PresenceHubService) {
this.accountService.currentUser$.pipe(take(1)).subscribe((user: User) => {
this.loggedInUsername = user.username;
});
+
}
ngOnInit(): void {
this.loadMembers();
}
+ ngOnDestroy() {
+ this.onDestroy.next();
+ this.onDestroy.complete();
+ }
+
loadMembers() {
this.loadingMembers = true;
this.memberService.getMembers().subscribe(members => {
diff --git a/UI/Web/src/app/all-collections/all-collections.component.ts b/UI/Web/src/app/all-collections/all-collections.component.ts
index ddd4b6407..b05e01a04 100644
--- a/UI/Web/src/app/all-collections/all-collections.component.ts
+++ b/UI/Web/src/app/all-collections/all-collections.component.ts
@@ -69,7 +69,6 @@ export class AllCollectionsComponent implements OnInit {
}
loadPage() {
- // TODO: See if we can move this pagination code into layout code
const page = this.route.snapshot.queryParamMap.get('page');
if (page != null) {
if (this.seriesPagination === undefined || this.seriesPagination === null) {
diff --git a/UI/Web/src/app/app.component.ts b/UI/Web/src/app/app.component.ts
index b406619f2..f2241df40 100644
--- a/UI/Web/src/app/app.component.ts
+++ b/UI/Web/src/app/app.component.ts
@@ -1,6 +1,10 @@
import { Component, OnInit } from '@angular/core';
+import { take } from 'rxjs/operators';
import { AccountService } from './_services/account.service';
+import { LibraryService } from './_services/library.service';
+import { MessageHubService } from './_services/message-hub.service';
import { NavService } from './_services/nav.service';
+import { PresenceHubService } from './_services/presence-hub.service';
import { StatsService } from './_services/stats.service';
@Component({
@@ -10,7 +14,9 @@ import { StatsService } from './_services/stats.service';
})
export class AppComponent implements OnInit {
- constructor(private accountService: AccountService, public navService: NavService, private statsService: StatsService) { }
+ constructor(private accountService: AccountService, public navService: NavService,
+ private statsService: StatsService, private messageHub: MessageHubService,
+ private presenceHub: PresenceHubService, private libraryService: LibraryService) { }
ngOnInit(): void {
this.setCurrentUser();
@@ -28,6 +34,9 @@ export class AppComponent implements OnInit {
if (user) {
this.navService.setDarkMode(user.preferences.siteDarkMode);
+ this.messageHub.createHubConnection(user);
+ this.presenceHub.createHubConnection(user);
+ this.libraryService.getLibraryNames().pipe(take(1)).subscribe(() => {/* No Operation */});
} else {
this.navService.setDarkMode(true);
}
diff --git a/UI/Web/src/app/carousel/carousel-reel/carousel-reel.component.ts b/UI/Web/src/app/carousel/carousel-reel/carousel-reel.component.ts
index 372fed44f..59f84271f 100644
--- a/UI/Web/src/app/carousel/carousel-reel/carousel-reel.component.ts
+++ b/UI/Web/src/app/carousel/carousel-reel/carousel-reel.component.ts
@@ -15,8 +15,11 @@ export class CarouselReelComponent implements OnInit {
swiper!: Swiper;
+ trackByIdentity: (index: number, item: any) => string;
- constructor() { }
+ constructor() {
+ this.trackByIdentity = (index: number, item: any) => `${this.title}_${item.id}_${item?.name}_${item?.pagesRead}_${index}`;
+ }
ngOnInit(): void {}
diff --git a/UI/Web/src/app/library/library.component.ts b/UI/Web/src/app/library/library.component.ts
index ea51ed429..ce0c03a47 100644
--- a/UI/Web/src/app/library/library.component.ts
+++ b/UI/Web/src/app/library/library.component.ts
@@ -49,7 +49,7 @@ export class LibraryComponent implements OnInit, OnDestroy {
this.accountService.currentUser$.pipe(take(1)).subscribe(user => {
this.user = user;
this.isAdmin = this.accountService.hasAdminRole(this.user);
- this.libraryService.getLibrariesForMember().subscribe(libraries => {
+ this.libraryService.getLibrariesForMember().pipe(take(1)).subscribe(libraries => {
this.libraries = libraries;
this.isLoading = false;
});
@@ -81,8 +81,9 @@ export class LibraryComponent implements OnInit, OnDestroy {
if (series === true || series === false) {
if (!series) {return;}
}
-
- if ((series as Series).pagesRead !== (series as Series).pages && (series as Series).pagesRead !== 0) {
+ // If the update to Series doesn't affect the requirement to be in this stream, then ignore update request
+ const seriesObj = (series as Series);
+ if (seriesObj.pagesRead !== seriesObj.pages && seriesObj.pagesRead !== 0) {
return;
}
diff --git a/UI/Web/src/app/shared/_services/dom-helper.service.ts b/UI/Web/src/app/shared/_services/dom-helper.service.ts
index 0f0344b5f..22aa1adf3 100644
--- a/UI/Web/src/app/shared/_services/dom-helper.service.ts
+++ b/UI/Web/src/app/shared/_services/dom-helper.service.ts
@@ -65,7 +65,7 @@ export class DomHelperService {
if (tagName === 'A' || tagName === 'AREA') {
return (el.attributes.getNamedItem('href') !== '');
}
- return !el.attributes.hasOwnProperty('disabled'); // TODO: check for cases when: disabled="true" and disabled="false"
+ return !el.attributes.hasOwnProperty('disabled'); // check for cases when: disabled="true" and disabled="false"
}
return false;
}
diff --git a/UI/Web/src/app/shared/card-detail-layout/card-detail-layout.component.html b/UI/Web/src/app/shared/card-detail-layout/card-detail-layout.component.html
index 4520816d2..d005bab63 100644
--- a/UI/Web/src/app/shared/card-detail-layout/card-detail-layout.component.html
+++ b/UI/Web/src/app/shared/card-detail-layout/card-detail-layout.component.html
@@ -10,7 +10,7 @@
-