mirror of
https://github.com/opf/openproject.git
synced 2026-06-13 19:20:00 +00:00
[#74950] Migrate Angular DI to inject()
Migrates Angular constructor-based dependency injection to the
`inject()` function. The initial pass used the Angular schematic;
manual follow-up handled abstract classes, inheritance-sensitive
constructors, and call sites that still instantiate services
directly.
Schematic command:
cd frontend && npx ng generate @angular/core:inject-migration \
--path ./ \
--migrate-abstract-classes \
--backwards-compatible-constructors=false \
--non-nullable-optional=false
https://community.openproject.org/wp/74950
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Inject, Injectable, DOCUMENT } from '@angular/core';
|
||||
import { Injectable, DOCUMENT, inject } from '@angular/core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { debugLog } from 'core-app/shared/helpers/debug_output';
|
||||
|
||||
@@ -6,7 +6,9 @@ import { debugLog } from 'core-app/shared/helpers/debug_output';
|
||||
export class ActiveWindowService {
|
||||
private activeState$ = new BehaviorSubject<boolean>(true);
|
||||
|
||||
constructor(@Inject(DOCUMENT) document:Document) {
|
||||
constructor() {
|
||||
const document = inject<Document>(DOCUMENT);
|
||||
|
||||
document.addEventListener('visibilitychange', () => {
|
||||
if (document.visibilityState) {
|
||||
debugLog(`Browser window has visibility state changed to ${document.visibilityState}`);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Injectable, Injector, inject } from '@angular/core';
|
||||
import { ApiV3GettableResource, ApiV3ResourceCollection } from 'core-app/core/apiv3/paths/apiv3-resource';
|
||||
import { Constructor } from 'core-app/core/util-types';
|
||||
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
|
||||
@@ -65,6 +65,9 @@ import {
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ApiV3Service {
|
||||
readonly injector = inject(Injector);
|
||||
readonly pathHelper = inject(PathHelperService);
|
||||
|
||||
// /api/v3/attachments
|
||||
public readonly attachments = this.apiV3CollectionEndpoint('attachments');
|
||||
|
||||
@@ -173,11 +176,6 @@ export class ApiV3Service {
|
||||
// VIRTUAL boards are /api/v3/grids + a scope filter
|
||||
public readonly boards = this.apiV3CustomEndpoint(ApiV3BoardsPaths);
|
||||
|
||||
constructor(
|
||||
readonly injector:Injector,
|
||||
readonly pathHelper:PathHelperService,
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Returns the part of the API that exists both
|
||||
* - WITHIN a project scope /api/v3/projects/*
|
||||
|
||||
@@ -37,8 +37,8 @@ import { ProjectResource } from 'core-app/features/hal/resources/project-resourc
|
||||
export class ProjectCache extends StateCacheService<ProjectResource> {
|
||||
@InjectField() private schemaCacheService:SchemaCacheService;
|
||||
|
||||
constructor(readonly injector:Injector,
|
||||
state:MultiInputState<ProjectResource>) {
|
||||
// eslint-disable-next-line @angular-eslint/prefer-inject -- manually instantiated, not DI-resolved
|
||||
constructor(readonly injector:Injector, state:MultiInputState<ProjectResource>) {
|
||||
super(state);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { NgModule, inject } from '@angular/core';
|
||||
import { OpenprojectModalModule } from 'core-app/shared/components/modal/modal.module';
|
||||
import { OpModalWrapperAugmentService } from 'core-app/shared/components/modal/modal-wrapper-augment.service';
|
||||
|
||||
@@ -34,7 +34,9 @@ import { OpModalWrapperAugmentService } from 'core-app/shared/components/modal/m
|
||||
imports: [OpenprojectModalModule],
|
||||
})
|
||||
export class OpenprojectAugmentingModule {
|
||||
constructor(modalWrapper:OpModalWrapperAugmentService) {
|
||||
constructor() {
|
||||
const modalWrapper = inject(OpModalWrapperAugmentService);
|
||||
|
||||
// Setup augmenting services
|
||||
modalWrapper.setupListener();
|
||||
|
||||
|
||||
@@ -26,17 +26,15 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { HalResource } from 'core-app/features/hal/resources/hal-resource';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class OpenProjectBackupService {
|
||||
constructor(
|
||||
protected apiV3Service:ApiV3Service,
|
||||
) {
|
||||
}
|
||||
protected apiV3Service = inject(ApiV3Service);
|
||||
|
||||
|
||||
public triggerBackup(backupToken:string, includeAttachments = true):Observable<HalResource> {
|
||||
return this
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Inject, Injectable, DOCUMENT } from '@angular/core';
|
||||
import { Injectable, DOCUMENT, inject } from '@angular/core';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class BrowserDetector {
|
||||
constructor(@Inject(DOCUMENT) private documentElement:Document) {
|
||||
}
|
||||
private documentElement = inject<Document>(DOCUMENT);
|
||||
|
||||
|
||||
/**
|
||||
* Detect mobile browser based on the Rails determined UA
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import moment from 'moment';
|
||||
|
||||
import { ConfigurationResource } from 'core-app/features/hal/resources/configuration-resource';
|
||||
@@ -35,15 +35,13 @@ import { type DurationFormat } from 'core-app/shared/helpers/chronic_duration';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ConfigurationService {
|
||||
private readonly apiV3Service = inject(ApiV3Service);
|
||||
|
||||
// fetches configuration from the ApiV3 endpoint
|
||||
// TODO: this currently saves the request between page reloads,
|
||||
// but could easily be stored in localStorage
|
||||
private configuration:ConfigurationResource;
|
||||
|
||||
public constructor(
|
||||
private readonly apiV3Service:ApiV3Service,
|
||||
) { }
|
||||
|
||||
public initialize():Promise<void> {
|
||||
return this.loadConfiguration();
|
||||
}
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
|
||||
import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
|
||||
import { CurrentProjectService } from './current-project.service';
|
||||
|
||||
describe('currentProject service', () => {
|
||||
@@ -40,7 +42,15 @@ describe('currentProject service', () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
currentProject = new CurrentProjectService(new PathHelperService(), apiV3Stub);
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
CurrentProjectService,
|
||||
PathHelperService,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
{ provide: ApiV3Service, useValue: apiV3Stub },
|
||||
],
|
||||
});
|
||||
currentProject = TestBed.inject(CurrentProjectService);
|
||||
});
|
||||
|
||||
describe('with no meta present', () => {
|
||||
|
||||
@@ -26,21 +26,21 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
|
||||
import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
|
||||
import { getMetaElement } from '../setup/globals/global-helpers';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CurrentProjectService {
|
||||
private PathHelper = inject(PathHelperService);
|
||||
private apiV3Service = inject(ApiV3Service);
|
||||
|
||||
private currentId:string|null = null;
|
||||
private currentName:string|null = null;
|
||||
private currentIdentifier:string|null = null;
|
||||
|
||||
constructor(
|
||||
private PathHelper:PathHelperService,
|
||||
private apiV3Service:ApiV3Service,
|
||||
) {
|
||||
constructor() {
|
||||
this.detect();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injector, NgModule } from '@angular/core';
|
||||
import { Injector, NgModule, inject } from '@angular/core';
|
||||
|
||||
import { CurrentUserService } from './current-user.service';
|
||||
import { CurrentUserStore } from './current-user.store';
|
||||
@@ -35,7 +35,9 @@ export function bootstrapModule(injector:Injector):void {
|
||||
],
|
||||
})
|
||||
export class CurrentUserModule {
|
||||
constructor(injector:Injector) {
|
||||
constructor() {
|
||||
const injector = inject(Injector);
|
||||
|
||||
bootstrapModule(injector);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { Query } from '@datorama/akita';
|
||||
import { CurrentUserState, CurrentUserStore } from './current-user.store';
|
||||
|
||||
@Injectable()
|
||||
export class CurrentUserQuery extends Query<CurrentUserState> {
|
||||
constructor(protected store:CurrentUserStore) {
|
||||
protected store:CurrentUserStore;
|
||||
|
||||
constructor() {
|
||||
const store = inject(CurrentUserStore);
|
||||
|
||||
super(store);
|
||||
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
isLoggedIn$ = this.select((state) => !!state.loggedIn);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
|
||||
import { ApiV3ListFilter } from 'core-app/core/apiv3/paths/apiv3-list-resource.interface';
|
||||
import { CapabilitiesResourceService } from 'core-app/core/state/capabilities/capabilities.service';
|
||||
@@ -38,12 +38,12 @@ import { CurrentUser, CurrentUserStore } from './current-user.store';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CurrentUserService {
|
||||
constructor(
|
||||
private apiV3Service:ApiV3Service,
|
||||
private currentUserStore:CurrentUserStore,
|
||||
private currentUserQuery:CurrentUserQuery,
|
||||
private capabilitiesService:CapabilitiesResourceService,
|
||||
) {
|
||||
private apiV3Service = inject(ApiV3Service);
|
||||
private currentUserStore = inject(CurrentUserStore);
|
||||
private currentUserQuery = inject(CurrentUserQuery);
|
||||
private capabilitiesService = inject(CapabilitiesResourceService);
|
||||
|
||||
constructor() {
|
||||
this.setupLegacyDataListeners();
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { ConfigurationService } from 'core-app/core/config/configuration.service';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import moment, { Moment } from 'moment-timezone';
|
||||
@@ -34,10 +34,9 @@ import { outputChronicDuration } from '../../shared/helpers/chronic_duration';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class TimezoneService {
|
||||
constructor(
|
||||
readonly configurationService:ConfigurationService,
|
||||
readonly I18n:I18nService,
|
||||
) { }
|
||||
readonly configurationService = inject(ConfigurationService);
|
||||
readonly I18n = inject(I18nService);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the user's configured timezone or guesses it through moment
|
||||
|
||||
@@ -26,10 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
Injectable,
|
||||
Injector,
|
||||
} from '@angular/core';
|
||||
import { Injectable, Injector, inject } from '@angular/core';
|
||||
import moment, { Moment } from 'moment';
|
||||
import {
|
||||
take,
|
||||
@@ -45,14 +42,12 @@ import {
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class WeekdayService {
|
||||
readonly injector = inject(Injector);
|
||||
|
||||
@InjectField() weekdaysService:WeekdayResourceService;
|
||||
|
||||
private weekdays:IWeekday[];
|
||||
|
||||
constructor(
|
||||
readonly injector:Injector,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @param date The iso day number (1-7) or a date instance
|
||||
* @return {boolean} whether the given iso day is working or not
|
||||
|
||||
@@ -26,18 +26,20 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Inject, Injectable, DOCUMENT } from '@angular/core';
|
||||
import { Injectable, DOCUMENT, inject } from '@angular/core';
|
||||
import { enterpriseEditionUrl } from 'core-app/core/setup/globals/constants.const';
|
||||
import { ConfigurationService } from 'core-app/core/config/configuration.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class BannersService {
|
||||
protected documentElement = inject<Document>(DOCUMENT);
|
||||
protected configuration = inject(ConfigurationService);
|
||||
|
||||
private readonly _bannersHidden:boolean = true;
|
||||
|
||||
constructor(
|
||||
@Inject(DOCUMENT) protected documentElement:Document,
|
||||
protected configuration:ConfigurationService,
|
||||
) {
|
||||
constructor() {
|
||||
const documentElement = this.documentElement;
|
||||
|
||||
this._bannersHidden = documentElement.body.classList.contains('ee-banners-hidden');
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ElementRef,
|
||||
HostListener,
|
||||
Input,
|
||||
OnDestroy,
|
||||
ViewChild,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, HostListener, Input, OnDestroy, ViewChild, ViewEncapsulation, inject } from '@angular/core';
|
||||
import { BehaviorSubject, Observable, of } from 'rxjs';
|
||||
import { first, map, switchMap, tap } from 'rxjs/operators';
|
||||
import { GlobalSearchService } from 'core-app/core/global_search/services/global-search.service';
|
||||
@@ -74,6 +63,18 @@ interface SearchResultItems {
|
||||
standalone: false,
|
||||
})
|
||||
export class GlobalSearchInputComponent implements AfterViewInit, OnDestroy {
|
||||
readonly elementRef = inject(ElementRef);
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly apiV3Service = inject(ApiV3Service);
|
||||
readonly pathHelperService = inject(PathHelperService);
|
||||
readonly halResourceService = inject(HalResourceService);
|
||||
readonly globalSearchService = inject(GlobalSearchService);
|
||||
readonly currentProjectService = inject(CurrentProjectService);
|
||||
readonly deviceService = inject(DeviceService);
|
||||
readonly cdRef = inject(ChangeDetectorRef);
|
||||
readonly halNotification = inject(HalResourceNotificationService);
|
||||
readonly recentItemsService = inject(RecentItemsService);
|
||||
|
||||
@Input() public placeholder:string;
|
||||
|
||||
@ViewChild('btn', { static: true }) btn:ElementRef;
|
||||
@@ -131,19 +132,7 @@ export class GlobalSearchInputComponent implements AfterViewInit, OnDestroy {
|
||||
search: this.I18n.t('js.autocompleter.search'),
|
||||
};
|
||||
|
||||
constructor(
|
||||
readonly elementRef:ElementRef,
|
||||
readonly I18n:I18nService,
|
||||
readonly apiV3Service:ApiV3Service,
|
||||
readonly pathHelperService:PathHelperService,
|
||||
readonly halResourceService:HalResourceService,
|
||||
readonly globalSearchService:GlobalSearchService,
|
||||
readonly currentProjectService:CurrentProjectService,
|
||||
readonly deviceService:DeviceService,
|
||||
readonly cdRef:ChangeDetectorRef,
|
||||
readonly halNotification:HalResourceNotificationService,
|
||||
readonly recentItemsService:RecentItemsService,
|
||||
) {
|
||||
constructor() {
|
||||
populateInputsFromDataset(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injector, NgModule } from '@angular/core';
|
||||
import { Injector, NgModule, inject } from '@angular/core';
|
||||
import { OpenprojectWorkPackagesModule } from 'core-app/features/work-packages/openproject-work-packages.module';
|
||||
import { GlobalSearchInputComponent } from 'core-app/core/global_search/input/global-search-input.component';
|
||||
import { GlobalSearchWorkPackagesComponent } from 'core-app/core/global_search/global-search-work-packages.component';
|
||||
@@ -53,6 +53,5 @@ import { RecentItemsService } from 'core-app/core/recent-items.service';
|
||||
],
|
||||
})
|
||||
export class OpenprojectGlobalSearchModule {
|
||||
constructor(readonly injector:Injector) {
|
||||
}
|
||||
readonly injector = inject(Injector);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Injectable, Injector, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { CurrentProjectService } from 'core-app/core/current-project/current-project.service';
|
||||
|
||||
@@ -34,13 +34,11 @@ import { PathHelperService } from 'core-app/core/path-helper/path-helper.service
|
||||
|
||||
@Injectable()
|
||||
export class GlobalSearchService {
|
||||
constructor(
|
||||
protected I18n:I18nService,
|
||||
protected injector:Injector,
|
||||
protected PathHelper:PathHelperService,
|
||||
protected currentProjectService:CurrentProjectService,
|
||||
) {
|
||||
}
|
||||
protected I18n = inject(I18nService);
|
||||
protected injector = inject(Injector);
|
||||
protected PathHelper = inject(PathHelperService);
|
||||
protected currentProjectService = inject(CurrentProjectService);
|
||||
|
||||
|
||||
public submitSearch(query:string, scope:string):void {
|
||||
const path = this.searchPath(scope);
|
||||
|
||||
@@ -26,8 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Injector, OnDestroy, OnInit } from '@angular/core';
|
||||
import { StateService } from '@uirouter/core';
|
||||
import { ChangeDetectionStrategy, Component, OnDestroy, OnInit, inject } from '@angular/core';
|
||||
import { Subscription } from 'rxjs';
|
||||
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';
|
||||
@@ -40,20 +39,13 @@ import { TabDefinition } from 'core-app/shared/components/tabs/tab.interface';
|
||||
standalone: false,
|
||||
})
|
||||
export class GlobalSearchTabsComponent extends ScrollableTabsComponent implements OnInit, OnDestroy {
|
||||
readonly globalSearchService = inject(GlobalSearchService);
|
||||
|
||||
private currentTabSub:Subscription;
|
||||
|
||||
private tabsSub:Subscription;
|
||||
|
||||
public classes:string[] = ['global-search--tabs', 'scrollable-tabs'];
|
||||
|
||||
constructor(
|
||||
readonly globalSearchService:GlobalSearchService,
|
||||
protected readonly $state:StateService,
|
||||
public injector:Injector,
|
||||
cdRef:ChangeDetectorRef,
|
||||
) {
|
||||
super($state, cdRef, injector);
|
||||
}
|
||||
public override classes:string[] = ['global-search--tabs', 'scrollable-tabs'];
|
||||
|
||||
ngOnInit():void {
|
||||
this.currentTabSub = this.globalSearchService
|
||||
|
||||
@@ -26,12 +26,13 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable, SecurityContext } from '@angular/core';
|
||||
import { Injectable, SecurityContext, inject } from '@angular/core';
|
||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class HTMLSanitizeService {
|
||||
public constructor(readonly sanitizer:DomSanitizer) { }
|
||||
readonly sanitizer = inject(DomSanitizer);
|
||||
|
||||
|
||||
public sanitize(string:string):SafeHtml {
|
||||
return this.sanitizer.sanitize(SecurityContext.HTML, string) || '';
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { getMetaContent } from '../setup/globals/global-helpers';
|
||||
|
||||
const titlePartsSeparator = ' | ';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class OpTitleService {
|
||||
constructor(private titleService:Title) {
|
||||
}
|
||||
private titleService = inject(Title);
|
||||
|
||||
|
||||
public get current():string {
|
||||
return this.titleService.getTitle();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { NgSelectConfig } from '@ng-select/ng-select';
|
||||
import { I18n } from 'i18n-js';
|
||||
import { FormatNumberOptions, TranslateOptions } from 'i18n-js/src/typing';
|
||||
@@ -6,12 +6,12 @@ import { getMetaValue } from '../setup/globals/global-helpers';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class I18nService {
|
||||
private config = inject(NgSelectConfig);
|
||||
|
||||
private i18n:I18n = window.I18n;
|
||||
private instanceLocale:string;
|
||||
|
||||
constructor(
|
||||
private config:NgSelectConfig,
|
||||
) {
|
||||
constructor() {
|
||||
this.instanceLocale = getMetaValue('openproject_initializer', 'instanceLocale', 'en');
|
||||
|
||||
this.config.addTagText = this.t('js.autocomplete_ng_select.add_tag');
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Injectable, Injector, inject } from '@angular/core';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { CurrentProjectService } from 'core-app/core/current-project/current-project.service';
|
||||
import { DeviceService } from 'core-app/core/browser/device.service';
|
||||
@@ -35,6 +35,9 @@ import { queryVisible } from 'core-app/shared/helpers/dom-helpers';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class MainMenuToggleService {
|
||||
injector = inject(Injector);
|
||||
readonly deviceService = inject(DeviceService);
|
||||
|
||||
private elementWidth:number;
|
||||
|
||||
private elementMinWidth = 11;
|
||||
@@ -61,10 +64,7 @@ export class MainMenuToggleService {
|
||||
|
||||
private wasCollapsedByUser = false;
|
||||
|
||||
constructor(
|
||||
public injector:Injector,
|
||||
readonly deviceService:DeviceService,
|
||||
) {
|
||||
constructor() {
|
||||
this.initializeMenu();
|
||||
// Add resize event listener
|
||||
window.addEventListener('resize', this.onWindowResize.bind(this));
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { type FrameElement } from '@hotwired/turbo';
|
||||
import { StateService } from '@uirouter/core';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class SubmenuService {
|
||||
constructor(protected $state:StateService) {}
|
||||
protected $state = inject(StateService);
|
||||
|
||||
|
||||
reloadSubmenu(selectedQueryId:string|null, sidemenuId?:string):void {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-assignment
|
||||
|
||||
@@ -26,15 +26,15 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map, shareReplay, startWith } from 'rxjs/operators';
|
||||
import { NavigationService } from 'core-app/core/navigation/navigation.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class UrlParamsService {
|
||||
constructor(private navigation:NavigationService) {
|
||||
}
|
||||
private navigation = inject(NavigationService);
|
||||
|
||||
|
||||
public get(key:string):string|null {
|
||||
return this.searchParams.get(key);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injector, NgModule } from '@angular/core';
|
||||
import { Injector, NgModule, inject } from '@angular/core';
|
||||
import { FirstRouteService } from 'core-app/core/routing/first-route-service';
|
||||
import { UIRouterModule } from '@uirouter/angular';
|
||||
import { ApplicationBaseComponent } from 'core-app/core/routing/base/application-base.component';
|
||||
@@ -52,7 +52,9 @@ import {
|
||||
],
|
||||
})
|
||||
export class OpenprojectRouterModule {
|
||||
constructor(injector:Injector) {
|
||||
constructor() {
|
||||
const injector = inject(Injector);
|
||||
|
||||
initializeUiRouterListeners(injector);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
import { State } from '@openproject/reactivestates';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { StateCacheService } from 'core-app/core/apiv3/cache/state-cache.service';
|
||||
import { firstValueFrom, Observable } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
@@ -41,13 +41,17 @@ export const fallbackSchemaId = '__fallback';
|
||||
|
||||
@Injectable()
|
||||
export class SchemaCacheService extends StateCacheService<SchemaResource> {
|
||||
readonly states:States;
|
||||
readonly halResourceService = inject(HalResourceService);
|
||||
|
||||
fallbackSchema = this.halResourceService.createHalResourceOfClass<SchemaResource>(SchemaResource, {}, true);
|
||||
|
||||
constructor(
|
||||
readonly states:States,
|
||||
readonly halResourceService:HalResourceService,
|
||||
) {
|
||||
constructor() {
|
||||
const states = inject(States);
|
||||
|
||||
super(states.schemas);
|
||||
this.states = states;
|
||||
|
||||
this.putValue(fallbackSchemaId, this.fallbackSchema);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, Injector, ViewChild } from '@angular/core';
|
||||
import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, Injector, ViewChild, inject } from '@angular/core';
|
||||
import { InjectField } from 'core-app/shared/helpers/angular/inject-field.decorator';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { ToastService } from 'core-app/shared/components/toaster/toast.service';
|
||||
@@ -43,6 +43,13 @@ import { JobStatusModalService } from 'core-app/features/job-status/job-status-m
|
||||
standalone: false,
|
||||
})
|
||||
export class BackupComponent implements AfterViewInit {
|
||||
readonly elementRef = inject<ElementRef<HTMLElement>>(ElementRef);
|
||||
injector = inject(Injector);
|
||||
protected i18n = inject(I18nService);
|
||||
protected toastService = inject(ToastService);
|
||||
protected pathHelper = inject(PathHelperService);
|
||||
protected jobStatusModalService = inject(JobStatusModalService);
|
||||
|
||||
public text = {
|
||||
info: this.i18n.t('js.backup.info'),
|
||||
note: this.i18n.t('js.backup.note'),
|
||||
@@ -72,14 +79,7 @@ export class BackupComponent implements AfterViewInit {
|
||||
|
||||
@ViewChild('backupTokenInput') backupTokenInput:ElementRef<HTMLInputElement>;
|
||||
|
||||
constructor(
|
||||
readonly elementRef:ElementRef<HTMLElement>,
|
||||
public injector:Injector,
|
||||
protected i18n:I18nService,
|
||||
protected toastService:ToastService,
|
||||
protected pathHelper:PathHelperService,
|
||||
protected jobStatusModalService:JobStatusModalService,
|
||||
) {
|
||||
constructor() {
|
||||
this.includeAttachments = this.mayIncludeAttachments;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,10 +58,7 @@ import {
|
||||
HttpClient,
|
||||
HttpErrorResponse,
|
||||
} from '@angular/common/http';
|
||||
import {
|
||||
Injectable,
|
||||
Injector,
|
||||
} from '@angular/core';
|
||||
import { Injectable, Injector, inject } from '@angular/core';
|
||||
import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
|
||||
import { ToastService } from 'core-app/shared/components/toaster/toast.service';
|
||||
import idFromLink from 'core-app/features/hal/helpers/id-from-link';
|
||||
@@ -76,18 +73,15 @@ export type ResourceKeyInput = ApiV3ListParameters|string;
|
||||
|
||||
@Injectable()
|
||||
export abstract class ResourceStoreService<T extends { id:ID }> {
|
||||
readonly injector = inject(Injector);
|
||||
readonly http = inject(HttpClient);
|
||||
readonly apiV3Service = inject(ApiV3Service);
|
||||
readonly toastService = inject(ToastService);
|
||||
|
||||
protected store:ResourceStore<T> = this.createStore();
|
||||
|
||||
protected query = new QueryEntity(this.store);
|
||||
|
||||
constructor(
|
||||
readonly injector:Injector,
|
||||
readonly http:HttpClient,
|
||||
readonly apiV3Service:ApiV3Service,
|
||||
readonly toastService:ToastService,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Require the results for the given filter params
|
||||
* Returns a cached set if it was loaded already.
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { combineLatest, Observable } from 'rxjs';
|
||||
import {
|
||||
filter, map, take, tap,
|
||||
@@ -44,15 +44,13 @@ import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
|
||||
|
||||
@Injectable()
|
||||
export class StorageFilesResourceService {
|
||||
private readonly httpClient = inject(HttpClient);
|
||||
private readonly apiV3Service = inject(ApiV3Service);
|
||||
|
||||
private readonly store:StorageFilesStore = new StorageFilesStore();
|
||||
|
||||
private readonly query = new QueryEntity(this.store);
|
||||
|
||||
constructor(
|
||||
private readonly httpClient:HttpClient,
|
||||
private readonly apiV3Service:ApiV3Service,
|
||||
) {}
|
||||
|
||||
files(link:IHalResourceLink):Observable<IStorageFiles> {
|
||||
const value = this.store.getValue().files[link.href];
|
||||
if (value !== undefined) {
|
||||
|
||||
@@ -26,10 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
Inject,
|
||||
Injectable,
|
||||
} from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { isVisible } from 'core-app/shared/helpers/dom-helpers';
|
||||
|
||||
@@ -37,8 +34,8 @@ export const ANIMATION_RATE_MS = 100;
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class TopMenuService {
|
||||
constructor(@Inject(DOCUMENT) private document:Document) {
|
||||
}
|
||||
private document = inject<Document>(DOCUMENT);
|
||||
|
||||
|
||||
register():void {
|
||||
this.skipContentClickListener();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { renderStreamMessage } from '@hotwired/turbo';
|
||||
import { ToastService } from 'core-app/shared/components/toaster/toast.service';
|
||||
import { debugLog } from 'core-app/shared/helpers/debug_output';
|
||||
@@ -7,14 +7,10 @@ import { getMetaContent } from '../setup/globals/global-helpers';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class TurboRequestsService {
|
||||
private toast = inject(ToastService);
|
||||
|
||||
#controllers = new Map<string, AbortController>();
|
||||
|
||||
constructor(
|
||||
private toast:ToastService,
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
public request(
|
||||
url:string,
|
||||
init:RequestInit = {},
|
||||
|
||||
+6
-9
@@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import {
|
||||
ExternalQueryConfigurationService,
|
||||
@@ -11,6 +11,11 @@ import {
|
||||
standalone: false,
|
||||
})
|
||||
export class EditableQueryPropsComponent implements OnInit {
|
||||
private elementRef = inject<ElementRef<HTMLElement>>(ElementRef);
|
||||
private I18n = inject(I18nService);
|
||||
private cdRef = inject(ChangeDetectorRef);
|
||||
private externalQuery = inject(ExternalQueryConfigurationService);
|
||||
|
||||
id:string|null;
|
||||
|
||||
name:string|null;
|
||||
@@ -23,14 +28,6 @@ export class EditableQueryPropsComponent implements OnInit {
|
||||
edit_query: this.I18n.t('js.admin.type_form.edit_query'),
|
||||
};
|
||||
|
||||
constructor(
|
||||
private elementRef:ElementRef<HTMLElement>,
|
||||
private I18n:I18nService,
|
||||
private cdRef:ChangeDetectorRef,
|
||||
private externalQuery:ExternalQueryConfigurationService,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
const element = this.elementRef.nativeElement;
|
||||
this.id = element.dataset.id!;
|
||||
|
||||
@@ -26,12 +26,14 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Injectable, Injector, inject } from '@angular/core';
|
||||
import { BcfResourceCollectionPath } from 'core-app/features/bim/bcf/api/bcf-path-resources';
|
||||
import { BcfProjectPaths } from 'core-app/features/bim/bcf/api/projects/bcf-project.paths';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class BcfApiService {
|
||||
readonly injector = inject(Injector);
|
||||
|
||||
public readonly bcfApiVersion = '2.1';
|
||||
|
||||
public readonly appBasePath = window.appBasePath || '';
|
||||
@@ -41,9 +43,6 @@ export class BcfApiService {
|
||||
// /api/bcf/:version/projects
|
||||
public readonly projects = new BcfResourceCollectionPath(this.injector, this.bcfApiBase, 'projects', BcfProjectPaths);
|
||||
|
||||
constructor(readonly injector:Injector) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given string into a BCF resource path
|
||||
*
|
||||
|
||||
@@ -6,18 +6,17 @@ import {
|
||||
Observable,
|
||||
} from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
|
||||
export type AllowedExtensionKey = keyof BcfExtensionResource;
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class BcfAuthorizationService {
|
||||
readonly bcfApi = inject(BcfApiService);
|
||||
|
||||
// Poor mans caching to avoid repeatedly fetching from the backend.
|
||||
protected authorizationMap = multiInput<BcfExtensionResource>();
|
||||
|
||||
constructor(readonly bcfApi:BcfApiService) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an observable boolean whether the given action
|
||||
* is authorized in the project by using the project extensions.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Injectable, Injector, inject } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
|
||||
import { InjectField } from 'core-app/shared/helpers/angular/inject-field.decorator';
|
||||
@@ -7,6 +7,8 @@ import { CreateBcfViewpointData } from 'core-app/features/bim/bcf/api/bcf-api.mo
|
||||
|
||||
@Injectable()
|
||||
export abstract class ViewerBridgeService {
|
||||
readonly injector = inject(Injector);
|
||||
|
||||
@InjectField() state:StateService;
|
||||
|
||||
/**
|
||||
@@ -14,8 +16,6 @@ export abstract class ViewerBridgeService {
|
||||
*/
|
||||
abstract shouldShowViewer:boolean;
|
||||
|
||||
protected constructor(readonly injector:Injector) {}
|
||||
|
||||
/**
|
||||
* Get a viewpoint from the viewer
|
||||
*/
|
||||
|
||||
+12
-24
@@ -26,17 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Optional,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit, ViewChild, inject } from '@angular/core';
|
||||
import { StateService } from '@uirouter/core';
|
||||
import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
|
||||
import { NgxGalleryComponent, NgxGalleryOptions } from '@kolkov/ngx-gallery';
|
||||
@@ -62,6 +52,17 @@ import { filter, take } from 'rxjs/operators';
|
||||
standalone: false,
|
||||
})
|
||||
export class BcfWpAttributeGroupComponent extends UntilDestroyedMixin implements AfterViewInit, OnDestroy, OnInit {
|
||||
readonly state = inject(StateService);
|
||||
readonly bcfAuthorization = inject(BcfAuthorizationService);
|
||||
readonly viewerBridge = inject(ViewerBridgeService);
|
||||
readonly apiV3Service = inject(ApiV3Service);
|
||||
readonly wpCreate = inject(WorkPackageCreateService);
|
||||
readonly toastService = inject(ToastService);
|
||||
readonly bcfViewer = inject(BcfViewService, { optional: true });
|
||||
readonly cdRef = inject(ChangeDetectorRef);
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly viewpointsService = inject(ViewpointsService);
|
||||
|
||||
@Input() workPackage:WorkPackageResource;
|
||||
|
||||
@ViewChild(NgxGalleryComponent) gallery:NgxGalleryComponent;
|
||||
@@ -146,19 +147,6 @@ export class BcfWpAttributeGroupComponent extends UntilDestroyedMixin implements
|
||||
|
||||
projectId:string;
|
||||
|
||||
constructor(readonly state:StateService,
|
||||
readonly bcfAuthorization:BcfAuthorizationService,
|
||||
readonly viewerBridge:ViewerBridgeService,
|
||||
readonly apiV3Service:ApiV3Service,
|
||||
readonly wpCreate:WorkPackageCreateService,
|
||||
readonly toastService:ToastService,
|
||||
@Optional() readonly bcfViewer:BcfViewService,
|
||||
readonly cdRef:ChangeDetectorRef,
|
||||
readonly I18n:I18nService,
|
||||
readonly viewpointsService:ViewpointsService) {
|
||||
super();
|
||||
}
|
||||
|
||||
ngAfterViewInit():void {
|
||||
// Observe changes on the work package to update the viewpoints
|
||||
this.observeChanges();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Inject, Injectable, DOCUMENT } from '@angular/core';
|
||||
import { Injectable, DOCUMENT, inject } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class BcfDetectorService {
|
||||
constructor(@Inject(DOCUMENT) private documentElement:Document) {
|
||||
}
|
||||
private documentElement = inject<Document>(DOCUMENT);
|
||||
|
||||
|
||||
/**
|
||||
* Detect whether the BCF module was activated,
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
|
||||
import { HalLink } from 'core-app/features/hal/hal-link/hal-link';
|
||||
|
||||
@Injectable()
|
||||
export class BcfPathHelperService {
|
||||
constructor(readonly pathHelper:PathHelperService) {
|
||||
}
|
||||
readonly pathHelper = inject(PathHelperService);
|
||||
|
||||
|
||||
public projectImportIssuePath(projectIdentifier:string) {
|
||||
return `${this.pathHelper.projectPath(projectIdentifier)}/issues/upload`;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Injectable, Injector, inject } from '@angular/core';
|
||||
import { InjectField } from 'core-app/shared/helpers/angular/inject-field.decorator';
|
||||
import { BcfApiService } from 'core-app/features/bim/bcf/api/bcf-api.service';
|
||||
import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
|
||||
@@ -42,6 +42,8 @@ import { HalResource } from 'core-app/features/hal/resources/hal-resource';
|
||||
|
||||
@Injectable()
|
||||
export class ViewpointsService {
|
||||
readonly injector = inject(Injector);
|
||||
|
||||
topicUUID:string|number|null = null;
|
||||
|
||||
@InjectField() bcfApi:BcfApiService;
|
||||
@@ -50,8 +52,6 @@ export class ViewpointsService {
|
||||
|
||||
@InjectField() apiV3Service:ApiV3Service;
|
||||
|
||||
constructor(readonly injector:Injector) { }
|
||||
|
||||
public getViewPointResource(workPackage:WorkPackageResource, index:number):BcfViewpointPaths {
|
||||
const viewpointHref = (workPackage.bcfViewpoints as HalResource[])[index].href!;
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
//-- copyright
|
||||
// OpenProject is an open source project management software.
|
||||
// Copyright (C) the OpenProject GmbH
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injector } from '@angular/core';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { IFCViewerService } from 'core-app/features/bim/ifc_models/ifc-viewer/ifc-viewer.service';
|
||||
import { viewerBridgeServiceFactory } from 'core-app/features/bim/bcf/openproject-bcf.module';
|
||||
|
||||
describe('viewerBridgeServiceFactory', () => {
|
||||
it('falls back to an IFC viewer service when none is registered', () => {
|
||||
const injector = TestBed.inject(Injector);
|
||||
|
||||
expect(viewerBridgeServiceFactory(injector)).toBeInstanceOf(IFCViewerService);
|
||||
});
|
||||
});
|
||||
@@ -29,6 +29,8 @@
|
||||
import {
|
||||
Injector,
|
||||
NgModule,
|
||||
inject,
|
||||
runInInjectionContext,
|
||||
} from '@angular/core';
|
||||
import { OpSharedModule } from 'core-app/shared/shared.module';
|
||||
import { NgxGalleryModule } from '@kolkov/ngx-gallery';
|
||||
@@ -57,9 +59,12 @@ import { RefreshButtonComponent } from 'core-app/features/bim/ifc_models/toolbar
|
||||
*/
|
||||
export const viewerBridgeServiceFactory = (injector:Injector) => {
|
||||
if (window.navigator.userAgent.search('Revit') > -1) {
|
||||
return new RevitBridgeService(injector);
|
||||
return runInInjectionContext(injector, () => new RevitBridgeService());
|
||||
}
|
||||
return injector.get(IFCViewerService, new IFCViewerService(injector));
|
||||
|
||||
const ifcViewerService = injector.get(IFCViewerService, null);
|
||||
|
||||
return ifcViewerService ?? runInInjectionContext(injector, () => new IFCViewerService());
|
||||
};
|
||||
|
||||
@NgModule({
|
||||
@@ -93,7 +98,9 @@ export const viewerBridgeServiceFactory = (injector:Injector) => {
|
||||
export class OpenprojectBcfModule {
|
||||
static bootstrapCalled = false;
|
||||
|
||||
constructor(injector:Injector) {
|
||||
constructor() {
|
||||
const injector = inject(Injector);
|
||||
|
||||
OpenprojectBcfModule.bootstrap(injector);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,11 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { BcfViewService } from 'core-app/features/bim/ifc_models/pages/viewer/bcf-view.service';
|
||||
@@ -42,9 +38,9 @@ import { BcfViewService } from 'core-app/features/bim/ifc_models/pages/viewer/bc
|
||||
standalone: false,
|
||||
})
|
||||
export class BcfSplitLeftComponent implements OnInit {
|
||||
showViewer$:Observable<boolean>;
|
||||
private readonly bcfView = inject(BcfViewService);
|
||||
|
||||
constructor(private readonly bcfView:BcfViewService) {}
|
||||
showViewer$:Observable<boolean>;
|
||||
|
||||
ngOnInit():void {
|
||||
this.showViewer$ = this.bcfView.live$()
|
||||
|
||||
+3
-7
@@ -26,11 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { BcfViewService } from 'core-app/features/bim/ifc_models/pages/viewer/bcf-view.service';
|
||||
import { map } from 'rxjs/operators';
|
||||
@@ -42,9 +38,9 @@ import { map } from 'rxjs/operators';
|
||||
standalone: false,
|
||||
})
|
||||
export class BcfSplitRightComponent implements OnInit {
|
||||
showWorkPackages$:Observable<boolean>;
|
||||
private readonly bcfView = inject(BcfViewService);
|
||||
|
||||
constructor(private readonly bcfView:BcfViewService) {}
|
||||
showWorkPackages$:Observable<boolean>;
|
||||
|
||||
ngOnInit():void {
|
||||
this.showWorkPackages$ = this.bcfView.live$()
|
||||
|
||||
@@ -26,16 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
HostListener,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, HostListener, OnDestroy, OnInit, ViewChild, inject } from '@angular/core';
|
||||
import { IFCViewerService } from 'core-app/features/bim/ifc_models/ifc-viewer/ifc-viewer.service';
|
||||
import { IfcModelsDataService } from 'core-app/features/bim/ifc_models/pages/viewer/ifc-models-data.service';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
@@ -56,6 +47,12 @@ import { filter, take } from 'rxjs/operators';
|
||||
standalone: false,
|
||||
})
|
||||
export class IFCViewerComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
ifcData = inject(IfcModelsDataService);
|
||||
private I18n = inject(I18nService);
|
||||
private ifcViewerService = inject(IFCViewerService);
|
||||
private currentUserService = inject(CurrentUserService);
|
||||
private currentProjectService = inject(CurrentProjectService);
|
||||
|
||||
private viewInitialized$ = new Subject<void>();
|
||||
|
||||
modelCount:number = this.ifcData.models.length;
|
||||
@@ -86,14 +83,6 @@ export class IFCViewerComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||
|
||||
@ViewChild('xeokitToolbarIcons') xeokitToolbarIcons:ElementRef;
|
||||
|
||||
constructor(
|
||||
public ifcData:IfcModelsDataService,
|
||||
private I18n:I18nService,
|
||||
private ifcViewerService:IFCViewerService,
|
||||
private currentUserService:CurrentUserService,
|
||||
private currentProjectService:CurrentProjectService,
|
||||
) { }
|
||||
|
||||
ngOnInit():void {
|
||||
if (this.modelCount === 0) {
|
||||
return;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { XeokitServer } from 'core-app/features/bim/ifc_models/xeokit/xeokit-server';
|
||||
import { ViewerBridgeService } from 'core-app/features/bim/bcf/bcf-viewer-bridge/viewer-bridge.service';
|
||||
import { BehaviorSubject, Observable, of } from 'rxjs';
|
||||
@@ -123,10 +123,6 @@ export class IFCViewerService extends ViewerBridgeService {
|
||||
|
||||
@InjectField() httpClient:HttpClient;
|
||||
|
||||
constructor(readonly injector:Injector) {
|
||||
super(injector);
|
||||
}
|
||||
|
||||
public newViewer(elements:XeokitElements, projects:IfcProjectDefinition[]):void {
|
||||
const server = new XeokitServer(this.pathHelper, this.ifcModelsDataService);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
||||
|
||||
@@ -26,10 +26,9 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { WorkPackageQueryStateService } from 'core-app/features/work-packages/routing/wp-view-base/view-services/wp-view-base.service';
|
||||
import { IsolatedQuerySpace } from 'core-app/features/work-packages/directives/query-space/isolated-query-space';
|
||||
import { QueryResource } from 'core-app/features/hal/resources/query-resource';
|
||||
import { ViewerBridgeService } from 'core-app/features/bim/bcf/bcf-viewer-bridge/viewer-bridge.service';
|
||||
|
||||
@@ -43,6 +42,9 @@ export type BcfViewState = 'cards'|'viewer'|'splitTable'|'splitCards'|'table';
|
||||
|
||||
@Injectable()
|
||||
export class BcfViewService extends WorkPackageQueryStateService<BcfViewState> {
|
||||
private readonly I18n = inject(I18nService);
|
||||
private readonly viewerBridgeService = inject(ViewerBridgeService);
|
||||
|
||||
public text:Record<string, string> = {
|
||||
cards: this.I18n.t('js.views.card'),
|
||||
viewer: this.I18n.t('js.ifc_models.views.viewer'),
|
||||
@@ -59,14 +61,6 @@ export class BcfViewService extends WorkPackageQueryStateService<BcfViewState> {
|
||||
table: 'icon-view-list',
|
||||
};
|
||||
|
||||
constructor(
|
||||
private readonly I18n:I18nService,
|
||||
private readonly viewerBridgeService:ViewerBridgeService,
|
||||
protected readonly querySpace:IsolatedQuerySpace,
|
||||
) {
|
||||
super(querySpace);
|
||||
}
|
||||
|
||||
hasChanged(query:QueryResource):boolean {
|
||||
return this.current !== query.displayRepresentation;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Injector, OnInit, OnDestroy, ViewEncapsulation } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, OnInit, OnDestroy, ViewEncapsulation, inject } from '@angular/core';
|
||||
|
||||
import {
|
||||
PartitionedQuerySpacePageComponent,
|
||||
@@ -94,6 +94,10 @@ import {
|
||||
export class IFCViewerPageComponent
|
||||
extends PartitionedQuerySpacePageComponent
|
||||
implements UntilDestroyedMixin, OnInit, OnDestroy {
|
||||
readonly ifcData = inject(IfcModelsDataService);
|
||||
readonly bcfView = inject(BcfViewService);
|
||||
readonly viewerBridgeService = inject(ViewerBridgeService);
|
||||
|
||||
text = {
|
||||
title: this.I18n.t('js.bcf.management'),
|
||||
delete: this.I18n.t('js.button_delete'),
|
||||
@@ -157,15 +161,6 @@ export class IFCViewerPageComponent
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
private removeSubscription:Function;
|
||||
|
||||
constructor(
|
||||
readonly ifcData:IfcModelsDataService,
|
||||
readonly bcfView:BcfViewService,
|
||||
readonly injector:Injector,
|
||||
readonly viewerBridgeService:ViewerBridgeService,
|
||||
) {
|
||||
super(injector);
|
||||
}
|
||||
|
||||
ngOnInit():void {
|
||||
super.ngOnInit();
|
||||
|
||||
|
||||
+13
-17
@@ -26,9 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy, ChangeDetectorRef, Component, Injector, OnDestroy, OnInit,
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Injector, OnDestroy, OnInit, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { CurrentProjectService } from 'core-app/core/current-project/current-project.service';
|
||||
import { BcfPathHelperService } from 'core-app/features/bim/bcf/helper/bcf-path-helper.service';
|
||||
@@ -59,6 +57,18 @@ import { JobStatusModalService } from 'core-app/features/job-status/job-status-m
|
||||
changeDetection: ChangeDetectionStrategy.Default,
|
||||
})
|
||||
export class BcfExportButtonComponent extends UntilDestroyedMixin implements OnInit, OnDestroy {
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly currentProject = inject(CurrentProjectService);
|
||||
readonly bcfPathHelper = inject(BcfPathHelperService);
|
||||
readonly querySpace = inject(IsolatedQuerySpace);
|
||||
readonly queryUrlParamsHelper = inject(UrlParamsHelperService);
|
||||
readonly jobStatusModalService = inject(JobStatusModalService);
|
||||
readonly httpClient = inject(HttpClient);
|
||||
readonly injector = inject(Injector);
|
||||
readonly toastService = inject(ToastService);
|
||||
readonly state = inject(StateService);
|
||||
readonly cdRef = inject(ChangeDetectorRef);
|
||||
|
||||
public text = {
|
||||
export: this.I18n.t('js.bcf.export'),
|
||||
export_hover: this.I18n.t('js.bcf.export_bcf_xml_file'),
|
||||
@@ -68,20 +78,6 @@ export class BcfExportButtonComponent extends UntilDestroyedMixin implements OnI
|
||||
|
||||
public exportLink:string;
|
||||
|
||||
constructor(readonly I18n:I18nService,
|
||||
readonly currentProject:CurrentProjectService,
|
||||
readonly bcfPathHelper:BcfPathHelperService,
|
||||
readonly querySpace:IsolatedQuerySpace,
|
||||
readonly queryUrlParamsHelper:UrlParamsHelperService,
|
||||
readonly jobStatusModalService:JobStatusModalService,
|
||||
readonly httpClient:HttpClient,
|
||||
readonly injector:Injector,
|
||||
readonly toastService:ToastService,
|
||||
readonly state:StateService,
|
||||
readonly cdRef:ChangeDetectorRef) {
|
||||
super();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.querySpace.query
|
||||
.values$()
|
||||
|
||||
+5
-6
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { CurrentProjectService } from 'core-app/core/current-project/current-project.service';
|
||||
import { BcfPathHelperService } from 'core-app/features/bim/bcf/helper/bcf-path-helper.service';
|
||||
@@ -48,16 +48,15 @@ import { BcfPathHelperService } from 'core-app/features/bim/bcf/helper/bcf-path-
|
||||
changeDetection: ChangeDetectionStrategy.Default,
|
||||
})
|
||||
export class BcfImportButtonComponent {
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly currentProject = inject(CurrentProjectService);
|
||||
readonly bcfPathHelper = inject(BcfPathHelperService);
|
||||
|
||||
public text = {
|
||||
import: this.I18n.t('js.bcf.import'),
|
||||
import_hover: this.I18n.t('js.bcf.import_bcf_xml_file'),
|
||||
};
|
||||
|
||||
constructor(readonly I18n:I18nService,
|
||||
readonly currentProject:CurrentProjectService,
|
||||
readonly bcfPathHelper:BcfPathHelperService) {
|
||||
}
|
||||
|
||||
public handleClick() {
|
||||
const projectIdentifier = this.currentProject.identifier;
|
||||
if (projectIdentifier) {
|
||||
|
||||
+4
-5
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { StateService } from '@uirouter/core';
|
||||
|
||||
@@ -43,15 +43,14 @@ import { StateService } from '@uirouter/core';
|
||||
standalone: false,
|
||||
})
|
||||
export class RefreshButtonComponent {
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly state = inject(StateService);
|
||||
|
||||
public text = {
|
||||
refresh: this.I18n.t('js.bcf.refresh'),
|
||||
refresh_hover: this.I18n.t('js.bcf.refresh_work_package'),
|
||||
};
|
||||
|
||||
constructor(readonly I18n:I18nService,
|
||||
readonly state:StateService) {
|
||||
}
|
||||
|
||||
refresh() {
|
||||
void this.state.go('.', {}, { reload: true });
|
||||
}
|
||||
|
||||
+4
-5
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { IfcModelsDataService } from 'core-app/features/bim/ifc_models/pages/viewer/ifc-models-data.service';
|
||||
|
||||
@@ -49,6 +49,9 @@ import { IfcModelsDataService } from 'core-app/features/bim/ifc_models/pages/vie
|
||||
standalone: false,
|
||||
})
|
||||
export class BimManageIfcModelsButtonComponent {
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly ifcData = inject(IfcModelsDataService);
|
||||
|
||||
text = {
|
||||
manage: this.I18n.t('js.ifc_models.models.ifc_models'),
|
||||
};
|
||||
@@ -56,8 +59,4 @@ export class BimManageIfcModelsButtonComponent {
|
||||
manageAllowed = this.ifcData.allowed('manage_ifc_models');
|
||||
|
||||
manageIFCPath = this.ifcData.manageIFCPath;
|
||||
|
||||
constructor(readonly I18n:I18nService,
|
||||
readonly ifcData:IfcModelsDataService) {
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { BcfViewService } from 'core-app/features/bim/ifc_models/pages/viewer/bcf-view.service';
|
||||
|
||||
@@ -50,7 +50,8 @@ import { BcfViewService } from 'core-app/features/bim/ifc_models/pages/viewer/bc
|
||||
standalone: false,
|
||||
})
|
||||
export class BcfViewToggleButtonComponent {
|
||||
view$ = this.bcfView.live$();
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly bcfView = inject(BcfViewService);
|
||||
|
||||
constructor(readonly I18n:I18nService, readonly bcfView:BcfViewService) { }
|
||||
view$ = this.bcfView.live$();
|
||||
}
|
||||
|
||||
+6
-11
@@ -26,8 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { OPContextMenuService } from 'core-app/shared/components/op-context-menu/op-context-menu.service';
|
||||
import { Directive, ElementRef } from '@angular/core';
|
||||
import { Directive, inject } from '@angular/core';
|
||||
import { OpContextMenuTrigger } from 'core-app/shared/components/op-context-menu/handlers/op-context-menu-trigger.directive';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { StateService } from '@uirouter/core';
|
||||
@@ -48,15 +47,11 @@ import { OpContextMenuItem } from 'core-app/shared/components/op-context-menu/op
|
||||
standalone: false,
|
||||
})
|
||||
export class BcfViewToggleDropdownDirective extends OpContextMenuTrigger {
|
||||
constructor(readonly elementRef:ElementRef,
|
||||
readonly opContextMenu:OPContextMenuService,
|
||||
readonly bcfView:BcfViewService,
|
||||
readonly I18n:I18nService,
|
||||
readonly state:StateService,
|
||||
readonly wpFiltersService:WorkPackageFiltersService,
|
||||
readonly viewerBridgeService:ViewerBridgeService) {
|
||||
super(elementRef, opContextMenu);
|
||||
}
|
||||
readonly bcfView = inject(BcfViewService);
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly state = inject(StateService);
|
||||
readonly wpFiltersService = inject(WorkPackageFiltersService);
|
||||
readonly viewerBridgeService = inject(ViewerBridgeService);
|
||||
|
||||
protected open(evt:Event):void {
|
||||
this.buildItems();
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
|
||||
@@ -36,13 +36,15 @@ import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
*/
|
||||
@Injectable()
|
||||
export class RevitAddInSettingsButtonService {
|
||||
private readonly i18n = inject(I18nService);
|
||||
|
||||
private readonly labelText:string;
|
||||
|
||||
private readonly groupLabelText:string;
|
||||
|
||||
constructor(
|
||||
private readonly i18n:I18nService,
|
||||
) {
|
||||
constructor() {
|
||||
const i18n = this.i18n;
|
||||
|
||||
const onRevitAddInEnvironment = window.navigator.userAgent.search('Revit') > -1;
|
||||
|
||||
if (onRevitAddInEnvironment) {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
||||
import {
|
||||
distinctUntilChanged, filter, first, map,
|
||||
@@ -66,8 +66,8 @@ export class RevitBridgeService extends ViewerBridgeService {
|
||||
|
||||
revitMessageReceived$ = this.revitMessageReceivedSource.asObservable();
|
||||
|
||||
constructor(readonly injector:Injector) {
|
||||
super(injector);
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
if (window.RevitBridge) {
|
||||
this.hookUpRevitListener();
|
||||
|
||||
+9
-16
@@ -26,13 +26,10 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
ChangeDetectorRef, Directive, ElementRef, Injector,
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectorRef, Directive, Injector, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { AuthorisationService } from 'core-app/core/model-auth/model-auth.service';
|
||||
import { OpContextMenuTrigger } from 'core-app/shared/components/op-context-menu/handlers/op-context-menu-trigger.directive';
|
||||
import { OPContextMenuService } from 'core-app/shared/components/op-context-menu/op-context-menu.service';
|
||||
import { OpModalService } from 'core-app/shared/components/modal/modal.service';
|
||||
import { IsolatedQuerySpace } from 'core-app/features/work-packages/directives/query-space/isolated-query-space';
|
||||
import { WorkPackageInlineCreateService } from 'core-app/features/work-packages/components/wp-inline-create/wp-inline-create.service';
|
||||
@@ -43,18 +40,14 @@ import { BoardListComponent } from 'core-app/features/boards/board/board-list/bo
|
||||
standalone: false,
|
||||
})
|
||||
export class AddCardDropdownMenuDirective extends OpContextMenuTrigger {
|
||||
constructor(readonly elementRef:ElementRef,
|
||||
readonly opContextMenu:OPContextMenuService,
|
||||
readonly opModalService:OpModalService,
|
||||
readonly authorisationService:AuthorisationService,
|
||||
readonly wpInlineCreate:WorkPackageInlineCreateService,
|
||||
readonly boardList:BoardListComponent,
|
||||
readonly injector:Injector,
|
||||
readonly querySpace:IsolatedQuerySpace,
|
||||
readonly cdRef:ChangeDetectorRef,
|
||||
readonly I18n:I18nService) {
|
||||
super(elementRef, opContextMenu);
|
||||
}
|
||||
readonly opModalService = inject(OpModalService);
|
||||
readonly authorisationService = inject(AuthorisationService);
|
||||
readonly wpInlineCreate = inject(WorkPackageInlineCreateService);
|
||||
readonly boardList = inject(BoardListComponent);
|
||||
readonly injector = inject(Injector);
|
||||
readonly querySpace = inject(IsolatedQuerySpace);
|
||||
readonly cdRef = inject(ChangeDetectorRef);
|
||||
readonly I18n = inject(I18nService);
|
||||
|
||||
protected open(evt:Event) {
|
||||
this.items = this.buildItems();
|
||||
|
||||
@@ -26,12 +26,8 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Inject, OnInit, ViewChild,
|
||||
} from '@angular/core';
|
||||
import { OpModalLocalsMap } from 'core-app/shared/components/modal/modal.types';
|
||||
import { ChangeDetectionStrategy, Component, OnInit, ViewChild, inject } from '@angular/core';
|
||||
import { OpModalComponent } from 'core-app/shared/components/modal/modal.component';
|
||||
import { OpModalLocalsToken } from 'core-app/shared/components/modal/modal.service';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { Board } from 'core-app/features/boards/board/board';
|
||||
import { BoardService } from 'core-app/features/boards/board/board.service';
|
||||
@@ -58,6 +54,14 @@ import { HalResource } from 'core-app/features/hal/resources/hal-resource';
|
||||
changeDetection: ChangeDetectionStrategy.Default,
|
||||
})
|
||||
export class AddListModalComponent extends OpModalComponent implements OnInit {
|
||||
readonly boardActions = inject(BoardActionsRegistryService);
|
||||
readonly halNotification = inject(HalResourceNotificationService);
|
||||
readonly boardService = inject(BoardService);
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly apiV3Service = inject(ApiV3Service);
|
||||
readonly currentProject = inject(CurrentProjectService);
|
||||
readonly pathHelper = inject(PathHelperService);
|
||||
|
||||
@ViewChild(OpAutocompleterComponent, { static: true }) public ngSelectComponent:OpAutocompleterComponent;
|
||||
|
||||
getAutocompleterData = (searchTerm:string):Observable<HalResource[]> => {
|
||||
@@ -112,19 +116,6 @@ export class AddListModalComponent extends OpModalComponent implements OnInit {
|
||||
/** Whether the no results warning is displayed */
|
||||
showWarning = false;
|
||||
|
||||
constructor(readonly elementRef:ElementRef,
|
||||
@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,
|
||||
readonly cdRef:ChangeDetectorRef,
|
||||
readonly boardActions:BoardActionsRegistryService,
|
||||
readonly halNotification:HalResourceNotificationService,
|
||||
readonly boardService:BoardService,
|
||||
readonly I18n:I18nService,
|
||||
readonly apiV3Service:ApiV3Service,
|
||||
readonly currentProject:CurrentProjectService,
|
||||
readonly pathHelper:PathHelperService) {
|
||||
super(locals, cdRef, elementRef);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
super.ngOnInit();
|
||||
this.board = this.locals.board;
|
||||
|
||||
+4
-5
@@ -25,7 +25,7 @@
|
||||
//
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Input, inject } from '@angular/core';
|
||||
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { UserResource } from 'core-app/features/hal/resources/user-resource';
|
||||
@@ -41,13 +41,12 @@ import { UserResource } from 'core-app/features/hal/resources/user-resource';
|
||||
changeDetection: ChangeDetectionStrategy.Default,
|
||||
})
|
||||
export class AssigneeBoardHeaderComponent {
|
||||
readonly pathHelper = inject(PathHelperService);
|
||||
readonly I18n = inject(I18nService);
|
||||
|
||||
@Input('resource') public user:UserResource;
|
||||
|
||||
text = {
|
||||
assignee: this.I18n.t('js.work_packages.properties.assignee'),
|
||||
};
|
||||
|
||||
constructor(readonly pathHelper:PathHelperService,
|
||||
readonly I18n:I18nService) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { BoardListsService } from 'core-app/features/boards/board/board-list/boa
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
|
||||
import { CurrentProjectService } from 'core-app/core/current-project/current-project.service';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Injectable, Injector, inject } from '@angular/core';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { IFieldSchema } from 'core-app/shared/components/fields/field.base';
|
||||
import { WorkPackageChangeset } from 'core-app/features/work-packages/components/wp-edit/work-package-changeset';
|
||||
@@ -25,15 +25,15 @@ import idFromLink from 'core-app/features/hal/helpers/id-from-link';
|
||||
|
||||
@Injectable()
|
||||
export abstract class BoardActionService {
|
||||
constructor(readonly injector:Injector,
|
||||
protected boardListsService:BoardListsService,
|
||||
protected I18n:I18nService,
|
||||
protected halResourceService:HalResourceService,
|
||||
protected pathHelper:PathHelperService,
|
||||
protected currentProject:CurrentProjectService,
|
||||
protected apiV3Service:ApiV3Service,
|
||||
protected schemaCache:SchemaCacheService) {
|
||||
}
|
||||
readonly injector = inject(Injector);
|
||||
protected boardListsService = inject(BoardListsService);
|
||||
protected I18n = inject(I18nService);
|
||||
protected halResourceService = inject(HalResourceService);
|
||||
protected pathHelper = inject(PathHelperService);
|
||||
protected currentProject = inject(CurrentProjectService);
|
||||
protected apiV3Service = inject(ApiV3Service);
|
||||
protected schemaCache = inject(SchemaCacheService);
|
||||
|
||||
|
||||
/**
|
||||
* Get the attribute name
|
||||
|
||||
+3
-4
@@ -25,7 +25,7 @@
|
||||
//
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Input, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { StatusResource } from 'core-app/features/hal/resources/status-resource';
|
||||
|
||||
@@ -40,12 +40,11 @@ import { StatusResource } from 'core-app/features/hal/resources/status-resource'
|
||||
changeDetection: ChangeDetectionStrategy.Default,
|
||||
})
|
||||
export class StatusBoardHeaderComponent {
|
||||
readonly I18n = inject(I18nService);
|
||||
|
||||
@Input('resource') public status:StatusResource;
|
||||
|
||||
text = {
|
||||
status: this.I18n.t('js.work_packages.properties.status'),
|
||||
};
|
||||
|
||||
constructor(readonly I18n:I18nService) {
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -25,7 +25,7 @@
|
||||
//
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Input, inject } from '@angular/core';
|
||||
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { HalResource } from 'core-app/features/hal/resources/hal-resource';
|
||||
@@ -42,6 +42,9 @@ import idFromLink from 'core-app/features/hal/helpers/id-from-link';
|
||||
changeDetection: ChangeDetectionStrategy.Default,
|
||||
})
|
||||
export class SubprojectBoardHeaderComponent {
|
||||
readonly pathHelper = inject(PathHelperService);
|
||||
readonly I18n = inject(I18nService);
|
||||
|
||||
@Input() public resource:HalResource;
|
||||
|
||||
idFromLink = idFromLink;
|
||||
@@ -49,8 +52,4 @@ export class SubprojectBoardHeaderComponent {
|
||||
text = {
|
||||
project: this.I18n.t('js.label_project'),
|
||||
};
|
||||
|
||||
constructor(readonly pathHelper:PathHelperService,
|
||||
readonly I18n:I18nService) {
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -25,7 +25,7 @@
|
||||
//
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Input, OnInit, inject } from '@angular/core';
|
||||
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
|
||||
@@ -43,6 +43,9 @@ import idFromLink from 'core-app/features/hal/helpers/id-from-link';
|
||||
changeDetection: ChangeDetectionStrategy.Default,
|
||||
})
|
||||
export class SubtasksBoardHeaderComponent implements OnInit {
|
||||
readonly pathHelper = inject(PathHelperService);
|
||||
readonly I18n = inject(I18nService);
|
||||
|
||||
@Input() public resource:WorkPackageResource;
|
||||
|
||||
idFromLink = idFromLink;
|
||||
@@ -53,10 +56,6 @@ export class SubtasksBoardHeaderComponent implements OnInit {
|
||||
|
||||
typeHighlightingClass:string;
|
||||
|
||||
constructor(readonly pathHelper:PathHelperService,
|
||||
readonly I18n:I18nService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.typeHighlightingClass = Highlighting.inlineClass('type', this.resource.type.id!);
|
||||
}
|
||||
|
||||
+5
-5
@@ -25,7 +25,7 @@
|
||||
//
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Input, inject } from '@angular/core';
|
||||
import { VersionResource } from 'core-app/features/hal/resources/version-resource';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
|
||||
@@ -41,11 +41,11 @@ import { PathHelperService } from 'core-app/core/path-helper/path-helper.service
|
||||
changeDetection: ChangeDetectionStrategy.Default,
|
||||
})
|
||||
export class VersionBoardHeaderComponent {
|
||||
@Input('resource') public version:VersionResource;
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly pathHelper = inject(PathHelperService);
|
||||
|
||||
constructor(readonly I18n:I18nService,
|
||||
readonly pathHelper:PathHelperService) {
|
||||
}
|
||||
// eslint-disable-next-line @angular-eslint/no-input-rename
|
||||
@Input('resource') public version:VersionResource;
|
||||
|
||||
public text = {
|
||||
isLocked: this.I18n.t('js.boards.version.is_locked'),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AfterViewInit, ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { AfterViewInit, ChangeDetectionStrategy, Component, Input, inject } from '@angular/core';
|
||||
import { Board } from 'core-app/features/boards/board/board';
|
||||
import { CurrentProjectService } from 'core-app/core/current-project/current-project.service';
|
||||
import { WorkPackageStatesInitializationService } from 'core-app/features/work-packages/components/wp-list/wp-states-initialization.service';
|
||||
@@ -23,22 +23,20 @@ import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
|
||||
changeDetection: ChangeDetectionStrategy.Default,
|
||||
})
|
||||
export class BoardFilterComponent extends UntilDestroyedMixin implements AfterViewInit {
|
||||
private readonly currentProjectService = inject(CurrentProjectService);
|
||||
private readonly querySpace = inject(IsolatedQuerySpace);
|
||||
private readonly apiV3Service = inject(ApiV3Service);
|
||||
private readonly halResourceService = inject(HalResourceService);
|
||||
private readonly wpStatesInitialization = inject(WorkPackageStatesInitializationService);
|
||||
private readonly wpTableFilters = inject(WorkPackageViewFiltersService);
|
||||
private readonly urlParamsHelper = inject(UrlParamsHelperService);
|
||||
private readonly boardFilters = inject(BoardFiltersService);
|
||||
|
||||
/** Current active */
|
||||
@Input() public board$:Observable<Board>;
|
||||
|
||||
initialized = false;
|
||||
|
||||
constructor(private readonly currentProjectService:CurrentProjectService,
|
||||
private readonly querySpace:IsolatedQuerySpace,
|
||||
private readonly apiV3Service:ApiV3Service,
|
||||
private readonly halResourceService:HalResourceService,
|
||||
private readonly wpStatesInitialization:WorkPackageStatesInitializationService,
|
||||
private readonly wpTableFilters:WorkPackageViewFiltersService,
|
||||
private readonly urlParamsHelper:UrlParamsHelperService,
|
||||
private readonly boardFilters:BoardFiltersService) {
|
||||
super();
|
||||
}
|
||||
|
||||
ngAfterViewInit():void {
|
||||
if (!this.board$) {
|
||||
return;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
|
||||
import {
|
||||
WorkPackageInlineCreateService,
|
||||
@@ -40,13 +40,8 @@ import { Observable } from 'rxjs';
|
||||
|
||||
@Injectable()
|
||||
export class BoardInlineCreateService extends WorkPackageInlineCreateService {
|
||||
constructor(
|
||||
readonly injector:Injector,
|
||||
protected readonly querySpace:IsolatedQuerySpace,
|
||||
protected readonly halResourceService:HalResourceService,
|
||||
) {
|
||||
super(injector);
|
||||
}
|
||||
protected readonly querySpace = inject(IsolatedQuerySpace);
|
||||
protected readonly halResourceService = inject(HalResourceService);
|
||||
|
||||
/**
|
||||
* A separate reference pane for the inline create component
|
||||
|
||||
@@ -26,9 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy, Component, EventEmitter, Input, Output,
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { AuthorisationService } from 'core-app/core/model-auth/model-auth.service';
|
||||
import { OpModalService } from 'core-app/shared/components/modal/modal.service';
|
||||
@@ -49,18 +47,17 @@ import { BoardActionService } from 'core-app/features/boards/board/board-actions
|
||||
changeDetection: ChangeDetectionStrategy.Default,
|
||||
})
|
||||
export class BoardListMenuComponent {
|
||||
readonly opModalService = inject(OpModalService);
|
||||
readonly authorisationService = inject(AuthorisationService);
|
||||
private readonly querySpace = inject(IsolatedQuerySpace);
|
||||
private readonly boardService = inject(BoardService);
|
||||
private readonly boardActionRegistry = inject(BoardActionsRegistryService);
|
||||
readonly I18n = inject(I18nService);
|
||||
|
||||
@Input() board:Board;
|
||||
|
||||
@Output() onRemove = new EventEmitter<void>();
|
||||
|
||||
constructor(readonly opModalService:OpModalService,
|
||||
readonly authorisationService:AuthorisationService,
|
||||
private readonly querySpace:IsolatedQuerySpace,
|
||||
private readonly boardService:BoardService,
|
||||
private readonly boardActionRegistry:BoardActionsRegistryService,
|
||||
readonly I18n:I18nService) {
|
||||
}
|
||||
|
||||
public get menuItems() {
|
||||
return async () => {
|
||||
const items:OpContextMenuItem[] = [
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
inject,
|
||||
Injector,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
@@ -19,7 +18,6 @@ import {
|
||||
import { WorkPackageInlineCreateService } from 'core-app/features/work-packages/components/wp-inline-create/wp-inline-create.service';
|
||||
import { BoardInlineCreateService } from 'core-app/features/boards/board/board-list/board-inline-create.service';
|
||||
import { AbstractWidgetComponent } from 'core-app/shared/components/grids/widgets/abstract-widget.component';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { ToastService } from 'core-app/shared/components/toaster/toast.service';
|
||||
import { IsolatedQuerySpace } from 'core-app/features/work-packages/directives/query-space/isolated-query-space';
|
||||
import { Board } from 'core-app/features/boards/board/board';
|
||||
@@ -89,6 +87,31 @@ export interface DisabledButtonPlaceholder {
|
||||
standalone: false,
|
||||
})
|
||||
export class BoardListComponent extends AbstractWidgetComponent implements OnInit, OnDestroy {
|
||||
readonly apiv3Service = inject(ApiV3Service);
|
||||
readonly state = inject(StateService);
|
||||
readonly cdRef = inject(ChangeDetectorRef);
|
||||
readonly transitions = inject(TransitionService);
|
||||
readonly boardFilters = inject(BoardFiltersService);
|
||||
readonly toastService = inject(ToastService);
|
||||
readonly querySpace = inject(IsolatedQuerySpace);
|
||||
readonly halNotification = inject(HalResourceNotificationService);
|
||||
readonly halEvents = inject(HalEventsService);
|
||||
readonly wpStatesInitialization = inject(WorkPackageStatesInitializationService);
|
||||
readonly wpViewFocusService = inject(WorkPackageViewFocusService);
|
||||
readonly wpViewSelectionService = inject(WorkPackageViewSelectionService);
|
||||
readonly boardListCrossSelectionService = inject(BoardListCrossSelectionService);
|
||||
readonly authorisationService = inject(AuthorisationService);
|
||||
readonly wpInlineCreate = inject(WorkPackageInlineCreateService);
|
||||
readonly halEditing = inject(HalResourceEditingService);
|
||||
readonly loadingIndicator = inject(LoadingIndicatorService);
|
||||
readonly schemaCache = inject(SchemaCacheService);
|
||||
readonly boardService = inject(BoardService);
|
||||
readonly boardActionRegistry = inject(BoardActionsRegistryService);
|
||||
readonly causedUpdates = inject(CausedUpdatesService);
|
||||
readonly keepTab = inject(KeepTabService);
|
||||
readonly currentProject = inject(CurrentProjectService);
|
||||
readonly pathHelper = inject(PathHelperService);
|
||||
|
||||
/** Output fired upon query removal */
|
||||
@Output() onRemove = new EventEmitter<void>();
|
||||
|
||||
@@ -127,13 +150,15 @@ export class BoardListComponent extends AbstractWidgetComponent implements OnIni
|
||||
|
||||
public columnsQueryProps:any;
|
||||
|
||||
public text = {
|
||||
addCard: this.I18n.t('js.boards.add_card'),
|
||||
updateSuccessful: this.I18n.t('js.notice_successful_update'),
|
||||
areYouSure: this.I18n.t('js.text_are_you_sure'),
|
||||
unnamed_list: this.I18n.t('js.boards.label_unnamed_list'),
|
||||
click_to_remove: this.I18n.t('js.boards.click_to_remove_list'),
|
||||
};
|
||||
public get text() {
|
||||
return {
|
||||
addCard: this.i18n.t('js.boards.add_card'),
|
||||
updateSuccessful: this.i18n.t('js.notice_successful_update'),
|
||||
areYouSure: this.i18n.t('js.text_are_you_sure'),
|
||||
unnamed_list: this.i18n.t('js.boards.label_unnamed_list'),
|
||||
click_to_remove: this.i18n.t('js.boards.click_to_remove_list'),
|
||||
};
|
||||
}
|
||||
|
||||
/** Are we allowed to remove and drag & drop elements ? */
|
||||
public canDragInto = false;
|
||||
@@ -153,37 +178,6 @@ export class BoardListComponent extends AbstractWidgetComponent implements OnIni
|
||||
|
||||
private readonly states = inject(States);
|
||||
|
||||
constructor(
|
||||
readonly apiv3Service:ApiV3Service,
|
||||
readonly I18n:I18nService,
|
||||
readonly state:StateService,
|
||||
readonly cdRef:ChangeDetectorRef,
|
||||
readonly transitions:TransitionService,
|
||||
readonly boardFilters:BoardFiltersService,
|
||||
readonly toastService:ToastService,
|
||||
readonly querySpace:IsolatedQuerySpace,
|
||||
readonly halNotification:HalResourceNotificationService,
|
||||
readonly halEvents:HalEventsService,
|
||||
readonly wpStatesInitialization:WorkPackageStatesInitializationService,
|
||||
readonly wpViewFocusService:WorkPackageViewFocusService,
|
||||
readonly wpViewSelectionService:WorkPackageViewSelectionService,
|
||||
readonly boardListCrossSelectionService:BoardListCrossSelectionService,
|
||||
readonly authorisationService:AuthorisationService,
|
||||
readonly wpInlineCreate:WorkPackageInlineCreateService,
|
||||
readonly injector:Injector,
|
||||
readonly halEditing:HalResourceEditingService,
|
||||
readonly loadingIndicator:LoadingIndicatorService,
|
||||
readonly schemaCache:SchemaCacheService,
|
||||
readonly boardService:BoardService,
|
||||
readonly boardActionRegistry:BoardActionsRegistryService,
|
||||
readonly causedUpdates:CausedUpdatesService,
|
||||
readonly keepTab:KeepTabService,
|
||||
readonly currentProject:CurrentProjectService,
|
||||
readonly pathHelper:PathHelperService,
|
||||
) {
|
||||
super(I18n, injector);
|
||||
}
|
||||
|
||||
ngOnInit():void {
|
||||
// Unset the isNew flag
|
||||
this.initiallyFocused = this.resource.isNewWidget;
|
||||
@@ -257,7 +251,7 @@ export class BoardListComponent extends AbstractWidgetComponent implements OnIni
|
||||
}
|
||||
|
||||
public get errorMessage() {
|
||||
return this.I18n.t('js.boards.error_loading_the_list', { error_message: this.loadingError });
|
||||
return this.i18n.t('js.boards.error_loading_the_list', { error_message: this.loadingError });
|
||||
}
|
||||
|
||||
public canMove(workPackage:WorkPackageResource) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { CurrentProjectService } from 'core-app/core/current-project/current-project.service';
|
||||
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
|
||||
import { QueryResource } from 'core-app/features/hal/resources/query-resource';
|
||||
@@ -19,18 +19,15 @@ import { IOPFieldSchema } from 'core-app/features/hal/interfaces';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class BoardListsService {
|
||||
private readonly CurrentProject = inject(CurrentProjectService);
|
||||
private readonly pathHelper = inject(PathHelperService);
|
||||
private readonly apiV3Service = inject(ApiV3Service);
|
||||
private readonly halResourceService = inject(HalResourceService);
|
||||
private readonly toastService = inject(ToastService);
|
||||
private readonly I18n = inject(I18nService);
|
||||
|
||||
private v3 = this.pathHelper.api.v3;
|
||||
|
||||
constructor(
|
||||
private readonly CurrentProject:CurrentProjectService,
|
||||
private readonly pathHelper:PathHelperService,
|
||||
private readonly apiV3Service:ApiV3Service,
|
||||
private readonly halResourceService:HalResourceService,
|
||||
private readonly toastService:ToastService,
|
||||
private readonly I18n:I18nService) {
|
||||
|
||||
}
|
||||
|
||||
private create(params:object, filters:ApiV3Filter[]):Observable<QueryResource> {
|
||||
const filterJson = JSON.stringify(filters);
|
||||
|
||||
|
||||
+7
-12
@@ -26,14 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
Injector,
|
||||
Input,
|
||||
OnDestroy,
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, Injector, Input, OnDestroy, inject } from '@angular/core';
|
||||
import { populateInputsFromDataset } from 'core-app/shared/components/dataset-inputs';
|
||||
import {
|
||||
WorkPackageIsolatedQuerySpaceDirective,
|
||||
@@ -64,12 +57,14 @@ import { QueryUpdatedService } from 'core-app/features/boards/board/query-update
|
||||
standalone: false,
|
||||
})
|
||||
export class BoardEntryComponent implements OnDestroy {
|
||||
readonly elementRef = inject(ElementRef);
|
||||
readonly injector = inject(Injector);
|
||||
|
||||
@Input() boardId:string;
|
||||
|
||||
constructor(
|
||||
readonly elementRef:ElementRef,
|
||||
readonly injector:Injector,
|
||||
) {
|
||||
constructor() {
|
||||
const injector = this.injector;
|
||||
|
||||
populateInputsFromDataset(this);
|
||||
|
||||
document.body.classList.add('router--boards-full-view');
|
||||
|
||||
+18
-22
@@ -54,6 +54,24 @@ import { resolveRoutingId } from 'core-app/features/work-packages/helpers/work-p
|
||||
standalone: false,
|
||||
})
|
||||
export class BoardListContainerComponent extends UntilDestroyedMixin implements OnInit {
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly state = inject(StateService);
|
||||
readonly toastService = inject(ToastService);
|
||||
readonly halNotification = inject(HalResourceNotificationService);
|
||||
readonly boardComponent = inject(BoardPartitionedPageComponent);
|
||||
readonly BoardList = inject(BoardListsService);
|
||||
readonly boardActionRegistry = inject(BoardActionsRegistryService);
|
||||
readonly opModalService = inject(OpModalService);
|
||||
readonly injector = inject(Injector);
|
||||
readonly apiV3Service = inject(ApiV3Service);
|
||||
readonly Boards = inject(BoardService);
|
||||
readonly boardListCrossSelectionService = inject(BoardListCrossSelectionService);
|
||||
readonly Drag = inject(DragAndDropService);
|
||||
readonly apiv3Service = inject(ApiV3Service);
|
||||
readonly QueryUpdated = inject(QueryUpdatedService);
|
||||
readonly pathHelper = inject(PathHelperService);
|
||||
readonly currentProject = inject(CurrentProjectService);
|
||||
|
||||
@Input() boardId:string;
|
||||
text = {
|
||||
delete: this.I18n.t('js.button_delete'),
|
||||
@@ -96,28 +114,6 @@ export class BoardListContainerComponent extends UntilDestroyedMixin implements
|
||||
|
||||
private readonly wpStates = inject(States);
|
||||
|
||||
constructor(
|
||||
readonly I18n:I18nService,
|
||||
readonly state:StateService,
|
||||
readonly toastService:ToastService,
|
||||
readonly halNotification:HalResourceNotificationService,
|
||||
readonly boardComponent:BoardPartitionedPageComponent,
|
||||
readonly BoardList:BoardListsService,
|
||||
readonly boardActionRegistry:BoardActionsRegistryService,
|
||||
readonly opModalService:OpModalService,
|
||||
readonly injector:Injector,
|
||||
readonly apiV3Service:ApiV3Service,
|
||||
readonly Boards:BoardService,
|
||||
readonly boardListCrossSelectionService:BoardListCrossSelectionService,
|
||||
readonly Drag:DragAndDropService,
|
||||
readonly apiv3Service:ApiV3Service,
|
||||
readonly QueryUpdated:QueryUpdatedService,
|
||||
readonly pathHelper:PathHelperService,
|
||||
readonly currentProject:CurrentProjectService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
ngOnInit():void {
|
||||
const id:string = this.boardId || this.state.params.board_id?.toString();
|
||||
this.board$ = this
|
||||
|
||||
+15
-26
@@ -1,11 +1,4 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
Injector,
|
||||
Input,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Injector, Input, OnInit, inject } from '@angular/core';
|
||||
import {
|
||||
DynamicComponentDefinition,
|
||||
ToolbarButtonComponentDefinition,
|
||||
@@ -60,6 +53,20 @@ export function boardCardViewHandlerFactory(injector:Injector) {
|
||||
standalone: false,
|
||||
})
|
||||
export class BoardPartitionedPageComponent extends UntilDestroyedMixin implements OnInit {
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly cdRef = inject(ChangeDetectorRef);
|
||||
readonly state = inject(StateService);
|
||||
readonly toastService = inject(ToastService);
|
||||
readonly halNotification = inject(HalResourceNotificationService);
|
||||
readonly injector = inject(Injector);
|
||||
readonly apiV3Service = inject(ApiV3Service);
|
||||
readonly boardFilters = inject(BoardFiltersService);
|
||||
readonly Boards = inject(BoardService);
|
||||
readonly titleService = inject(OpTitleService);
|
||||
readonly submenuService = inject(SubmenuService);
|
||||
readonly pathHelperService = inject(PathHelperService);
|
||||
readonly currentProject = inject(CurrentProjectService);
|
||||
|
||||
@Input() boardId:string;
|
||||
text = {
|
||||
button_more: this.I18n.t('js.button_more'),
|
||||
@@ -129,24 +136,6 @@ export class BoardPartitionedPageComponent extends UntilDestroyedMixin implement
|
||||
},
|
||||
];
|
||||
|
||||
constructor(
|
||||
readonly I18n:I18nService,
|
||||
readonly cdRef:ChangeDetectorRef,
|
||||
readonly state:StateService,
|
||||
readonly toastService:ToastService,
|
||||
readonly halNotification:HalResourceNotificationService,
|
||||
readonly injector:Injector,
|
||||
readonly apiV3Service:ApiV3Service,
|
||||
readonly boardFilters:BoardFiltersService,
|
||||
readonly Boards:BoardService,
|
||||
readonly titleService:OpTitleService,
|
||||
readonly submenuService:SubmenuService,
|
||||
readonly pathHelperService:PathHelperService,
|
||||
readonly currentProject:CurrentProjectService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
ngOnInit():void {
|
||||
// Ensure board is being loaded
|
||||
this.Boards.loadAllBoards();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { HalResourceService } from 'core-app/features/hal/services/hal-resource.service';
|
||||
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
|
||||
import { CurrentProjectService } from 'core-app/core/current-project/current-project.service';
|
||||
@@ -10,6 +10,12 @@ import { ApiV3Service } from 'core-app/core/apiv3/api-v3.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class BoardService {
|
||||
protected apiV3Service = inject(ApiV3Service);
|
||||
protected PathHelper = inject(PathHelperService);
|
||||
protected CurrentProject = inject(CurrentProjectService);
|
||||
protected halResourceService = inject(HalResourceService);
|
||||
protected I18n = inject(I18nService);
|
||||
|
||||
public currentBoard$:BehaviorSubject<string|null> = new BehaviorSubject<string|null>(null);
|
||||
|
||||
private loadAllPromise:Promise<Board[]>|undefined;
|
||||
@@ -21,15 +27,6 @@ export class BoardService {
|
||||
unnamed_list: this.I18n.t('js.boards.label_unnamed_list'),
|
||||
};
|
||||
|
||||
constructor(
|
||||
protected apiV3Service:ApiV3Service,
|
||||
protected PathHelper:PathHelperService,
|
||||
protected CurrentProject:CurrentProjectService,
|
||||
protected halResourceService:HalResourceService,
|
||||
protected I18n:I18nService,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all boards in the current scope of the project
|
||||
*
|
||||
|
||||
+8
-27
@@ -1,19 +1,5 @@
|
||||
import {
|
||||
ApplicationRef,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ComponentFactoryResolver,
|
||||
ElementRef,
|
||||
Inject,
|
||||
Injector,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { OpModalLocalsMap } from 'core-app/shared/components/modal/modal.types';
|
||||
import { ApplicationRef, ChangeDetectionStrategy, Component, ComponentFactoryResolver, ElementRef, Injector, OnDestroy, OnInit, ViewChild, inject } from '@angular/core';
|
||||
import { OpModalComponent } from 'core-app/shared/components/modal/modal.component';
|
||||
import { OpModalLocalsToken } from 'core-app/shared/components/modal/modal.service';
|
||||
import {
|
||||
ActiveTabInterface,
|
||||
TabComponent,
|
||||
@@ -34,6 +20,13 @@ import { Board } from 'core-app/features/boards/board/board';
|
||||
changeDetection: ChangeDetectionStrategy.Default,
|
||||
})
|
||||
export class BoardConfigurationModalComponent extends OpModalComponent implements OnInit, OnDestroy {
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly boardService = inject(BoardService);
|
||||
readonly boardConfigurationService = inject(BoardConfigurationService);
|
||||
readonly injector = inject(Injector);
|
||||
readonly appRef = inject(ApplicationRef);
|
||||
readonly componentFactoryResolver = inject(ComponentFactoryResolver);
|
||||
|
||||
public text = {
|
||||
title: this.I18n.t('js.boards.configuration_modal.title'),
|
||||
closePopup: this.I18n.t('js.close_popup_title'),
|
||||
@@ -48,18 +41,6 @@ export class BoardConfigurationModalComponent extends OpModalComponent implement
|
||||
// And a reference to the actual portal host interface
|
||||
public tabPortalHost:TabPortalOutlet;
|
||||
|
||||
constructor(@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,
|
||||
readonly I18n:I18nService,
|
||||
readonly boardService:BoardService,
|
||||
readonly boardConfigurationService:BoardConfigurationService,
|
||||
readonly injector:Injector,
|
||||
readonly appRef:ApplicationRef,
|
||||
readonly componentFactoryResolver:ComponentFactoryResolver,
|
||||
readonly cdRef:ChangeDetectorRef,
|
||||
readonly elementRef:ElementRef) {
|
||||
super(locals, cdRef, elementRef);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.element = this.elementRef.nativeElement as HTMLElement;
|
||||
|
||||
|
||||
+3
-4
@@ -1,10 +1,12 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { TabInterface } from 'core-app/features/work-packages/components/wp-table/configuration-modal/tab-portal-outlet';
|
||||
import { BoardHighlightingTabComponent } from 'core-app/features/boards/board/configuration-modal/tabs/highlighting-tab.component';
|
||||
|
||||
@Injectable()
|
||||
export class BoardConfigurationService {
|
||||
readonly I18n = inject(I18nService);
|
||||
|
||||
protected _tabs:TabInterface[] = [
|
||||
{
|
||||
id: 'highlighting',
|
||||
@@ -13,9 +15,6 @@ export class BoardConfigurationService {
|
||||
},
|
||||
];
|
||||
|
||||
constructor(readonly I18n:I18nService) {
|
||||
}
|
||||
|
||||
public get tabs() {
|
||||
return this._tabs;
|
||||
}
|
||||
|
||||
+5
-6
@@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component, Inject, Injector, OnInit } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Injector, OnInit, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { TabComponent } from 'core-app/features/work-packages/components/wp-table/configuration-modal/tab-portal-outlet';
|
||||
import { OpModalLocalsMap } from 'core-app/shared/components/modal/modal.types';
|
||||
@@ -15,6 +15,10 @@ import { CardHighlightingMode } from 'core-app/features/work-packages/components
|
||||
changeDetection: ChangeDetectionStrategy.Default,
|
||||
})
|
||||
export class BoardHighlightingTabComponent implements TabComponent, OnInit {
|
||||
readonly injector = inject(Injector);
|
||||
locals = inject<OpModalLocalsMap>(OpModalLocalsToken);
|
||||
readonly I18n = inject(I18nService);
|
||||
|
||||
// Highlighting mode
|
||||
public highlightingMode:CardHighlightingMode = 'none';
|
||||
|
||||
@@ -35,11 +39,6 @@ export class BoardHighlightingTabComponent implements TabComponent, OnInit {
|
||||
},
|
||||
};
|
||||
|
||||
constructor(readonly injector:Injector,
|
||||
@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,
|
||||
readonly I18n:I18nService) {
|
||||
}
|
||||
|
||||
public onSave() {
|
||||
this.updateMode(this.highlightingMode);
|
||||
this.board.highlightingMode = this.highlightingMode;
|
||||
|
||||
+13
-24
@@ -26,17 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
EventEmitter,
|
||||
Input,
|
||||
Output,
|
||||
ViewChild,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output, ViewChild, ViewEncapsulation, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { catchError, map, tap } from 'rxjs/operators';
|
||||
@@ -66,6 +56,18 @@ import { HalResourceService } from 'core-app/features/hal/services/hal-resource.
|
||||
changeDetection: ChangeDetectionStrategy.Default,
|
||||
})
|
||||
export class BoardInlineAddAutocompleterComponent implements AfterViewInit {
|
||||
private readonly querySpace = inject(IsolatedQuerySpace);
|
||||
private readonly pathHelper = inject(PathHelperService);
|
||||
private readonly apiV3Service = inject(ApiV3Service);
|
||||
private readonly urlParamsHelper = inject(UrlParamsHelperService);
|
||||
private readonly notificationService = inject(WorkPackageNotificationService);
|
||||
private readonly CurrentProject = inject(CurrentProjectService);
|
||||
private readonly halResourceService = inject(HalResourceService);
|
||||
private readonly schemaCacheService = inject(SchemaCacheService);
|
||||
private readonly cdRef = inject(ChangeDetectorRef);
|
||||
private readonly I18n = inject(I18nService);
|
||||
private readonly wpCardDragDrop = inject(WorkPackageCardDragAndDropService);
|
||||
|
||||
readonly text = {
|
||||
placeholder: this.I18n.t('js.relations_autocomplete.placeholder'),
|
||||
};
|
||||
@@ -119,19 +121,6 @@ export class BoardInlineAddAutocompleterComponent implements AfterViewInit {
|
||||
|
||||
@Output() onReferenced = new EventEmitter<WorkPackageResource>();
|
||||
|
||||
constructor(private readonly querySpace:IsolatedQuerySpace,
|
||||
private readonly pathHelper:PathHelperService,
|
||||
private readonly apiV3Service:ApiV3Service,
|
||||
private readonly urlParamsHelper:UrlParamsHelperService,
|
||||
private readonly notificationService:WorkPackageNotificationService,
|
||||
private readonly CurrentProject:CurrentProjectService,
|
||||
private readonly halResourceService:HalResourceService,
|
||||
private readonly schemaCacheService:SchemaCacheService,
|
||||
private readonly cdRef:ChangeDetectorRef,
|
||||
private readonly I18n:I18nService,
|
||||
private readonly wpCardDragDrop:WorkPackageCardDragAndDropService) {
|
||||
}
|
||||
|
||||
ngAfterViewInit():void {
|
||||
if (!this.ngSelectComponent.ngSelectInstance) {
|
||||
return;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { interval } from 'rxjs';
|
||||
import { filter, startWith, switchMap } from 'rxjs/operators';
|
||||
import { ActiveWindowService } from 'core-app/core/active-window/active-window.service';
|
||||
@@ -8,9 +8,9 @@ const POLLING_INTERVAL = 2000;
|
||||
|
||||
@Injectable()
|
||||
export class QueryUpdatedService {
|
||||
constructor(readonly activeWindow:ActiveWindowService,
|
||||
readonly apiV3Service:ApiV3Service) {
|
||||
}
|
||||
readonly activeWindow = inject(ActiveWindowService);
|
||||
readonly apiV3Service = inject(ApiV3Service);
|
||||
|
||||
|
||||
public monitor(ids:string[]) {
|
||||
let time = new Date();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Input, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { Board } from 'core-app/features/boards/board/board';
|
||||
import { Observable } from 'rxjs';
|
||||
@@ -19,12 +19,11 @@ import { Observable } from 'rxjs';
|
||||
changeDetection: ChangeDetectionStrategy.Default,
|
||||
})
|
||||
export class BoardsMenuButtonComponent {
|
||||
readonly I18n = inject(I18nService);
|
||||
|
||||
@Input() board$:Observable<Board>;
|
||||
|
||||
text = {
|
||||
button_more: this.I18n.t('js.button_more'),
|
||||
};
|
||||
|
||||
constructor(readonly I18n:I18nService) {
|
||||
}
|
||||
}
|
||||
|
||||
+10
-18
@@ -26,13 +26,10 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
Directive, ElementRef, Injector, Input,
|
||||
} from '@angular/core';
|
||||
import { Directive, Injector, Input, inject } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { OpContextMenuTrigger } from 'core-app/shared/components/op-context-menu/handlers/op-context-menu-trigger.directive';
|
||||
import { OPContextMenuService } from 'core-app/shared/components/op-context-menu/op-context-menu.service';
|
||||
import { OpModalService } from 'core-app/shared/components/modal/modal.service';
|
||||
import { Board } from 'core-app/features/boards/board/board';
|
||||
import { BoardConfigurationModalComponent } from 'core-app/features/boards/board/configuration-modal/board-configuration.modal';
|
||||
@@ -46,21 +43,16 @@ import { selectableTitleIdentifier, triggerEditingEvent } from 'core-app/shared/
|
||||
standalone: false,
|
||||
})
|
||||
export class BoardsToolbarMenuDirective extends OpContextMenuTrigger {
|
||||
@Input('boardsToolbarMenu-resource') public board:Board;
|
||||
readonly opModalService = inject(OpModalService);
|
||||
readonly boardService = inject(BoardService);
|
||||
readonly Notifications = inject(ToastService);
|
||||
readonly State = inject(StateService);
|
||||
readonly injector = inject(Injector);
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly http = inject(HttpClient);
|
||||
|
||||
constructor(
|
||||
readonly elementRef:ElementRef,
|
||||
readonly opContextMenu:OPContextMenuService,
|
||||
readonly opModalService:OpModalService,
|
||||
readonly boardService:BoardService,
|
||||
readonly Notifications:ToastService,
|
||||
readonly State:StateService,
|
||||
readonly injector:Injector,
|
||||
readonly I18n:I18nService,
|
||||
readonly http:HttpClient,
|
||||
) {
|
||||
super(elementRef, opContextMenu);
|
||||
}
|
||||
// eslint-disable-next-line @angular-eslint/no-input-rename
|
||||
@Input('boardsToolbarMenu-resource') public board:Board;
|
||||
|
||||
public get locals() {
|
||||
return {
|
||||
|
||||
@@ -26,13 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
Input,
|
||||
OnDestroy,
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, Input, OnDestroy, inject } from '@angular/core';
|
||||
import { populateInputsFromDataset } from 'core-app/shared/components/dataset-inputs';
|
||||
import {
|
||||
WorkPackageIsolatedQuerySpaceDirective,
|
||||
@@ -45,9 +39,11 @@ import {
|
||||
standalone: false,
|
||||
})
|
||||
export class CalendarEntryComponent implements OnDestroy {
|
||||
readonly elementRef = inject(ElementRef);
|
||||
|
||||
@Input() queryId:string;
|
||||
|
||||
constructor(readonly elementRef:ElementRef) {
|
||||
constructor() {
|
||||
populateInputsFromDataset(this);
|
||||
document.body.classList.add('router--calendar');
|
||||
}
|
||||
|
||||
@@ -26,16 +26,25 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { OpCalendarService } from 'core-app/features/calendar/op-calendar.service';
|
||||
import { WeekdayService } from 'core-app/core/days/weekday.service';
|
||||
import { DayResourceService } from 'core-app/core/state/days/day.service';
|
||||
import { ConfigurationService } from 'core-app/core/config/configuration.service';
|
||||
|
||||
describe('OP calendar service', () => {
|
||||
let service:OpCalendarService;
|
||||
|
||||
beforeEach(() => {
|
||||
// This is not a valid constructor call, but since we only want to test a helper method that does not
|
||||
// depend on injected services, we can pass null values here.
|
||||
// @ts-expect-error ignore invalid constructor call since we don't need a completely valid instance
|
||||
service = new OpCalendarService(null, null, null);
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
OpCalendarService,
|
||||
{ provide: WeekdayService, useValue: {} },
|
||||
{ provide: DayResourceService, useValue: {} },
|
||||
{ provide: ConfigurationService, useValue: {} },
|
||||
],
|
||||
});
|
||||
service = TestBed.inject(OpCalendarService);
|
||||
});
|
||||
|
||||
describe('stripYearFromDateFormat', () => {
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
ElementRef,
|
||||
Injectable,
|
||||
} from '@angular/core';
|
||||
import { ElementRef, Injectable, inject } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { UntilDestroyedMixin } from 'core-app/shared/helpers/angular/until-destroyed.mixin';
|
||||
import { WeekdayService } from 'core-app/core/days/weekday.service';
|
||||
@@ -13,18 +10,14 @@ import { DayHeaderContentArg } from '@fullcalendar/core';
|
||||
|
||||
@Injectable()
|
||||
export class OpCalendarService extends UntilDestroyedMixin {
|
||||
readonly weekdayService = inject(WeekdayService);
|
||||
readonly dayService = inject(DayResourceService);
|
||||
readonly configurationService = inject(ConfigurationService);
|
||||
|
||||
resize$ = new Subject<void>();
|
||||
|
||||
resizeObs:ResizeObserver;
|
||||
|
||||
constructor(
|
||||
readonly weekdayService:WeekdayService,
|
||||
readonly dayService:DayResourceService,
|
||||
readonly configurationService:ConfigurationService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
resizeObserver(v:ElementRef|undefined):void {
|
||||
if (!v) {
|
||||
return;
|
||||
|
||||
@@ -75,6 +75,28 @@ interface CalendarOptionsWithDayGrid extends CalendarOptions {
|
||||
|
||||
@Injectable()
|
||||
export class OpWorkPackagesCalendarService extends UntilDestroyedMixin {
|
||||
private I18n = inject(I18nService);
|
||||
private configuration = inject(ConfigurationService);
|
||||
private sanitizer = inject(DomSanitizer);
|
||||
readonly injector = inject(Injector);
|
||||
readonly schemaCache = inject(SchemaCacheService);
|
||||
readonly toastService = inject(ToastService);
|
||||
readonly wpTableFilters = inject(WorkPackageViewFiltersService);
|
||||
readonly wpListService = inject(WorkPackagesListService);
|
||||
readonly wpListChecksumService = inject(WorkPackagesListChecksumService);
|
||||
readonly urlParamsHelper = inject(UrlParamsHelperService);
|
||||
readonly querySpace = inject(IsolatedQuerySpace);
|
||||
readonly apiV3Service = inject(ApiV3Service);
|
||||
readonly halResourceService = inject(HalResourceService);
|
||||
readonly timezoneService = inject(TimezoneService);
|
||||
readonly pathHelper = inject(PathHelperService);
|
||||
readonly halEditing = inject(HalResourceEditingService);
|
||||
readonly wpTableSelection = inject(WorkPackageViewSelectionService);
|
||||
readonly contextMenuService = inject(OPContextMenuService);
|
||||
readonly calendarService = inject(OpCalendarService);
|
||||
readonly weekdayService = inject(WeekdayService);
|
||||
readonly dayService = inject(DayResourceService);
|
||||
|
||||
static MAX_DISPLAYED = 500;
|
||||
|
||||
tooManyResultsText:string|null;
|
||||
@@ -91,32 +113,6 @@ export class OpWorkPackagesCalendarService extends UntilDestroyedMixin {
|
||||
|
||||
private readonly states = inject(States);
|
||||
|
||||
constructor(
|
||||
private I18n:I18nService,
|
||||
private configuration:ConfigurationService,
|
||||
private sanitizer:DomSanitizer,
|
||||
readonly injector:Injector,
|
||||
readonly schemaCache:SchemaCacheService,
|
||||
readonly toastService:ToastService,
|
||||
readonly wpTableFilters:WorkPackageViewFiltersService,
|
||||
readonly wpListService:WorkPackagesListService,
|
||||
readonly wpListChecksumService:WorkPackagesListChecksumService,
|
||||
readonly urlParamsHelper:UrlParamsHelperService,
|
||||
readonly querySpace:IsolatedQuerySpace,
|
||||
readonly apiV3Service:ApiV3Service,
|
||||
readonly halResourceService:HalResourceService,
|
||||
readonly timezoneService:TimezoneService,
|
||||
readonly pathHelper:PathHelperService,
|
||||
readonly halEditing:HalResourceEditingService,
|
||||
readonly wpTableSelection:WorkPackageViewSelectionService,
|
||||
readonly contextMenuService:OPContextMenuService,
|
||||
readonly calendarService:OpCalendarService,
|
||||
readonly weekdayService:WeekdayService,
|
||||
readonly dayService:DayResourceService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
calendarOptions(additionalOptions:CalendarOptions):CalendarOptions {
|
||||
return { ...this.defaultOptions(), ...additionalOptions };
|
||||
}
|
||||
|
||||
@@ -1,17 +1,4 @@
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
Injector,
|
||||
Input,
|
||||
OnDestroy,
|
||||
Output,
|
||||
SecurityContext,
|
||||
ViewChild,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Injector, Input, OnDestroy, Output, SecurityContext, ViewChild, ViewEncapsulation, inject } from '@angular/core';
|
||||
import { FullCalendarComponent } from '@fullcalendar/angular';
|
||||
import { States } from 'core-app/core/states/states.service';
|
||||
import moment, { Moment } from 'moment';
|
||||
@@ -115,6 +102,25 @@ const ADD_ENTRY_PROHIBITED_CLASS_NAME = '-prohibited';
|
||||
standalone: false,
|
||||
})
|
||||
export class TimeEntryCalendarComponent implements AfterViewInit, OnDestroy {
|
||||
readonly states = inject(States);
|
||||
readonly apiV3Service = inject(ApiV3Service);
|
||||
readonly $state = inject(StateService);
|
||||
private element = inject(ElementRef);
|
||||
readonly i18n = inject(I18nService);
|
||||
readonly injector = inject(Injector);
|
||||
readonly notifications = inject(HalResourceNotificationService);
|
||||
private sanitizer = inject(DomSanitizer);
|
||||
private configuration = inject(ConfigurationService);
|
||||
private timezone = inject(TimezoneService);
|
||||
private schemaCache = inject(SchemaCacheService);
|
||||
private colors = inject(ColorsService);
|
||||
private browserDetector = inject(BrowserDetector);
|
||||
private calendar = inject(OpCalendarService);
|
||||
readonly weekdayService = inject(WeekdayService);
|
||||
readonly dayService = inject(DayResourceService);
|
||||
readonly turboRequests = inject(TurboRequestsService);
|
||||
readonly pathHelper = inject(PathHelperService);
|
||||
|
||||
@ViewChild(FullCalendarComponent) ucCalendar:FullCalendarComponent;
|
||||
|
||||
@Input() projectIdentifier:string;
|
||||
@@ -202,27 +208,6 @@ export class TimeEntryCalendarComponent implements AfterViewInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
constructor(
|
||||
readonly states:States,
|
||||
readonly apiV3Service:ApiV3Service,
|
||||
readonly $state:StateService,
|
||||
private element:ElementRef,
|
||||
readonly i18n:I18nService,
|
||||
readonly injector:Injector,
|
||||
readonly notifications:HalResourceNotificationService,
|
||||
private sanitizer:DomSanitizer,
|
||||
private configuration:ConfigurationService,
|
||||
private timezone:TimezoneService,
|
||||
private schemaCache:SchemaCacheService,
|
||||
private colors:ColorsService,
|
||||
private browserDetector:BrowserDetector,
|
||||
private calendar:OpCalendarService,
|
||||
readonly weekdayService:WeekdayService,
|
||||
readonly dayService:DayResourceService,
|
||||
readonly turboRequests:TurboRequestsService,
|
||||
readonly pathHelper:PathHelperService,
|
||||
) { }
|
||||
|
||||
ngAfterViewInit():void {
|
||||
document.addEventListener('dialog:close', this.closeDialogHandler);
|
||||
}
|
||||
|
||||
@@ -26,15 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
Input,
|
||||
OnInit,
|
||||
ViewChild,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, Input, OnInit, ViewChild, ViewEncapsulation, inject } from '@angular/core';
|
||||
import {
|
||||
CalendarOptions,
|
||||
DateSelectArg,
|
||||
@@ -103,6 +95,29 @@ import { TimezoneService } from 'core-app/core/datetime/timezone.service';
|
||||
standalone: false,
|
||||
})
|
||||
export class WorkPackagesCalendarComponent extends UntilDestroyedMixin implements OnInit {
|
||||
readonly actions$ = inject(ActionsService);
|
||||
readonly states = inject(States);
|
||||
readonly wpTableFilters = inject(WorkPackageViewFiltersService);
|
||||
readonly wpListService = inject(WorkPackagesListService);
|
||||
readonly querySpace = inject(IsolatedQuerySpace);
|
||||
readonly schemaCache = inject(SchemaCacheService);
|
||||
private element = inject(ElementRef);
|
||||
readonly i18n = inject(I18nService);
|
||||
readonly toastService = inject(ToastService);
|
||||
private sanitizer = inject(DomSanitizer);
|
||||
private I18n = inject(I18nService);
|
||||
private configuration = inject(ConfigurationService);
|
||||
readonly calendar = inject(OpCalendarService);
|
||||
readonly workPackagesCalendar = inject(OpWorkPackagesCalendarService);
|
||||
readonly currentProject = inject(CurrentProjectService);
|
||||
readonly halEditing = inject(HalResourceEditingService);
|
||||
readonly halNotification = inject(HalResourceNotificationService);
|
||||
readonly weekdayService = inject(WeekdayService);
|
||||
readonly dayService = inject(DayResourceService);
|
||||
readonly apiV3Service = inject(ApiV3Service);
|
||||
readonly pathHelper = inject(PathHelperService);
|
||||
readonly timezoneService = inject(TimezoneService);
|
||||
|
||||
@ViewChild(FullCalendarComponent) ucCalendar:FullCalendarComponent;
|
||||
|
||||
@ViewChild('ucCalendar', { read: ElementRef })
|
||||
@@ -123,33 +138,6 @@ export class WorkPackagesCalendarComponent extends UntilDestroyedMixin implement
|
||||
today: this.I18n.t('js.team_planner.today'),
|
||||
};
|
||||
|
||||
constructor(
|
||||
readonly actions$:ActionsService,
|
||||
readonly states:States,
|
||||
readonly wpTableFilters:WorkPackageViewFiltersService,
|
||||
readonly wpListService:WorkPackagesListService,
|
||||
readonly querySpace:IsolatedQuerySpace,
|
||||
readonly schemaCache:SchemaCacheService,
|
||||
private element:ElementRef,
|
||||
readonly i18n:I18nService,
|
||||
readonly toastService:ToastService,
|
||||
private sanitizer:DomSanitizer,
|
||||
private I18n:I18nService,
|
||||
private configuration:ConfigurationService,
|
||||
readonly calendar:OpCalendarService,
|
||||
readonly workPackagesCalendar:OpWorkPackagesCalendarService,
|
||||
readonly currentProject:CurrentProjectService,
|
||||
readonly halEditing:HalResourceEditingService,
|
||||
readonly halNotification:HalResourceNotificationService,
|
||||
readonly weekdayService:WeekdayService,
|
||||
readonly dayService:DayResourceService,
|
||||
readonly apiV3Service:ApiV3Service,
|
||||
readonly pathHelper:PathHelperService,
|
||||
readonly timezoneService:TimezoneService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
ngOnInit():void {
|
||||
registerEffectCallbacks(this, this.untilDestroyed());
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Input, OnInit, inject } from '@angular/core';
|
||||
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
|
||||
import { BannersService } from 'core-app/core/enterprise/banners.service';
|
||||
|
||||
@@ -37,6 +37,9 @@ import { BannersService } from 'core-app/core/enterprise/banners.service';
|
||||
standalone: false,
|
||||
})
|
||||
export class EnterpriseBannerFrameComponent implements OnInit {
|
||||
protected pathHelper = inject(PathHelperService);
|
||||
protected banners = inject(BannersService);
|
||||
|
||||
@Input() public feature:string;
|
||||
|
||||
@Input() public dismissable = false;
|
||||
@@ -45,12 +48,6 @@ export class EnterpriseBannerFrameComponent implements OnInit {
|
||||
frameURL:string;
|
||||
frameID:string;
|
||||
|
||||
constructor(
|
||||
protected pathHelper:PathHelperService,
|
||||
protected banners:BannersService,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.visible = this.banners.showBannerFor(this.feature);
|
||||
this.frameURL = this.pathHelper.bannerFramePath(this.feature, this.dismissable);
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
ErrorHandler,
|
||||
Injectable,
|
||||
} from '@angular/core';
|
||||
import { ErrorHandler, Injectable, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { HalResource } from 'core-app/features/hal/resources/hal-resource';
|
||||
import { ErrorResource } from 'core-app/features/hal/resources/error-resource';
|
||||
@@ -14,14 +11,12 @@ interface RejectedPromise {
|
||||
|
||||
@Injectable()
|
||||
export class HalAwareErrorHandler extends ErrorHandler {
|
||||
private readonly I18n = inject(I18nService);
|
||||
|
||||
private text = {
|
||||
internal_error: this.I18n.t('js.error.internal'),
|
||||
};
|
||||
|
||||
constructor(private readonly I18n:I18nService) {
|
||||
super();
|
||||
}
|
||||
|
||||
public handleError(error:unknown):void {
|
||||
let message:string = this.text.internal_error;
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
import { StateService } from '@uirouter/core';
|
||||
import { HalResourceService } from 'core-app/features/hal/services/hal-resource.service';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Injectable, Injector, inject } from '@angular/core';
|
||||
import { LoadingIndicatorService } from 'core-app/core/loading-indicator/loading-indicator.service';
|
||||
import { ToastService } from 'core-app/shared/components/toaster/toast.service';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
@@ -41,6 +41,8 @@ import { HalError } from 'core-app/features/hal/services/hal-error';
|
||||
|
||||
@Injectable()
|
||||
export class HalResourceNotificationService {
|
||||
injector = inject(Injector);
|
||||
|
||||
@InjectField() protected I18n:I18nService;
|
||||
|
||||
@InjectField() protected $state:StateService;
|
||||
@@ -53,9 +55,6 @@ export class HalResourceNotificationService {
|
||||
|
||||
@InjectField() protected schemaCache:SchemaCacheService;
|
||||
|
||||
constructor(public injector:Injector) {
|
||||
}
|
||||
|
||||
public showSave(resource:HalResource, isCreate = false) {
|
||||
const message:any = {
|
||||
message: this.I18n.t(`js.notice_successful_${isCreate ? 'create' : 'update'}`),
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Injectable, Injector, inject } from '@angular/core';
|
||||
import { HttpClient, HttpErrorResponse, HttpParams } from '@angular/common/http';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
@@ -59,17 +59,14 @@ interface ErrorWithType {
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class HalResourceService {
|
||||
readonly injector = inject(Injector);
|
||||
readonly http = inject(HttpClient);
|
||||
|
||||
/**
|
||||
* List of all known hal resources, extendable.
|
||||
*/
|
||||
private config:Record<string, HalResourceFactoryConfigInterface> = {};
|
||||
|
||||
constructor(
|
||||
readonly injector:Injector,
|
||||
readonly http:HttpClient,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a HTTP request and return a HalResource promise.
|
||||
*/
|
||||
|
||||
+8
-8
@@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, Input, OnInit, HostListener } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, Input, OnInit, HostListener, inject } from '@angular/core';
|
||||
import { combineLatest, merge, Observable, timer } from 'rxjs';
|
||||
import { filter, map, shareReplay, switchMap, throttleTime } from 'rxjs/operators';
|
||||
import { ActiveWindowService } from 'core-app/core/active-window/active-window.service';
|
||||
@@ -15,6 +15,12 @@ import { populateInputsFromDataset } from 'core-app/shared/components/dataset-in
|
||||
standalone: false,
|
||||
})
|
||||
export class InAppNotificationBellComponent implements OnInit {
|
||||
readonly elementRef = inject(ElementRef);
|
||||
readonly storeService = inject(IanBellService);
|
||||
readonly apiV3Service = inject(ApiV3Service);
|
||||
readonly activeWindow = inject(ActiveWindowService);
|
||||
readonly pathHelper = inject(PathHelperService);
|
||||
|
||||
@Input() interval = 50000;
|
||||
|
||||
polling$:Observable<number>;
|
||||
@@ -25,13 +31,7 @@ export class InAppNotificationBellComponent implements OnInit {
|
||||
|
||||
public bellDisplayLimit = 99;
|
||||
|
||||
constructor(
|
||||
readonly elementRef:ElementRef,
|
||||
readonly storeService:IanBellService,
|
||||
readonly apiV3Service:ApiV3Service,
|
||||
readonly activeWindow:ActiveWindowService,
|
||||
readonly pathHelper:PathHelperService,
|
||||
) {
|
||||
constructor() {
|
||||
populateInputsFromDataset(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import {
|
||||
catchError,
|
||||
map,
|
||||
@@ -57,6 +57,9 @@ import { IanBellStore } from 'core-app/features/in-app-notifications/bell/state/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
@EffectHandler
|
||||
export class IanBellService {
|
||||
readonly actions$ = inject(ActionsService);
|
||||
readonly resourceService = inject(InAppNotificationsResourceService);
|
||||
|
||||
readonly id = 'ian-bell';
|
||||
|
||||
readonly store = new IanBellStore();
|
||||
@@ -65,10 +68,7 @@ export class IanBellService {
|
||||
|
||||
unread$ = this.query.unread$;
|
||||
|
||||
constructor(
|
||||
readonly actions$:ActionsService,
|
||||
readonly resourceService:InAppNotificationsResourceService,
|
||||
) {
|
||||
constructor() {
|
||||
this.query.unreadCountChanged$.subscribe((count) => {
|
||||
this.actions$.dispatch(notificationCountChanged({ origin: this.id, count }));
|
||||
});
|
||||
|
||||
+12
-15
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
import { StateService } from '@uirouter/angular';
|
||||
@@ -52,6 +52,17 @@ import {
|
||||
standalone: false,
|
||||
})
|
||||
export class InAppNotificationCenterComponent implements OnInit {
|
||||
readonly cdRef = inject(ChangeDetectorRef);
|
||||
readonly elementRef = inject(ElementRef);
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly storeService = inject(IanCenterService);
|
||||
readonly bellService = inject(IanBellService);
|
||||
readonly urlParams = inject(UrlParamsService);
|
||||
readonly state = inject(StateService);
|
||||
readonly apiV3 = inject(ApiV3Service);
|
||||
readonly pathService = inject(PathHelperService);
|
||||
readonly colorsService = inject(ColorsService);
|
||||
|
||||
maxSize = NOTIFICATIONS_MAX_SIZE;
|
||||
|
||||
hasMoreThanPageSize$ = this.storeService.hasMoreThanPageSize$;
|
||||
@@ -141,20 +152,6 @@ export class InAppNotificationCenterComponent implements OnInit {
|
||||
|
||||
protected readonly idFromLink = idFromLink;
|
||||
|
||||
constructor(
|
||||
readonly cdRef:ChangeDetectorRef,
|
||||
readonly elementRef:ElementRef,
|
||||
readonly I18n:I18nService,
|
||||
readonly storeService:IanCenterService,
|
||||
readonly bellService:IanBellService,
|
||||
readonly urlParams:UrlParamsService,
|
||||
readonly state:StateService,
|
||||
readonly apiV3:ApiV3Service,
|
||||
readonly pathService:PathHelperService,
|
||||
readonly colorsService:ColorsService,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit():void {
|
||||
const facet = this.urlParams.get('facet') || 'unread';
|
||||
this.storeService.setFacet(facet as 'unread'|'all');
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// See COPYRIGHT and LICENSE files for more details.
|
||||
//++
|
||||
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { Injectable, Injector, inject } from '@angular/core';
|
||||
import { debounceTime, defaultIfEmpty, distinctUntilChanged, map, mapTo, switchMap, take, tap } from 'rxjs/operators';
|
||||
import { forkJoin, from, Observable, Subject } from 'rxjs';
|
||||
import { ID, Query } from '@datorama/akita';
|
||||
@@ -71,6 +71,18 @@ export interface INotificationPageQueryParameters {
|
||||
@Injectable({ providedIn: 'root' })
|
||||
@EffectHandler
|
||||
export class IanCenterService extends UntilDestroyedMixin {
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly injector = inject(Injector);
|
||||
readonly resourceService = inject(InAppNotificationsResourceService);
|
||||
readonly actions$ = inject(ActionsService);
|
||||
readonly apiV3Service = inject(ApiV3Service);
|
||||
readonly toastService = inject(ToastService);
|
||||
readonly urlParams = inject(UrlParamsService);
|
||||
readonly state = inject(StateService);
|
||||
readonly deviceService = inject(DeviceService);
|
||||
readonly pathHelper = inject(PathHelperService);
|
||||
readonly ianBellService = inject(IanBellService);
|
||||
|
||||
readonly id = 'ian-center';
|
||||
|
||||
readonly store = new IanCenterStore();
|
||||
@@ -182,19 +194,7 @@ export class IanCenterService extends UntilDestroyedMixin {
|
||||
|
||||
selectedWorkPackage$ = this.urlParams.pathMatching$(/\/details\/(\d+)/);
|
||||
|
||||
constructor(
|
||||
readonly I18n:I18nService,
|
||||
readonly injector:Injector,
|
||||
readonly resourceService:InAppNotificationsResourceService,
|
||||
readonly actions$:ActionsService,
|
||||
readonly apiV3Service:ApiV3Service,
|
||||
readonly toastService:ToastService,
|
||||
readonly urlParams:UrlParamsService,
|
||||
readonly state:StateService,
|
||||
readonly deviceService:DeviceService,
|
||||
readonly pathHelper:PathHelperService,
|
||||
readonly ianBellService:IanBellService,
|
||||
) {
|
||||
constructor() {
|
||||
super();
|
||||
this.reload.subscribe();
|
||||
|
||||
|
||||
+4
-6
@@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component, HostBinding, Input, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, HostBinding, Input, OnInit, ViewEncapsulation, inject } from '@angular/core';
|
||||
import { DeviceService } from 'core-app/core/browser/device.service';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { INotification } from 'core-app/core/state/in-app-notifications/in-app-notification.model';
|
||||
@@ -13,6 +13,9 @@ import { PrincipalLike } from 'core-app/shared/components/principal/principal-ty
|
||||
standalone: false,
|
||||
})
|
||||
export class InAppNotificationActorsLineComponent implements OnInit {
|
||||
readonly deviceService = inject(DeviceService);
|
||||
private I18n = inject(I18nService);
|
||||
|
||||
@HostBinding('class.op-ian-actors') className = true;
|
||||
|
||||
@Input() aggregatedNotifications:INotification[];
|
||||
@@ -34,11 +37,6 @@ export class InAppNotificationActorsLineComponent implements OnInit {
|
||||
mark_as_read: this.I18n.t('js.notifications.center.mark_as_read'),
|
||||
};
|
||||
|
||||
constructor(
|
||||
readonly deviceService:DeviceService,
|
||||
private I18n:I18nService,
|
||||
) { }
|
||||
|
||||
ngOnInit():void {
|
||||
// Don't show the actor if the first item is actor-less (date alert)
|
||||
if (this.notification._links.actor) {
|
||||
|
||||
+4
-13
@@ -1,11 +1,4 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
HostBinding,
|
||||
Input,
|
||||
OnInit,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, HostBinding, Input, OnInit, ViewEncapsulation, inject } from '@angular/core';
|
||||
import { TimezoneService } from 'core-app/core/datetime/timezone.service';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { IInAppNotificationDetailsAttribute, INotification } from 'core-app/core/state/in-app-notifications/in-app-notification.model';
|
||||
@@ -20,6 +13,9 @@ import moment, { Moment } from 'moment';
|
||||
standalone: false,
|
||||
})
|
||||
export class InAppNotificationDateAlertComponent implements OnInit {
|
||||
private I18n = inject(I18nService);
|
||||
private timezoneService = inject(TimezoneService);
|
||||
|
||||
@Input() aggregatedNotifications:INotification[];
|
||||
|
||||
@HostBinding('class.op-ian-date-alert') className = true;
|
||||
@@ -49,11 +45,6 @@ export class InAppNotificationDateAlertComponent implements OnInit {
|
||||
note: '', // date alerts do not have notes
|
||||
};
|
||||
|
||||
constructor(
|
||||
private I18n:I18nService,
|
||||
private timezoneService:TimezoneService,
|
||||
) { }
|
||||
|
||||
ngOnInit():void {
|
||||
// Find the most important date alert
|
||||
const interestingAlert = this.deriveMostRelevantAlert(this.aggregatedNotifications);
|
||||
|
||||
+9
-13
@@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component, HostBinding, Input, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, HostBinding, Input, OnInit, ViewEncapsulation, inject } from '@angular/core';
|
||||
import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource';
|
||||
import { Observable } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
@@ -23,6 +23,14 @@ import { UntilDestroyedMixin } from 'core-app/shared/helpers/angular/until-destr
|
||||
standalone: false,
|
||||
})
|
||||
export class InAppNotificationEntryComponent extends UntilDestroyedMixin implements OnInit {
|
||||
readonly apiV3Service = inject(ApiV3Service);
|
||||
readonly I18n = inject(I18nService);
|
||||
readonly storeService = inject(IanCenterService);
|
||||
readonly timezoneService = inject(TimezoneService);
|
||||
readonly pathHelper = inject(PathHelperService);
|
||||
readonly deviceService = inject(DeviceService);
|
||||
readonly urlParams = inject(UrlParamsService);
|
||||
|
||||
@HostBinding('class.op-ian-item') className = true;
|
||||
|
||||
@Input() notification:INotification;
|
||||
@@ -55,18 +63,6 @@ export class InAppNotificationEntryComponent extends UntilDestroyedMixin impleme
|
||||
|
||||
workPackageId:string|null;
|
||||
|
||||
constructor(
|
||||
readonly apiV3Service:ApiV3Service,
|
||||
readonly I18n:I18nService,
|
||||
readonly storeService:IanCenterService,
|
||||
readonly timezoneService:TimezoneService,
|
||||
readonly pathHelper:PathHelperService,
|
||||
readonly deviceService:DeviceService,
|
||||
readonly urlParams:UrlParamsService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
ngOnInit():void {
|
||||
const href = this.notification._links.resource?.href;
|
||||
this.workPackageId = href && HalResource.matchFromLink(href, 'work_packages');
|
||||
|
||||
+4
-12
@@ -1,10 +1,4 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Input,
|
||||
OnInit,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Input, OnInit, ViewEncapsulation, inject } from '@angular/core';
|
||||
import { TimezoneService } from 'core-app/core/datetime/timezone.service';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { INotification } from 'core-app/core/state/in-app-notifications/in-app-notification.model';
|
||||
@@ -20,6 +14,9 @@ import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
standalone: false,
|
||||
})
|
||||
export class InAppNotificationRelativeTimeComponent implements OnInit {
|
||||
private I18n = inject(I18nService);
|
||||
private timezoneService = inject(TimezoneService);
|
||||
|
||||
@Input() notification:INotification;
|
||||
@Input() hasActorByLine = true;
|
||||
|
||||
@@ -37,11 +34,6 @@ export class InAppNotificationRelativeTimeComponent implements OnInit {
|
||||
),
|
||||
};
|
||||
|
||||
constructor(
|
||||
private I18n:I18nService,
|
||||
private timezoneService:TimezoneService,
|
||||
) { }
|
||||
|
||||
ngOnInit():void {
|
||||
this.buildTime();
|
||||
}
|
||||
|
||||
+3
-12
@@ -1,11 +1,4 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
HostBinding,
|
||||
Input,
|
||||
OnInit,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, HostBinding, Input, OnInit, ViewEncapsulation, inject } from '@angular/core';
|
||||
import { I18nService } from 'core-app/core/i18n/i18n.service';
|
||||
import { IInAppNotificationDetailsResource, INotification } from 'core-app/core/state/in-app-notifications/in-app-notification.model';
|
||||
|
||||
@@ -18,6 +11,8 @@ import { IInAppNotificationDetailsResource, INotification } from 'core-app/core/
|
||||
standalone: false,
|
||||
})
|
||||
export class InAppNotificationReminderAlertComponent implements OnInit {
|
||||
private I18n = inject(I18nService);
|
||||
|
||||
@Input() aggregatedNotifications:INotification[];
|
||||
|
||||
@HostBinding('class.op-ian-reminder-alert') className = true;
|
||||
@@ -27,10 +22,6 @@ export class InAppNotificationReminderAlertComponent implements OnInit {
|
||||
hasDateAlert = false;
|
||||
dateAlerts:INotification[] = [];
|
||||
|
||||
constructor(
|
||||
private I18n:I18nService,
|
||||
) { }
|
||||
|
||||
ngOnInit():void {
|
||||
this.reminderAlert = this.deriveMostRecentReminder(this.aggregatedNotifications);
|
||||
this.reminderNote = this.extractReminderNoteValue(this.reminderAlert._embedded.details);
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { TurboRequestsService } from 'core-app/core/turbo/turbo-requests.service';
|
||||
import { PathHelperService } from 'core-app/core/path-helper/path-helper.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class JobStatusModalService {
|
||||
constructor(
|
||||
protected pathHelper:PathHelperService,
|
||||
protected turboRequests:TurboRequestsService,
|
||||
) {}
|
||||
protected pathHelper = inject(PathHelperService);
|
||||
protected turboRequests = inject(TurboRequestsService);
|
||||
|
||||
|
||||
public show(jobId:string):void {
|
||||
void this.turboRequests.requestStream(this.jobModalUrl(jobId));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user