Get notification count in tab headings via local injector

pull/9599/head
Benjamin Bädorf 3 years ago
parent c5caf237a6
commit 4e788bdcb7
No known key found for this signature in database
GPG Key ID: 069CA2D117AB5CCF
  1. 16
      frontend/src/app/core/global_search/tabs/global-search-tabs.component.ts
  2. 8
      frontend/src/app/features/in-app-notifications/center/in-app-notification-center-page.component.ts
  3. 10
      frontend/src/app/features/in-app-notifications/center/in-app-notification-center.component.ts
  4. 7
      frontend/src/app/features/work-packages/components/wp-tabs/services/wp-tabs/wp-tabs.service.ts
  5. 15
      frontend/src/app/shared/components/tabs/content-tabs/content-tabs.component.ts
  6. 4
      frontend/src/app/shared/components/tabs/scrollable-tabs/scrollable-tabs.component.html
  7. 7
      frontend/src/app/shared/components/tabs/scrollable-tabs/scrollable-tabs.component.ts
  8. 2
      frontend/src/app/shared/components/tabs/tab-badges/tab-count.component.html
  9. 2
      frontend/src/app/shared/components/tabs/tab-badges/tab-count.component.ts
  10. 3
      frontend/src/app/shared/components/tabs/tab.interface.ts

@ -26,7 +26,12 @@
// See docs/COPYRIGHT.rdoc for more details. // See docs/COPYRIGHT.rdoc for more details.
//++ //++
import { ChangeDetectorRef, Component, OnDestroy } from '@angular/core'; import {
ChangeDetectorRef,
Component,
OnDestroy,
Injector,
} from '@angular/core';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { GlobalSearchService } from 'core-app/core/global_search/services/global-search.service'; import { GlobalSearchService } from 'core-app/core/global_search/services/global-search.service';
import { ScrollableTabsComponent } from 'core-app/shared/components/tabs/scrollable-tabs/scrollable-tabs.component'; import { ScrollableTabsComponent } from 'core-app/shared/components/tabs/scrollable-tabs/scrollable-tabs.component';
@ -46,9 +51,12 @@ export class GlobalSearchTabsComponent extends ScrollableTabsComponent implement
public classes:string[] = ['global-search--tabs', 'scrollable-tabs']; public classes:string[] = ['global-search--tabs', 'scrollable-tabs'];
constructor(readonly globalSearchService:GlobalSearchService, constructor(
cdRef:ChangeDetectorRef) { readonly globalSearchService:GlobalSearchService,
super(cdRef); public injector: Injector,
cdRef:ChangeDetectorRef,
) {
super(cdRef, injector);
} }
ngOnInit() { ngOnInit() {

@ -20,6 +20,9 @@ import { NotificationSettingsButtonComponent } from 'core-app/features/in-app-no
import { ActivateFacetButtonComponent } from 'core-app/features/in-app-notifications/center/toolbar/facet/activate-facet-button.component'; import { ActivateFacetButtonComponent } from 'core-app/features/in-app-notifications/center/toolbar/facet/activate-facet-button.component';
import { MarkAllAsReadButtonComponent } from 'core-app/features/in-app-notifications/center/toolbar/mark-all-as-read/mark-all-as-read-button.component'; import { MarkAllAsReadButtonComponent } from 'core-app/features/in-app-notifications/center/toolbar/mark-all-as-read/mark-all-as-read-button.component';
import { UntilDestroyedMixin } from 'core-app/shared/helpers/angular/until-destroyed.mixin'; import { UntilDestroyedMixin } from 'core-app/shared/helpers/angular/until-destroyed.mixin';
import { InAppNotificationsQuery } from 'core-app/features/in-app-notifications/store/in-app-notifications.query';
import { InAppNotificationsStore } from 'core-app/features/in-app-notifications/store/in-app-notifications.store';
import { InAppNotificationsService } from 'core-app/features/in-app-notifications/store/in-app-notifications.service';
import { import {
BackRouteOptions, BackRouteOptions,
BackRoutingService, BackRoutingService,
@ -31,6 +34,11 @@ import {
'../../work-packages/routing/partitioned-query-space-page/partitioned-query-space-page.component.sass', '../../work-packages/routing/partitioned-query-space-page/partitioned-query-space-page.component.sass',
], ],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
InAppNotificationsService,
InAppNotificationsStore,
InAppNotificationsQuery,
],
}) })
export class InAppNotificationCenterPageComponent extends UntilDestroyedMixin implements OnInit { export class InAppNotificationCenterPageComponent extends UntilDestroyedMixin implements OnInit {
text = { text = {

@ -6,12 +6,11 @@ import {
OnInit, OnInit,
} from '@angular/core'; } from '@angular/core';
import { I18nService } from 'core-app/core/i18n/i18n.service'; import { I18nService } from 'core-app/core/i18n/i18n.service';
import { InAppNotificationsQuery } from 'core-app/features/in-app-notifications/store/in-app-notifications.query';
import { InAppNotificationsStore } from 'core-app/features/in-app-notifications/store/in-app-notifications.store';
import { InAppNotificationsService } from 'core-app/features/in-app-notifications/store/in-app-notifications.service';
import { NOTIFICATIONS_MAX_SIZE } from 'core-app/features/in-app-notifications/store/in-app-notification.model'; import { NOTIFICATIONS_MAX_SIZE } from 'core-app/features/in-app-notifications/store/in-app-notification.model';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { StateService } from '@uirouter/angular'; import { StateService } from '@uirouter/angular';
import { InAppNotificationsQuery } from 'core-app/features/in-app-notifications/store/in-app-notifications.query';
import { InAppNotificationsService } from 'core-app/features/in-app-notifications/store/in-app-notifications.service';
import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource'; import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
import { UIRouterGlobals } from '@uirouter/core'; import { UIRouterGlobals } from '@uirouter/core';
@ -20,11 +19,6 @@ import { UIRouterGlobals } from '@uirouter/core';
templateUrl: './in-app-notification-center.component.html', templateUrl: './in-app-notification-center.component.html',
styleUrls: ['./in-app-notification-center.component.sass'], styleUrls: ['./in-app-notification-center.component.sass'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
InAppNotificationsService,
InAppNotificationsStore,
InAppNotificationsQuery,
],
}) })
export class InAppNotificationCenterComponent implements OnInit { export class InAppNotificationCenterComponent implements OnInit {
activeFacet$ = this.ianQuery.activeFacet$; activeFacet$ = this.ianQuery.activeFacet$;

@ -1,8 +1,9 @@
import { Injectable, Injector } from '@angular/core'; import { Injectable, Injector } from '@angular/core';
import { from } from 'rxjs';
import { StateService } from '@uirouter/core';
import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource'; import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
import { WpTabDefinition } from 'core-app/features/work-packages/components/wp-tabs/components/wp-tab-wrapper/tab'; import { WpTabDefinition } from 'core-app/features/work-packages/components/wp-tabs/components/wp-tab-wrapper/tab';
import { WorkPackageRelationsTabComponent } from 'core-app/features/work-packages/components/wp-single-view-tabs/relations-tab/relations-tab.component'; import { WorkPackageRelationsTabComponent } from 'core-app/features/work-packages/components/wp-single-view-tabs/relations-tab/relations-tab.component';
import { StateService } from '@uirouter/core';
import { WorkPackageOverviewTabComponent } from 'core-app/features/work-packages/components/wp-single-view-tabs/overview-tab/overview-tab.component'; import { WorkPackageOverviewTabComponent } from 'core-app/features/work-packages/components/wp-single-view-tabs/overview-tab/overview-tab.component';
import { WorkPackageActivityTabComponent } from 'core-app/features/work-packages/components/wp-single-view-tabs/activity-panel/activity-tab.component'; import { WorkPackageActivityTabComponent } from 'core-app/features/work-packages/components/wp-single-view-tabs/activity-panel/activity-tab.component';
import { WorkPackageWatchersTabComponent } from 'core-app/features/work-packages/components/wp-single-view-tabs/watchers-tab/watchers-tab.component'; import { WorkPackageWatchersTabComponent } from 'core-app/features/work-packages/components/wp-single-view-tabs/watchers-tab/watchers-tab.component';
@ -45,7 +46,9 @@ export class WorkPackageTabsService {
.map( .map(
(tab) => ({ (tab) => ({
...tab, ...tab,
...!!tab.count && { counter: tab.count(workPackage, this.injector) }, counter: tab.count
? (injector:Injector) => tab.count!(workPackage, injector || this.injector)
: (_:Injector) => from([0]),
}), }),
); );
} }

@ -27,7 +27,11 @@
//++ //++
import { import {
ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
Injector,
} from '@angular/core'; } from '@angular/core';
import { GonService } from 'core-app/core/gon/gon.service'; import { GonService } from 'core-app/core/gon/gon.service';
import { StateService } from '@uirouter/core'; import { StateService } from '@uirouter/core';
@ -52,12 +56,15 @@ interface GonTab extends TabDefinition {
export class ContentTabsComponent extends ScrollableTabsComponent { export class ContentTabsComponent extends ScrollableTabsComponent {
public classes:string[] = ['content--tabs', 'scrollable-tabs']; public classes:string[] = ['content--tabs', 'scrollable-tabs'];
constructor(readonly elementRef:ElementRef, constructor(
readonly elementRef:ElementRef,
readonly $state:StateService, readonly $state:StateService,
readonly gon:GonService, readonly gon:GonService,
cdRef:ChangeDetectorRef, cdRef:ChangeDetectorRef,
readonly I18n:I18nService) { readonly I18n:I18nService,
super(cdRef); public injector: Injector,
) {
super(cdRef, injector);
const gonTabs = JSON.parse((this.gon.get('contentTabs') as any).tabs); const gonTabs = JSON.parse((this.gon.get('contentTabs') as any).tabs);
const currentTab = JSON.parse((this.gon.get('contentTabs') as any).selected); const currentTab = JSON.parse((this.gon.get('contentTabs') as any).selected);

@ -38,10 +38,10 @@
<span [textContent]="tab.name"></span> <span [textContent]="tab.name"></span>
<op-tab-count <op-tab-count
*ngIf="tab.counter && tab.showCountAsBubble" *ngIf="tab.counter && tab.showCountAsBubble"
[counter]="tab.counter" [count]="tab.counter(injector) | async"
[attr.data-qa-selector]="'tab-counter-' + tab.name" [attr.data-qa-selector]="'tab-counter-' + tab.name"
></op-tab-count> ></op-tab-count>
<ng-container *ngIf="tab.counter | async as tabCounter"> <ng-container *ngIf="tab.counter(injector) | async as tabCounter">
<span <span
*ngIf="tabCounter > 0 && !tab.showCountAsBubble" *ngIf="tabCounter > 0 && !tab.showCountAsBubble"
data-qa-selector="tab-count" data-qa-selector="tab-count"

@ -6,6 +6,7 @@ import {
ElementRef, ElementRef,
EventEmitter, EventEmitter,
Input, Input,
Injector,
OnChanges, OnChanges,
Output, Output,
SimpleChanges, SimpleChanges,
@ -47,8 +48,10 @@ export class ScrollableTabsComponent implements AfterViewInit, OnChanges {
private pane:Element; private pane:Element;
constructor(private cdRef:ChangeDetectorRef) { constructor(
} private cdRef:ChangeDetectorRef,
public injector:Injector,
) { }
ngAfterViewInit():void { ngAfterViewInit():void {
this.container = this.scrollContainer.nativeElement; this.container = this.scrollContainer.nativeElement;

@ -1,4 +1,4 @@
<ng-container *ngIf="(counter$ | async) as count"> <ng-container *ngIf="count">
<span <span
class="op-tab-count" class="op-tab-count"
*ngIf="count > 0" *ngIf="count > 0"

@ -8,5 +8,5 @@ import { Observable } from 'rxjs';
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class TabCountComponent { export class TabCountComponent {
@Input('counter') counter$:Observable<number>; @Input('count') count:number;
} }

@ -1,4 +1,5 @@
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { Injector } from '@angular/core';
export interface TabDefinition { export interface TabDefinition {
/** Internal identifier of the tab */ /** Internal identifier of the tab */
@ -12,7 +13,7 @@ export interface TabDefinition {
/** UI router params to use uiParams with */ /** UI router params to use uiParams with */
routeParams?:unknown; routeParams?:unknown;
/** Show a tab count with this observable's result */ /** Show a tab count with this observable's result */
counter?:Observable<number>; counter?:(injector?:Injector) => Observable<number>;
/** Whether the counter should be shown as number in brackets or within a bubble */ /** Whether the counter should be shown as number in brackets or within a bubble */
showCountAsBubble?:boolean; showCountAsBubble?:boolean;
/** Disable the tab, optionally with an explanatory title */ /** Disable the tab, optionally with an explanatory title */

Loading…
Cancel
Save