Dashboard Customization Polish (#2295)
This commit is contained in:
parent
25e759d301
commit
25ffb2ffe1
42 changed files with 255 additions and 258 deletions
|
|
@ -120,7 +120,6 @@ export class AccountService {
|
|||
const user = response;
|
||||
if (user) {
|
||||
this.setCurrentUser(user);
|
||||
this.messageHub.createHubConnection(user, this.hasAdminRole(user));
|
||||
}
|
||||
}),
|
||||
takeUntilDestroyed(this.destroyRef)
|
||||
|
|
@ -150,7 +149,8 @@ export class AccountService {
|
|||
this.stopRefreshTokenTimer();
|
||||
|
||||
if (this.currentUser) {
|
||||
this.messageHub.createHubConnection(this.currentUser, this.hasAdminRole(this.currentUser));
|
||||
this.messageHub.stopHubConnection();
|
||||
this.messageHub.createHubConnection(this.currentUser);
|
||||
this.hasValidLicense().subscribe();
|
||||
this.startRefreshTokenTimer();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,8 +114,6 @@ export class MessageHubService {
|
|||
*/
|
||||
public onlineUsers$ = this.onlineUsersSource.asObservable();
|
||||
|
||||
isAdmin: boolean = false;
|
||||
|
||||
constructor() {}
|
||||
|
||||
/**
|
||||
|
|
@ -132,9 +130,7 @@ export class MessageHubService {
|
|||
return event.event === eventType;
|
||||
}
|
||||
|
||||
createHubConnection(user: User, isAdmin: boolean) {
|
||||
this.isAdmin = isAdmin;
|
||||
|
||||
createHubConnection(user: User) {
|
||||
this.hubConnection = new HubConnectionBuilder()
|
||||
.withUrl(this.hubUrl + 'messages', {
|
||||
accessTokenFactory: () => user.token
|
||||
|
|
@ -186,7 +182,6 @@ export class MessageHubService {
|
|||
});
|
||||
|
||||
this.hubConnection.on(EVENTS.DashboardUpdate, resp => {
|
||||
console.log('dashboard update event came in')
|
||||
this.messagesSource.next({
|
||||
event: EVENTS.DashboardUpdate,
|
||||
payload: resp.body as DashboardUpdateEvent
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ export class LicenseComponent implements OnInit {
|
|||
}
|
||||
|
||||
async deleteLicense() {
|
||||
if (!await this.confirmService.confirm(translate('k+-delete-key'))) {
|
||||
if (!await this.confirmService.confirm(translate('toasts.k+-delete-key'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import {ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, injec
|
|||
import {Title} from '@angular/platform-browser';
|
||||
import {Router, RouterLink} from '@angular/router';
|
||||
import {Observable, of, ReplaySubject, Subject, switchMap} from 'rxjs';
|
||||
import {map, shareReplay, take, tap, throttleTime} from 'rxjs/operators';
|
||||
import {debounceTime, map, shareReplay, take, tap, throttleTime} from 'rxjs/operators';
|
||||
import {FilterUtilitiesService} from 'src/app/shared/_services/filter-utilities.service';
|
||||
import {Library} from 'src/app/_models/library';
|
||||
import {RecentlyAddedItem} from 'src/app/_models/recently-added-item';
|
||||
|
|
@ -57,6 +57,7 @@ export class DashboardComponent implements OnInit {
|
|||
streams: Array<DashboardStream> = [];
|
||||
genre: Genre | undefined;
|
||||
refreshStreams$ = new Subject<void>();
|
||||
refreshStreamsFromDashboardUpdate$ = new Subject<void>();
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -80,6 +81,13 @@ export class DashboardComponent implements OnInit {
|
|||
|
||||
this.loadDashboard();
|
||||
|
||||
this.refreshStreamsFromDashboardUpdate$.pipe(takeUntilDestroyed(this.destroyRef), debounceTime(1000),
|
||||
tap(() => {
|
||||
console.log('Loading Dashboard')
|
||||
this.loadDashboard()
|
||||
}))
|
||||
.subscribe();
|
||||
|
||||
this.refreshStreams$.pipe(takeUntilDestroyed(this.destroyRef), throttleTime(10_000),
|
||||
tap(() => {
|
||||
this.loadDashboard()
|
||||
|
|
@ -87,29 +95,12 @@ export class DashboardComponent implements OnInit {
|
|||
.subscribe();
|
||||
|
||||
|
||||
// TODO: Solve how Websockets will work with these dyanamic streams
|
||||
this.messageHub.messages$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(res => {
|
||||
|
||||
if (res.event === EVENTS.DashboardUpdate) {
|
||||
console.log('dashboard update triggered')
|
||||
this.refreshStreams$.next();
|
||||
this.refreshStreamsFromDashboardUpdate$.next();
|
||||
} else if (res.event === EVENTS.SeriesAdded) {
|
||||
// const seriesAddedEvent = res.payload as SeriesAddedEvent;
|
||||
|
||||
// this.seriesService.getSeries(seriesAddedEvent.seriesId).subscribe(series => {
|
||||
// if (this.recentlyAddedSeries.filter(s => s.id === series.id).length > 0) return;
|
||||
// this.recentlyAddedSeries = [series, ...this.recentlyAddedSeries];
|
||||
// this.cdRef.markForCheck();
|
||||
// });
|
||||
this.refreshStreams$.next();
|
||||
} else if (res.event === EVENTS.SeriesRemoved) {
|
||||
//const seriesRemovedEvent = res.payload as SeriesRemovedEvent;
|
||||
|
||||
//
|
||||
// this.inProgress = this.inProgress.filter(item => item.id != seriesRemovedEvent.seriesId);
|
||||
// this.recentlyAddedSeries = this.recentlyAddedSeries.filter(item => item.id != seriesRemovedEvent.seriesId);
|
||||
// this.recentlyUpdatedSeries = this.recentlyUpdatedSeries.filter(item => item.seriesId != seriesRemovedEvent.seriesId);
|
||||
// this.cdRef.markForCheck();
|
||||
this.refreshStreams$.next();
|
||||
} else if (res.event === EVENTS.ScanSeries) {
|
||||
// We don't have events for when series are updated, but we do get events when a scan update occurs. Refresh recentlyAdded at that time.
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@
|
|||
<span class="visually-hidden">{{t('shortcuts-menu-alt')}}</span>
|
||||
</button>
|
||||
<button *ngIf="!bookmarkMode && hasBookmarkRights" class="btn btn-icon" role="checkbox" [attr.aria-checked]="CurrentPageBookmarked"
|
||||
title="{{CurrentPageBookmarked ? 'Unbookmark Page' : 'Bookmark Page'}}" (click)="bookmarkPage()">
|
||||
title="{{t(CurrentPageBookmarked ? 'unbookmark-page-tooltip' : 'bookmark-page-tooltip')}}" (click)="bookmarkPage()">
|
||||
<i class="{{CurrentPageBookmarked ? 'fa' : 'far'}} fa-bookmark" aria-hidden="true"></i>
|
||||
<span class="visually-hidden">{{CurrentPageBookmarked ? 'Unbookmark Page' : 'Bookmark Page'}}</span>
|
||||
<span class="visually-hidden">{{t(CurrentPageBookmarked ? 'unbookmark-page-tooltip' : 'bookmark-page-tooltip')}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -737,7 +737,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
getPage(pageNum: number, chapterId: number = this.chapterId, forceNew: boolean = false) {
|
||||
|
||||
let img;
|
||||
if (this.bookmarkMode) img = this.cachedImages.find(img => this.readerService.imageUrlToPageNum(img.src) === pageNum);
|
||||
if (this.bookmarkMode) img = this.cachedImages.find(img => this.readerService.imageUrlToPageNum(img.src) === pageNum);
|
||||
else img = this.cachedImages.find(img => this.readerService.imageUrlToPageNum(img.src) === pageNum
|
||||
&& (this.readerService.imageUrlToChapterId(img.src) == chapterId || this.readerService.imageUrlToChapterId(img.src) === -1)
|
||||
);
|
||||
|
|
@ -1208,9 +1208,14 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
setCanvasImage() {
|
||||
if (this.cachedImages === undefined) return;
|
||||
this.canvasImage = this.getPage(this.pageNum, this.chapterId, this.layoutMode !== LayoutMode.Single);
|
||||
this.canvasImage.addEventListener('load', () => {
|
||||
if (!this.canvasImage.complete) {
|
||||
this.canvasImage.addEventListener('load', () => {
|
||||
this.currentImage.next(this.canvasImage);
|
||||
}, false);
|
||||
} else {
|
||||
this.currentImage.next(this.canvasImage);
|
||||
}, false);
|
||||
}
|
||||
|
||||
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
|
@ -1329,7 +1334,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
// const pages = this.cachedImages.map(img => [this.readerService.imageUrlToChapterId(img.src), this.readerService.imageUrlToPageNum(img.src)]);
|
||||
//const pages = this.cachedImages.map(img => [this.readerService.imageUrlToChapterId(img.src), this.readerService.imageUrlToPageNum(img.src)]);
|
||||
// console.log(this.pageNum, ' Prefetched pages: ', pages.map(p => {
|
||||
// if (this.pageNum === p[1]) return '[' + p + ']';
|
||||
// return '' + p
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
<ng-template #mobileView>
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-2 col-10">
|
||||
<div class="col-md-4 col-10">
|
||||
<select class="form-select" formControlName="comparison">
|
||||
<option *ngFor="let opt of groupOptions" [value]="opt.value">{{opt.title}}</option>
|
||||
</select>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
}
|
||||
|
||||
|
||||
::ng-deep .ngb-dp-content, ::ng-deep .ngb-dp-header, ::ng-deep .dropdown-menu{
|
||||
::ng-deep .ngb-dp-content, ::ng-deep .ngb-dp-header{
|
||||
background: var(--bs-body-bg);
|
||||
color: var(--body-text-color);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,26 @@
|
|||
<ng-container *transloco="let t; read: 'metadata-filter'">
|
||||
<ng-container *ngIf="toggleService.toggleState$ | async as isOpen">
|
||||
<div *ngIf="utilityService.getActiveBreakpoint() >= Breakpoint.Tablet">
|
||||
<div #collapse="ngbCollapse" [ngbCollapse]="!isOpen" (ngbCollapseChange)="setToggle($event)">
|
||||
<ng-container [ngTemplateOutlet]="filterSection"></ng-container>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="utilityService.getActiveBreakpoint() < Breakpoint.Desktop">
|
||||
<app-drawer #commentDrawer="drawer" [isOpen]="isOpen" [options]="{topOffset: 56}" (drawerClosed)="toggleService.set(false)">
|
||||
<h5 header>
|
||||
{{t('filter-title')}}
|
||||
</h5>
|
||||
<div body class="drawer-body">
|
||||
<!-- TODO: BUG: Filter section is instantiated twice if this isn't ngIf'd -->
|
||||
<ng-container *ngIf="utilityService.getActiveBreakpoint() as activeBreakpoint">
|
||||
<div *ngIf="activeBreakpoint >= Breakpoint.Tablet; else mobileView">
|
||||
<div #collapse="ngbCollapse" [ngbCollapse]="!isOpen" (ngbCollapseChange)="setToggle($event)">
|
||||
<ng-container [ngTemplateOutlet]="filterSection"></ng-container>
|
||||
</div>
|
||||
</app-drawer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template #mobileView>
|
||||
<div>
|
||||
<app-drawer #commentDrawer="drawer" [isOpen]="isOpen" [options]="{topOffset: 56}" (drawerClosed)="toggleService.set(false)" [width]="600">
|
||||
<h5 header>
|
||||
{{t('filter-title')}}
|
||||
</h5>
|
||||
<div body class="drawer-body">
|
||||
<!-- TODO: BUG: Filter section is instantiated twice if this isn't ngIf'd -->
|
||||
<ng-container [ngTemplateOutlet]="filterSection"></ng-container>
|
||||
</div>
|
||||
</app-drawer>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<ng-template #filterSection>
|
||||
|
|
@ -30,13 +34,13 @@
|
|||
</div>
|
||||
<form [formGroup]="sortGroup" class="container-fluid">
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-2 col-sm-2">
|
||||
<div class="col-md-2 col-sm-3">
|
||||
<div class="form-group pe-1">
|
||||
<label for="limit-to" class="form-label">{{t('limit-label')}}</label>
|
||||
<input id="limit-to" type="number" inputmode="numeric" class="form-control" formControlName="limitTo">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-10">
|
||||
<div class="col-md-3 col-sm-9">
|
||||
<label for="sort-options" class="form-label">{{t('sort-by-label')}}</label>
|
||||
<button class="btn btn-sm btn-secondary-outline" (click)="updateSortOrder()" style="height: 25px; padding-bottom: 0;" [disabled]="filterSettings.sortDisabled">
|
||||
<i class="fa fa-arrow-up" [title]="t('ascending-alt')" *ngIf="isAscendingSort; else descSort"></i>
|
||||
|
|
@ -48,17 +52,16 @@
|
|||
<option *ngFor="let field of allSortFields" [value]="field">{{field | sortField}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-10">
|
||||
<div class="col-md-4 col-sm-12" [ngClass]="{'mt-3': utilityService.getActiveBreakpoint() <= Breakpoint.Mobile}">
|
||||
<label for="filter-name" class="form-label">{{t('filter-name-label')}}</label>
|
||||
<input id="filter-name" type="text" class="form-control" formControlName="name">
|
||||
<!-- <select2 [data]="smartFilters"-->
|
||||
<!-- id="filter-name"-->
|
||||
<!-- formControlName="name"-->
|
||||
<!-- (update)="updateFilterValue($event)"-->
|
||||
<!-- (update)="loadSavedFilter($event)"-->
|
||||
<!-- (autoCreateItem)="createFilterValue($event)"-->
|
||||
<!-- [autoCreate]="true"-->
|
||||
<!-- [multiple]="false"-->
|
||||
<!-- [infiniteScroll]="false"-->
|
||||
<!-- [hideSelectedItems]="true"-->
|
||||
<!-- displaySearchStatus="always"-->
|
||||
<!-- [resettable]="true">-->
|
||||
<!-- </select2>-->
|
||||
</div>
|
||||
|
|
@ -73,11 +76,11 @@
|
|||
</ng-template>
|
||||
<ng-template #buttons>
|
||||
<!-- TODO: I might want to put a Clear button which blanks out the whole filter -->
|
||||
<div class="col-md-2 col-sm-6 mt-4 pt-2 d-flex justify-content-between">
|
||||
<div class="col-md-6 col-sm-6 mt-4 pt-2 d-flex justify-content-between">
|
||||
<button class="btn btn-secondary col-6 me-1" (click)="clear()"><i class="fa-solid fa-arrow-rotate-left me-1" aria-hidden="true"></i>{{t('reset')}}</button>
|
||||
<button class="btn btn-primary col-6" (click)="apply()"><i class="fa-solid fa-play me-1" aria-hidden="true"></i>{{t('apply')}}</button>
|
||||
</div>
|
||||
<div class="col-md-1 col-sm-6 mt-4 pt-2">
|
||||
<div class="col-md-2 col-sm-6 mt-4 pt-2">
|
||||
<button class="btn btn-primary col-12" (click)="save()" [disabled]="filterSettings.saveDisabled || !this.sortGroup.get('name')?.value">
|
||||
<i class="fa-solid fa-floppy-disk" aria-hidden="true"></i>
|
||||
{{t('save')}}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import {SeriesFilterV2} from '../_models/metadata/v2/series-filter-v2';
|
|||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
import {TypeaheadComponent} from '../typeahead/_components/typeahead.component';
|
||||
import {DrawerComponent} from '../shared/drawer/drawer.component';
|
||||
import {AsyncPipe, NgForOf, NgIf, NgTemplateOutlet} from '@angular/common';
|
||||
import {AsyncPipe, NgClass, NgForOf, NgIf, NgTemplateOutlet} from '@angular/common';
|
||||
import {translate, TranslocoModule} from "@ngneat/transloco";
|
||||
import {SortFieldPipe} from "../pipe/sort-field.pipe";
|
||||
import {MetadataBuilderComponent} from "./_components/metadata-builder/metadata-builder.component";
|
||||
|
|
@ -30,7 +30,13 @@ import {MetadataService} from "../_services/metadata.service";
|
|||
import {FilterUtilitiesService} from "../shared/_services/filter-utilities.service";
|
||||
import {FilterService} from "../_services/filter.service";
|
||||
import {ToastrService} from "ngx-toastr";
|
||||
import {Select2Module, Select2Option, Select2UpdateEvent} from "ng-select2-component";
|
||||
import {
|
||||
Select2AutoCreateEvent,
|
||||
Select2Module,
|
||||
Select2Option,
|
||||
Select2UpdateEvent,
|
||||
Select2UpdateValue
|
||||
} from "ng-select2-component";
|
||||
import {SmartFilter} from "../_models/metadata/v2/smart-filter";
|
||||
|
||||
@Component({
|
||||
|
|
@ -40,7 +46,7 @@ import {SmartFilter} from "../_models/metadata/v2/smart-filter";
|
|||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [NgIf, NgbCollapse, NgTemplateOutlet, DrawerComponent, NgbTooltip, TypeaheadComponent,
|
||||
ReactiveFormsModule, FormsModule, NgbRating, AsyncPipe, TranslocoModule, SortFieldPipe, MetadataBuilderComponent, NgForOf, Select2Module]
|
||||
ReactiveFormsModule, FormsModule, NgbRating, AsyncPipe, TranslocoModule, SortFieldPipe, MetadataBuilderComponent, NgForOf, Select2Module, NgClass]
|
||||
})
|
||||
export class MetadataFilterComponent implements OnInit {
|
||||
|
||||
|
|
@ -61,6 +67,7 @@ export class MetadataFilterComponent implements OnInit {
|
|||
@ContentChild('[ngbCollapse]') collapse!: NgbCollapse;
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
public readonly utilityService = inject(UtilityService);
|
||||
public readonly filterUtilitiesService = inject(FilterUtilitiesService);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -114,8 +121,36 @@ export class MetadataFilterComponent implements OnInit {
|
|||
this.loadFromPresetsAndSetup();
|
||||
}
|
||||
|
||||
updateFilterValue(event: Select2UpdateEvent<any>) {
|
||||
console.log('event: ', event);
|
||||
loadSavedFilter(event: Select2UpdateEvent<any>) {
|
||||
// Load the filter from the backend and update the screen
|
||||
if (event.value === undefined || typeof(event.value) === 'string') return;
|
||||
const smartFilter = event.value as SmartFilter;
|
||||
this.filterV2 = this.filterUtilitiesService.decodeSeriesFilter(smartFilter.filter);
|
||||
this.cdRef.markForCheck();
|
||||
console.log('update event: ', event);
|
||||
}
|
||||
|
||||
createFilterValue(event: Select2AutoCreateEvent<any>) {
|
||||
// Create a new name and filter
|
||||
if (!this.filterV2) return;
|
||||
this.filterV2.name = event.value;
|
||||
this.filterService.saveFilter(this.filterV2).subscribe(() => {
|
||||
|
||||
const item = {
|
||||
value: {
|
||||
filter: this.filterUtilitiesService.encodeSeriesFilter(this.filterV2!),
|
||||
name: event.value,
|
||||
} as SmartFilter,
|
||||
label: event.value
|
||||
};
|
||||
this.smartFilters.push(item);
|
||||
this.sortGroup.get('name')?.setValue(item);
|
||||
this.cdRef.markForCheck();
|
||||
this.toastr.success(translate('toasts.smart-filter-updated'));
|
||||
this.apply();
|
||||
});
|
||||
|
||||
console.log('create event: ', event);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -204,7 +239,7 @@ export class MetadataFilterComponent implements OnInit {
|
|||
|
||||
apply() {
|
||||
this.applyFilter.emit({isFirst: this.updateApplied === 0, filterV2: this.filterV2!});
|
||||
|
||||
|
||||
if (this.utilityService.getActiveBreakpoint() === Breakpoint.Mobile && this.updateApplied !== 0) {
|
||||
this.toggleSelected();
|
||||
}
|
||||
|
|
@ -219,7 +254,7 @@ export class MetadataFilterComponent implements OnInit {
|
|||
this.filterService.saveFilter(this.filterV2).subscribe(() => {
|
||||
this.toastr.success(translate('toasts.smart-filter-updated'));
|
||||
this.apply();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
toggleSelected() {
|
||||
|
|
@ -231,5 +266,5 @@ export class MetadataFilterComponent implements OnInit {
|
|||
this.toggleService.set(!this.filteringCollapsed);
|
||||
}
|
||||
|
||||
protected readonly Breakpoint = Breakpoint;
|
||||
protected readonly Breakpoint = Breakpoint;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ export class ProviderNamePipe implements PipeTransform {
|
|||
return 'MAL';
|
||||
case ScrobbleProvider.Kavita:
|
||||
return 'Kavita';
|
||||
case ScrobbleProvider.GoogleBooks:
|
||||
return 'Google Books';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export class DrawerOptions {
|
|||
@Component({
|
||||
selector: 'app-drawer',
|
||||
standalone: true,
|
||||
imports: [CommonModule, TranslocoDirective],
|
||||
imports: [CommonModule, TranslocoDirective],
|
||||
templateUrl: './drawer.component.html',
|
||||
styleUrls: ['./drawer.component.scss'],
|
||||
exportAs: "drawer",
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@
|
|||
{{filter.name}}
|
||||
<button class="btn btn-icon" (click)="addFilterToStream(filter)">
|
||||
<i class="fa fa-plus" aria-hidden="true"></i>
|
||||
Add
|
||||
{{t('add')}}
|
||||
</button>
|
||||
</li>
|
||||
<li class="list-group-item" *ngIf="smartFilters.length === 0">
|
||||
All Smart filters added to Dashboard or none created yet.
|
||||
{{t('no-data')}}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ export class CustomizeDashboardModalComponent {
|
|||
private readonly cdRef = inject(ChangeDetectorRef);
|
||||
|
||||
constructor(public modal: NgbActiveModal) {
|
||||
|
||||
forkJoin([this.dashboardService.getDashboardStreams(false), this.filterService.getAllFilters()]).subscribe(results => {
|
||||
this.items = results[0];
|
||||
const smartFilterStreams = new Set(results[0].filter(d => !d.isProvided).map(d => d.name));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue