diff --git a/frontend/src/app/core/apiv3/endpoints/queries/apiv3-queries-paths.ts b/frontend/src/app/core/apiv3/endpoints/queries/apiv3-queries-paths.ts index 71080464e1c1..f4bf59173663 100644 --- a/frontend/src/app/core/apiv3/endpoints/queries/apiv3-queries-paths.ts +++ b/frontend/src/app/core/apiv3/endpoints/queries/apiv3-queries-paths.ts @@ -38,6 +38,7 @@ import { CollectionResource } from 'core-app/features/hal/resources/collection-r import { ApiV3ListParameters, listParamsString } from 'core-app/core/apiv3/paths/apiv3-list-resource.interface'; import { QueryFiltersService } from 'core-app/features/work-packages/components/wp-query/query-filters.service'; import { HalPayloadHelper } from 'core-app/features/hal/schemas/hal-payload.helper'; +import { HTTPClientParamMap } from 'core-app/features/hal/http/http.interfaces'; export class ApiV3QueriesPaths extends ApiV3ResourceCollection { @LazyInject() private queryFilters:QueryFiltersService; @@ -89,7 +90,7 @@ export class ApiV3QueriesPaths extends ApiV3ResourceCollection(path, queryData); + .get(path, queryData as HTTPClientParamMap); } /** @@ -101,7 +102,7 @@ export class ApiV3QueriesPaths extends ApiV3ResourceCollection( this.default.path, - params, + params as HTTPClientParamMap, ); } diff --git a/frontend/src/app/core/apiv3/endpoints/queries/apiv3-query-paths.ts b/frontend/src/app/core/apiv3/endpoints/queries/apiv3-query-paths.ts index e2fd8fb6b705..e8df6622aa5b 100644 --- a/frontend/src/app/core/apiv3/endpoints/queries/apiv3-query-paths.ts +++ b/frontend/src/app/core/apiv3/endpoints/queries/apiv3-query-paths.ts @@ -36,6 +36,7 @@ import { LazyInject } from 'core-app/shared/helpers/angular/lazy-inject.decorato import { QueryFiltersService } from 'core-app/features/work-packages/components/wp-query/query-filters.service'; import { HalPayloadHelper } from 'core-app/features/hal/schemas/hal-payload.helper'; import { PaginationObject } from 'core-app/shared/components/table-pagination/pagination-service'; +import { HTTPClientParamMap } from 'core-app/features/hal/http/http.interfaces'; export class ApiV3QueryPaths extends ApiV3GettableResource { @LazyInject() private queryFilters:QueryFiltersService; @@ -52,7 +53,7 @@ export class ApiV3QueryPaths extends ApiV3GettableResource { */ public parameterised(params:object):Observable { return this.halResourceService - .get(this.path, params); + .get(this.path, params as HTTPClientParamMap); } /** diff --git a/frontend/src/app/core/model-auth/model-auth.service.ts b/frontend/src/app/core/model-auth/model-auth.service.ts index 0333565d8d0d..3a79ea3f3589 100644 --- a/frontend/src/app/core/model-auth/model-auth.service.ts +++ b/frontend/src/app/core/model-auth/model-auth.service.ts @@ -31,7 +31,7 @@ import { input } from '@openproject/reactivestates'; import { Observable } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; -export type ModelLinks = Record; +export type ModelLinks = Record; export type ModelLinksHash = Record; @Injectable({ providedIn: 'root' }) @@ -46,7 +46,7 @@ export class AuthorisationService { }); } - public observeUntil(unsubscribe:Observable) { + public observeUntil(unsubscribe:Observable) { return this.links.values$().pipe(takeUntil(unsubscribe)); } diff --git a/frontend/src/app/core/schemas/schema-cache.service.ts b/frontend/src/app/core/schemas/schema-cache.service.ts index 973413d76e70..91bca36e6af8 100644 --- a/frontend/src/app/core/schemas/schema-cache.service.ts +++ b/frontend/src/app/core/schemas/schema-cache.service.ts @@ -129,7 +129,7 @@ export class SchemaCacheService extends StateCacheService { ); } - protected loadAll(hrefs:string[]):Promise { + protected loadAll(hrefs:string[]):Promise { return Promise.all(hrefs.map((href) => this.load(href))); } diff --git a/frontend/src/app/core/state/capabilities/capabilities.service.ts b/frontend/src/app/core/state/capabilities/capabilities.service.ts index 6e136fe4ee90..64f3f5ecf4d6 100644 --- a/frontend/src/app/core/state/capabilities/capabilities.service.ts +++ b/frontend/src/app/core/state/capabilities/capabilities.service.ts @@ -40,6 +40,7 @@ import { ResourceStore, ResourceStoreService, } from 'core-app/core/state/resource-store.service'; +import { HttpErrorResponse } from '@angular/common/http'; @Injectable() export class CapabilitiesResourceService extends ResourceStoreService { @@ -59,7 +60,7 @@ export class CapabilitiesResourceService extends ResourceStoreService { + catchError((error:HttpErrorResponse) => { this.toastService.addError(error); throw error; }), diff --git a/frontend/src/app/core/states/states.service.ts b/frontend/src/app/core/states/states.service.ts index 8e42af9ef35d..de68c9f468fd 100644 --- a/frontend/src/app/core/states/states.service.ts +++ b/frontend/src/app/core/states/states.service.ts @@ -93,7 +93,7 @@ export class States extends StatesGroup { additional:Record> = {}; forType(stateName:string):MultiInputState { - let state = (this as any)[stateName] || this.additional[stateName]; + let state = (this as unknown as Record|undefined>)[stateName] ?? this.additional[stateName] as MultiInputState|undefined; if (!state) { state = this.additional[stateName] = multiInput(); diff --git a/frontend/src/app/features/admin/editable-query-props/editable-query-props.component.ts b/frontend/src/app/features/admin/editable-query-props/editable-query-props.component.ts index 82caea3d7282..7bbbb409d78a 100644 --- a/frontend/src/app/features/admin/editable-query-props/editable-query-props.component.ts +++ b/frontend/src/app/features/admin/editable-query-props/editable-query-props.component.ts @@ -76,7 +76,7 @@ export class EditableQueryPropsComponent implements OnInit { // eslint-disable-next-line @typescript-eslint/no-unsafe-return return JSON.parse(this.queryProps); } catch (e) { - console.error(`Failed to parse query props from ${this.queryProps}: ${e}`); + console.error(`Failed to parse query props from ${this.queryProps}: ${String(e)}`); return {}; } })(); diff --git a/frontend/src/app/features/bim/bcf/api/bcf-api-request.service.ts b/frontend/src/app/features/bim/bcf/api/bcf-api-request.service.ts index 5cdf27f3f69f..3c52b59043b7 100644 --- a/frontend/src/app/features/bim/bcf/api/bcf-api-request.service.ts +++ b/frontend/src/app/features/bim/bcf/api/bcf-api-request.service.ts @@ -70,7 +70,7 @@ export class BcfApiRequestService { responseType: 'json', }; - return this._request('get', path, config); + return this.sendRequest('get', path, config); } /** @@ -81,11 +81,11 @@ export class BcfApiRequestService { * @param data Request payload (URL params for get, JSON payload otherwise) * @param headers Request headers */ - public request(method:HTTPSupportedMethods, path:string, data:HTTPClientParamMap = {}, headers:HTTPClientHeaders = {}):Observable { + public request(method:HTTPSupportedMethods, path:string, data:unknown = {}, headers:HTTPClientHeaders = {}):Observable { // HttpClient requires us to create HttpParams instead of passing data for get // so forward to that method instead. if (method === 'get') { - return this.get(path, data, headers); + return this.get(path, data as HTTPClientParamMap, headers); } const config:HTTPClientOptions = { @@ -95,7 +95,7 @@ export class BcfApiRequestService { responseType: 'json', }; - return this._request(method, path, config); + return this.sendRequest(method, path, config); } /** @@ -107,12 +107,12 @@ export class BcfApiRequestService { * * @private */ - private _request(method:HTTPSupportedMethods, path:string, config:HTTPClientOptions):Observable { + private sendRequest(method:HTTPSupportedMethods, path:string, config:HTTPClientOptions):Observable { return this .http .request(method, path, config) .pipe( - map((response:any) => this.deserialize(response)), + map((response) => this.deserialize(response)), catchError((error:HttpErrorResponse) => { console.error(`Failed to ${method} ${path}: ${error.name}`); return throwError(error); @@ -124,11 +124,11 @@ export class BcfApiRequestService { * Deserialize the JSON data into the mapped resource class, if given. * @param data JSON API response. */ - protected deserialize(data:any):T { + protected deserialize(data:unknown):T { if (this.resourceClass) { const serializer = new TypedJSON(this.resourceClass); - return serializer.parse(data)!; + return serializer.parse(data) as T; } - return data; + return data as T; } } diff --git a/frontend/src/app/features/bim/bcf/api/bcf-api.service.ts b/frontend/src/app/features/bim/bcf/api/bcf-api.service.ts index 21cc945d65e1..0be855467895 100644 --- a/frontend/src/app/features/bim/bcf/api/bcf-api.service.ts +++ b/frontend/src/app/features/bim/bcf/api/bcf-api.service.ts @@ -58,22 +58,22 @@ export class BcfApiService { .split('/'); // Try to find a target collection or resource - let current:any = this; + let current = this as object; for (const pathOrId of parts) { if (pathOrId in current) { // Current has a member named like this URL part // descend into it - current = current[pathOrId]; + current = (current as Record)[pathOrId]; } else if (current instanceof BcfResourceCollectionPath) { // Otherwise, assume we're looking for an ID - current = current.id(pathOrId); + current = current.id(pathOrId) as object; } else { // Otherwise, return the current break; } } - return current === this ? undefined : current; + return current === this ? undefined : current as T; } } diff --git a/frontend/src/app/features/bim/bcf/api/topics/bcf-topic.resource.ts b/frontend/src/app/features/bim/bcf/api/topics/bcf-topic.resource.ts index 8608b72334f9..61d49454cd5c 100644 --- a/frontend/src/app/features/bim/bcf/api/topics/bcf-topic.resource.ts +++ b/frontend/src/app/features/bim/bcf/api/topics/bcf-topic.resource.ts @@ -64,13 +64,13 @@ export class BcfTopicResource { @jsonArrayMember(String) labels:string[]; - @jsonMember({ deserializer: (value) => moment(value), serializer: (timestamp:Moment) => timestamp.toISOString() }) + @jsonMember({ deserializer: (value:string) => moment(value), serializer: (timestamp:Moment) => timestamp.toISOString() }) creation_date:Moment; @jsonMember(String) creation_author:string; - @jsonMember({ deserializer: (value) => moment(value), serializer: (timestamp:Moment) => timestamp.toISOString() }) + @jsonMember({ deserializer: (value:string) => moment(value), serializer: (timestamp:Moment) => timestamp.toISOString() }) modified_date:Moment; @jsonMember(String, { preserveNull: true }) @@ -86,7 +86,7 @@ export class BcfTopicResource { description:string; @jsonMember({ - deserializer: (value) => moment(value), + deserializer: (value:string) => moment(value), serializer: (timestamp:Moment) => timestamp.format('YYYY-MM-DD'), }) due_date:Moment; diff --git a/frontend/src/app/features/bim/bcf/api/topics/bcf-viewpoint-collection.paths.ts b/frontend/src/app/features/bim/bcf/api/topics/bcf-viewpoint-collection.paths.ts index 4880615e6fcb..b51de3e4df12 100644 --- a/frontend/src/app/features/bim/bcf/api/topics/bcf-viewpoint-collection.paths.ts +++ b/frontend/src/app/features/bim/bcf/api/topics/bcf-viewpoint-collection.paths.ts @@ -50,7 +50,7 @@ export class BcfTopicCollectionPath extends BcfResourceCollectionPath { + post(payload:unknown):Observable { return this .bcfTopicService .request( diff --git a/frontend/src/app/features/bim/bcf/bcf-wp-attribute-group/bcf-wp-attribute-group.component.ts b/frontend/src/app/features/bim/bcf/bcf-wp-attribute-group/bcf-wp-attribute-group.component.ts index 241968ad46ab..893e22f19cbc 100644 --- a/frontend/src/app/features/bim/bcf/bcf-wp-attribute-group/bcf-wp-attribute-group.component.ts +++ b/frontend/src/app/features/bim/bcf/bcf-wp-attribute-group/bcf-wp-attribute-group.component.ts @@ -29,7 +29,7 @@ import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit, ViewChild, inject } from '@angular/core'; import { UrlParamsService } from 'core-app/core/navigation/url-params.service'; import { WorkPackageResource } from 'core-app/features/hal/resources/work-package-resource'; -import { NgxGalleryComponent, NgxGalleryOptions } from '@kolkov/ngx-gallery'; +import { NgxGalleryComponent, NgxGalleryImage, NgxGalleryOptions } from '@kolkov/ngx-gallery'; import { HalLink } from 'core-app/features/hal/hal-link/hal-link'; import idFromLink from 'core-app/features/hal/helpers/id-from-link'; import { I18nService } from 'core-app/core/i18n/i18n.service'; @@ -135,7 +135,7 @@ export class BcfWpAttributeGroupComponent extends UntilDestroyedMixin implements viewpoints:BcfViewpointItem[] = []; - galleryImages:any[] = []; + galleryImages:NgxGalleryImage[] = []; // Store whether viewing is allowed viewAllowed = false; @@ -279,7 +279,7 @@ export class BcfWpAttributeGroupComponent extends UntilDestroyedMixin implements return [ { icon: 'icon-view-model', - onClick: (evt:any, index:number) => { + onClick: (evt:Event, index:number) => { this.showViewpoint(this.workPackage, index); this.gallery.preview.close(); }, @@ -287,7 +287,7 @@ export class BcfWpAttributeGroupComponent extends UntilDestroyedMixin implements }, { icon: 'icon-delete', - onClick: (evt:any, index:number) => this.deleteViewpoint(this.workPackage, index), + onClick: (evt:Event, index:number) => this.deleteViewpoint(this.workPackage, index), titleText: this.text.delete_viewpoint, }, ]; diff --git a/frontend/src/app/features/bim/ifc_models/toolbar/import-export-bcf/bcf-export-button.component.ts b/frontend/src/app/features/bim/ifc_models/toolbar/import-export-bcf/bcf-export-button.component.ts index bcaf68a03bd9..0dadc3264f39 100644 --- a/frontend/src/app/features/bim/ifc_models/toolbar/import-export-bcf/bcf-export-button.component.ts +++ b/frontend/src/app/features/bim/ifc_models/toolbar/import-export-bcf/bcf-export-button.component.ts @@ -96,7 +96,7 @@ export class BcfExportButtonComponent extends UntilDestroyedMixin implements OnI }); } - public showDelayedExport(event:any) { + public showDelayedExport(event:Event) { this.requestExport(this.exportLink); event.preventDefault(); diff --git a/frontend/src/app/features/boards/board/add-list-modal/add-list-modal.component.ts b/frontend/src/app/features/boards/board/add-list-modal/add-list-modal.component.ts index 61a34befe334..89af46d9ef82 100644 --- a/frontend/src/app/features/boards/board/add-list-modal/add-list-modal.component.ts +++ b/frontend/src/app/features/boards/board/add-list-modal/add-list-modal.component.ts @@ -97,7 +97,7 @@ export class AddListModalComponent extends OpModalComponent implements OnInit { public warningText:string|undefined; - public text:any = { + public text = { title: this.I18n.t('js.boards.add_list'), button_add: this.I18n.t('js.button_add'), button_create: this.I18n.t('js.button_create'), @@ -118,7 +118,7 @@ export class AddListModalComponent extends OpModalComponent implements OnInit { ngOnInit() { super.ngOnInit(); - this.board = this.locals.board; + this.board = this.locals.board as Board; this.active = new Set(this.locals.active as string[]); this.actionService = this.boardActions.get(this.board.actionAttribute!); this.autocompleterOptions.resource = this.actionService.resourceName.toLowerCase(); @@ -162,15 +162,14 @@ export class AddListModalComponent extends OpModalComponent implements OnInit { } private getVersionPayload(name:string) { - const payload:any = {}; - payload.name = name; - payload._links = { - definingProject: { - href: this.apiV3Service.projects.id(this.currentProject.id!).path, + return { + name, + _links: { + definingProject: { + href: this.apiV3Service.projects.id(this.currentProject.id!).path, + }, }, }; - - return payload; } private warnIfNoOptions(values:unknown[]) { diff --git a/frontend/src/app/features/boards/board/board-list/board-list.component.ts b/frontend/src/app/features/boards/board/board-list/board-list.component.ts index 3b8162fe8d05..ea2f89520ccb 100644 --- a/frontend/src/app/features/boards/board/board-list/board-list.component.ts +++ b/frontend/src/app/features/boards/board/board-list/board-list.component.ts @@ -95,6 +95,7 @@ import { firstValueFrom } from 'rxjs'; import { WorkPackageIsolatedQuerySpaceDirective } from 'core-app/features/work-packages/directives/query-space/wp-isolated-query-space.directive'; import { CurrentProjectService } from 'core-app/core/current-project/current-project.service'; import { PathHelperService } from 'core-app/core/path-helper/path-helper.service'; +import { HTTPClientParamMap } from 'core-app/features/hal/http/http.interfaces'; export interface DisabledButtonPlaceholder { text:string; @@ -176,7 +177,7 @@ export class BoardListComponent extends AbstractWidgetComponent implements OnIni private canAdd = firstValueFrom(this.wpInlineCreate.canAdd); - public columnsQueryProps:any; + public columnsQueryProps:HTTPClientParamMap; public get text() { return { @@ -480,7 +481,7 @@ export class BoardListComponent extends AbstractWidgetComponent implements OnIni const existingFilters = (this.resource.options.filters || []) as ApiV3Filter[]; const newFilters = existingFilters.concat(filters); - const newColumnsQueryProps:any = { + const newColumnsQueryProps:HTTPClientParamMap = { 'columns[]': ['id', 'subject'], showHierarchies: false, pageSize: 500, diff --git a/frontend/src/app/features/boards/board/board-partitioned-page/board-list-container.component.ts b/frontend/src/app/features/boards/board/board-partitioned-page/board-list-container.component.ts index 51e74727d837..0f7aa2cc6cbe 100644 --- a/frontend/src/app/features/boards/board/board-partitioned-page/board-list-container.component.ts +++ b/frontend/src/app/features/boards/board/board-partitioned-page/board-list-container.component.ts @@ -183,12 +183,12 @@ export class BoardListContainerComponent extends UntilDestroyedMixin implements this.saveBoard(board); } - addList(board:Board):any { + addList(board:Board):Promise|undefined { if (board.isFree) { return this.BoardList .addFreeQuery(board, { name: this.text.unnamedList }) .then((board) => this.Boards.save(board).toPromise()) - .catch((error) => this.showError(error)); + .catch((error) => this.showError(error as string)); } const active = this.getActionFiltersFromWidget(board); this.opModalService.show( @@ -196,6 +196,7 @@ export class BoardListContainerComponent extends UntilDestroyedMixin implements this.injector, { board, active }, ); + return undefined; } changeVisibilityOfList(board:Board, boardWidget:GridWidgetResource, visible:boolean) { diff --git a/frontend/src/app/features/boards/board/board-partitioned-page/board-partitioned-page.component.ts b/frontend/src/app/features/boards/board/board-partitioned-page/board-partitioned-page.component.ts index 636492f6b2d1..2cad74ec1979 100644 --- a/frontend/src/app/features/boards/board/board-partitioned-page/board-partitioned-page.component.ts +++ b/frontend/src/app/features/boards/board/board-partitioned-page/board-partitioned-page.component.ts @@ -58,6 +58,7 @@ import { SubmenuService } from 'core-app/core/main-menu/submenu.service'; import { PathHelperService } from 'core-app/core/path-helper/path-helper.service'; import { CurrentProjectService } from 'core-app/core/current-project/current-project.service'; import * as Turbo from '@hotwired/turbo'; +import { ApiV3Filter } from 'core-app/shared/helpers/api-v3/api-v3-filter-builder'; export function boardCardViewHandlerFactory(injector:Injector) { return new CardViewHandlerRegistry(injector); @@ -189,7 +190,7 @@ export class BoardPartitionedPageComponent extends UntilDestroyedMixin implement this.editable = board.editable; this.selectedTitle = board.name; this.titleService.setFirstPart(board.name); - this.boardFilters.filters.putValue(queryProps ? JSON.parse(queryProps) : board.filters); + this.boardFilters.filters.putValue(queryProps ? JSON.parse(queryProps) as ApiV3Filter[] : board.filters); this.cdRef.detectChanges(); }); diff --git a/frontend/src/app/features/boards/board/board.service.ts b/frontend/src/app/features/boards/board/board.service.ts index d84b0c26034d..845028103d15 100644 --- a/frontend/src/app/features/boards/board/board.service.ts +++ b/frontend/src/app/features/boards/board/board.service.ts @@ -51,7 +51,7 @@ export class BoardService { private text = { unnamed_board: this.I18n.t('js.boards.label_unnamed_board'), action_board: (attr:string) => this.I18n.t('js.boards.board_type.action_by_attribute', - { attribute: this.I18n.t(`js.boards.board_type.action_type.${attr}`) }), + { attribute: this.I18n.t(`js.boards.board_type.action_type.${attr}`) }), unnamed_list: this.I18n.t('js.boards.label_unnamed_list'), }; diff --git a/frontend/src/app/features/boards/board/configuration-modal/tabs/highlighting-tab.component.ts b/frontend/src/app/features/boards/board/configuration-modal/tabs/highlighting-tab.component.ts index 6af41e24b0a7..fa0d459955a6 100644 --- a/frontend/src/app/features/boards/board/configuration-modal/tabs/highlighting-tab.component.ts +++ b/frontend/src/app/features/boards/board/configuration-modal/tabs/highlighting-tab.component.ts @@ -73,7 +73,7 @@ export class BoardHighlightingTabComponent implements TabComponent, OnInit { } ngOnInit() { - this.board = this.locals.board; + this.board = this.locals.board as Board; this.highlightingMode = this.board.highlightingMode; this.updateMode(this.highlightingMode); } diff --git a/frontend/src/app/features/hal/http/http.interfaces.ts b/frontend/src/app/features/hal/http/http.interfaces.ts index c0432974a924..bd760862eb56 100644 --- a/frontend/src/app/features/hal/http/http.interfaces.ts +++ b/frontend/src/app/features/hal/http/http.interfaces.ts @@ -40,6 +40,7 @@ export interface HTTPClientOptions { responseType:'json'; } -export type HTTPClientParamMap = Record; -export type HTTPClientHeaders = HttpHeaders|HTTPClientParamMap; +export type HTTPClientParamValue = string|number|boolean|readonly (string|number|boolean)[]; +export type HTTPClientParamMap = Record; +export type HTTPClientHeaders = HttpHeaders|Record; export type HTTPClientParams = HttpParams|HTTPClientParamMap; diff --git a/frontend/src/app/features/user-preferences/state/user-preferences.service.ts b/frontend/src/app/features/user-preferences/state/user-preferences.service.ts index 32bd94ce8b76..5b74b9b2c4c7 100644 --- a/frontend/src/app/features/user-preferences/state/user-preferences.service.ts +++ b/frontend/src/app/features/user-preferences/state/user-preferences.service.ts @@ -34,6 +34,7 @@ import { I18nService } from 'core-app/core/i18n/i18n.service'; import { IUserPreference } from 'core-app/features/user-preferences/state/user-preferences.model'; import { UserPreferencesStore } from 'core-app/features/user-preferences/state/user-preferences.store'; import { UserPreferencesQuery } from 'core-app/features/user-preferences/state/user-preferences.query'; +import { HttpErrorResponse } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class UserPreferencesService { @@ -50,8 +51,8 @@ export class UserPreferencesService { this.preferenceAPI(user) .get() .subscribe( - (prefs) => this.store.update(prefs), - (error) => this.toastService.addError(error), + (prefs) => { this.store.update(prefs); }, + (error:HttpErrorResponse) => this.toastService.addError(error), ) .add( () => this.store.setLoading(false), @@ -68,7 +69,7 @@ export class UserPreferencesService { this.store.update(prefs); this.toastService.addSuccess(this.I18n.t('js.notice_successful_update')); }, - (error) => this.toastService.addError(error), + (error:HttpErrorResponse) => this.toastService.addError(error), ) .add(() => this.store.setLoading(false)); } diff --git a/frontend/src/app/shared/components/autocompleter/create-autocompleter/create-autocompleter.component.ts b/frontend/src/app/shared/components/autocompleter/create-autocompleter/create-autocompleter.component.ts index 08077650eb73..486f26989afb 100644 --- a/frontend/src/app/shared/components/autocompleter/create-autocompleter/create-autocompleter.component.ts +++ b/frontend/src/app/shared/components/autocompleter/create-autocompleter/create-autocompleter.component.ts @@ -62,7 +62,7 @@ export class CreateAutocompleterComponent extends UntilDestroyedMixin implements @Input() public resource:HalResource; - @Input() public model:any; + @Input() public model:unknown; @Input() public required = false; diff --git a/frontend/src/app/shared/components/autocompleter/version-autocompleter/version-autocompleter.component.ts b/frontend/src/app/shared/components/autocompleter/version-autocompleter/version-autocompleter.component.ts index 15ebaaf7c151..486cfc94429d 100644 --- a/frontend/src/app/shared/components/autocompleter/version-autocompleter/version-autocompleter.component.ts +++ b/frontend/src/app/shared/components/autocompleter/version-autocompleter/version-autocompleter.component.ts @@ -107,14 +107,13 @@ export class VersionAutocompleterComponent extends CreateAutocompleterComponent } private getVersionPayload(name:string) { - const payload:any = {}; - payload.name = name; - payload._links = { - definingProject: { - href: this.apiV3Service.projects.id(this.currentProject.id!).path, + return { + name, + _links: { + definingProject: { + href: this.apiV3Service.projects.id(this.currentProject.id!).path, + }, }, }; - - return payload; } } diff --git a/frontend/src/app/shared/components/date/op-date-time.component.ts b/frontend/src/app/shared/components/date/op-date-time.component.ts index 7052772da6bf..3958ed87e67e 100644 --- a/frontend/src/app/shared/components/date/op-date-time.component.ts +++ b/frontend/src/app/shared/components/date/op-date-time.component.ts @@ -47,11 +47,11 @@ import { TimezoneService } from 'core-app/core/datetime/timezone.service'; export class OpDateTimeComponent implements OnInit { readonly timezoneService = inject(TimezoneService); - @Input() dateTimeValue:any; + @Input() dateTimeValue:string; - public date:any; + public date:string; - public time:any; + public time:string; ngOnInit() { const c = this.timezoneService.formattedDatetimeComponents(this.dateTimeValue); diff --git a/frontend/src/app/shared/components/datepicker/wp-date-picker-modal/wp-date-picker.modal.ts b/frontend/src/app/shared/components/datepicker/wp-date-picker-modal/wp-date-picker.modal.ts index 56149d1fd101..ca64bcd32573 100644 --- a/frontend/src/app/shared/components/datepicker/wp-date-picker-modal/wp-date-picker.modal.ts +++ b/frontend/src/app/shared/components/datepicker/wp-date-picker-modal/wp-date-picker.modal.ts @@ -31,6 +31,14 @@ import { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/cor import { OpModalComponent } from 'core-app/shared/components/modal/modal.component'; import { PathHelperService } from 'core-app/core/path-helper/path-helper.service'; +interface DatePickerModalResource { + id:string; + startDate:string|null; + dueDate:string|null; + duration:string|null; + includeNonWorkingDays:boolean|null; +} + @Component({ templateUrl: './wp-date-picker.modal.html', changeDetection: ChangeDetectionStrategy.OnPush, @@ -75,43 +83,33 @@ export class OpWpDatePickerModalComponent extends OpModalComponent implements On } public updateFrameSrc():void { + const resource = this.locals.resource as DatePickerModalResource; const url = new URL( - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - this.pathHelper.workPackageDatepickerDialogContentPath(this.locals.resource.id as string), + this.pathHelper.workPackageDatepickerDialogContentPath(resource.id), window.location.origin, ); - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - url.searchParams.set('field', this.locals.name); - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-member-access - url.searchParams.set('work_package[initial][start_date]', this.nullAsEmptyStringFormatter(this.locals.resource.startDate)); - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-member-access - url.searchParams.set('work_package[initial][due_date]', this.nullAsEmptyStringFormatter(this.locals.resource.dueDate)); - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-member-access - url.searchParams.set('work_package[initial][duration]', this.nullAsEmptyStringFormatter(this.locals.resource.duration)); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument - url.searchParams.set('work_package[initial][ignore_non_working_days]', this.nullAsEmptyStringFormatter(this.locals.resource.includeNonWorkingDays)); - - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-member-access - url.searchParams.set('work_package[start_date]', this.nullAsEmptyStringFormatter(this.locals.resource.startDate)); - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-member-access - url.searchParams.set('work_package[due_date]', this.nullAsEmptyStringFormatter(this.locals.resource.dueDate)); - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-member-access - url.searchParams.set('work_package[duration]', this.nullAsEmptyStringFormatter(this.locals.resource.duration)); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument - url.searchParams.set('work_package[ignore_non_working_days]', this.nullAsEmptyStringFormatter(this.locals.resource.includeNonWorkingDays)); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (this.locals.resource?.id === 'new' && this.locals.resource.startDate) { + url.searchParams.set('field', this.locals.name as string); + url.searchParams.set('work_package[initial][start_date]', this.nullAsEmptyStringFormatter(resource.startDate)); + url.searchParams.set('work_package[initial][due_date]', this.nullAsEmptyStringFormatter(resource.dueDate)); + url.searchParams.set('work_package[initial][duration]', this.nullAsEmptyStringFormatter(resource.duration)); + url.searchParams.set('work_package[initial][ignore_non_working_days]', this.nullAsEmptyStringFormatter(resource.includeNonWorkingDays)); + + url.searchParams.set('work_package[start_date]', this.nullAsEmptyStringFormatter(resource.startDate)); + url.searchParams.set('work_package[due_date]', this.nullAsEmptyStringFormatter(resource.dueDate)); + url.searchParams.set('work_package[duration]', this.nullAsEmptyStringFormatter(resource.duration)); + url.searchParams.set('work_package[ignore_non_working_days]', this.nullAsEmptyStringFormatter(resource.includeNonWorkingDays)); + if (resource.id === 'new' && resource.startDate) { url.searchParams.set('work_package[start_date_touched]', 'true'); } this.turboFrameSrc = url.toString(); } - private nullAsEmptyStringFormatter(value:null|undefined|string):string { + private nullAsEmptyStringFormatter(value:null|undefined|string|boolean):string { if (value === undefined || value === null) { return ''; } - return value; + return String(value); } } diff --git a/frontend/src/app/shared/components/editable-toolbar-title/editable-toolbar-title.component.ts b/frontend/src/app/shared/components/editable-toolbar-title/editable-toolbar-title.component.ts index d3730c056d31..2637ed9558d1 100644 --- a/frontend/src/app/shared/components/editable-toolbar-title/editable-toolbar-title.component.ts +++ b/frontend/src/app/shared/components/editable-toolbar-title/editable-toolbar-title.component.ts @@ -116,7 +116,7 @@ export class EditableToolbarTitleComponent implements OnInit, OnChanges { ngOnChanges(changes:SimpleChanges):void { if (changes.inputTitle) { - this.selectedTitle = changes.inputTitle.currentValue; + this.selectedTitle = changes.inputTitle.currentValue as string; } if (changes.initialFocus && changes.initialFocus.firstChange && this.inputField!) { diff --git a/frontend/src/app/shared/components/grids/grid/area.service.ts b/frontend/src/app/shared/components/grids/grid/area.service.ts index df824687f6f8..a7b1ea8892f9 100644 --- a/frontend/src/app/shared/components/grids/grid/area.service.ts +++ b/frontend/src/app/shared/components/grids/grid/area.service.ts @@ -53,6 +53,8 @@ interface GridPatchPayload { [key:string]:unknown; } +type ScrollIntoViewIfNeededElement = HTMLElement&{ scrollIntoViewIfNeeded?:() => void }; + @Injectable() export class GridAreaService { private apiV3Service = inject(ApiV3Service); @@ -207,10 +209,10 @@ export class GridAreaService { // But as scrollIntoView will always readjust the viewport, the result would be an unbearable flicker // which causes e.g. dragging to be impossible. public scrollPlaceholderIntoView() { - const placeholder = document.querySelector('.grid--area.-placeholder'); + const placeholder = document.querySelector('.grid--area.-placeholder')!; - if ((placeholder as any).scrollIntoViewIfNeeded) { - setTimeout(() => (placeholder as any).scrollIntoViewIfNeeded()); + if (placeholder.scrollIntoViewIfNeeded) { + setTimeout(() => placeholder.scrollIntoViewIfNeeded!()); } } diff --git a/frontend/src/app/shared/components/grids/grid/drag-and-drop.service.ts b/frontend/src/app/shared/components/grids/grid/drag-and-drop.service.ts index 39c6f0cf4279..aa27a9c1301c 100644 --- a/frontend/src/app/shared/components/grids/grid/drag-and-drop.service.ts +++ b/frontend/src/app/shared/components/grids/grid/drag-and-drop.service.ts @@ -116,7 +116,7 @@ export class GridDragAndDropService implements OnDestroy { public start(area:GridWidgetArea) { this.placeholderArea = new GridWidgetArea(area.widget); // TODO find an angular way to do this that ideally does not require passing the element from the grid component - this.draggedHeight = (document as any).getElementById(area.guid).offsetHeight - 2; // border width * 2 + this.draggedHeight = document.getElementById(area.guid)!.offsetHeight - 2; // border width * 2 this.draggedArea = area; } diff --git a/frontend/src/app/shared/components/grids/grid/grid.component.ts b/frontend/src/app/shared/components/grids/grid/grid.component.ts index 4be2ce3f6508..cd4b3a206617 100644 --- a/frontend/src/app/shared/components/grids/grid/grid.component.ts +++ b/frontend/src/app/shared/components/grids/grid/grid.component.ts @@ -26,7 +26,7 @@ // See COPYRIGHT and LICENSE files for more details. //++ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ComponentRef, HostListener, Input, OnDestroy, OnInit, inject } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ComponentRef, HostListener, Input, OnDestroy, OnInit, Type, inject } from '@angular/core'; import { GridResource } from 'core-app/features/hal/resources/grid-resource'; import { DomSanitizer } from '@angular/platform-browser'; import { GridWidgetsService } from 'core-app/shared/components/grids/widgets/widgets.service'; @@ -46,7 +46,7 @@ import { WidgetChangeset } from 'core-app/shared/components/grids/widgets/widget export interface WidgetRegistration { identifier:string; title:string; - component:new (...args:any[]) => AbstractWidgetComponent; + component:Type; properties?:Record; } @@ -80,7 +80,7 @@ export class GridComponent implements OnDestroy, OnInit { readonly browserDetector = inject(BrowserDetector); readonly cdRef = inject(ChangeDetectorRef); - public uiWidgets:ComponentRef[] = []; + public uiWidgets:ComponentRef[] = []; public GRID_AREA_HEIGHT = 'auto'; diff --git a/frontend/src/app/shared/components/grids/widgets/custom-text/custom-text.component.ts b/frontend/src/app/shared/components/grids/widgets/custom-text/custom-text.component.ts index fd2453663860..8cd01711af3f 100644 --- a/frontend/src/app/shared/components/grids/widgets/custom-text/custom-text.component.ts +++ b/frontend/src/app/shared/components/grids/widgets/custom-text/custom-text.component.ts @@ -35,6 +35,7 @@ import { HalResource } from 'core-app/features/hal/resources/hal-resource'; import { filter } from 'rxjs/operators'; import { GridAreaService } from 'core-app/shared/components/grids/grid/area.service'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; +import { GridWidgetResource } from 'core-app/features/hal/resources/grid-widget-resource'; @Component({ templateUrl: './custom-text.component.html', @@ -83,7 +84,7 @@ export class WidgetCustomTextComponent extends AbstractWidgetComponent implement } ngOnChanges(changes:SimpleChanges):void { - if (changes.resource.currentValue.options.text.raw !== this.currentRawText) { + if (((changes.resource.currentValue as GridWidgetResource).options.text as HalResource).raw !== this.currentRawText) { this.setupVariables(); this.cdr.detectChanges(); diff --git a/frontend/src/app/shared/components/grids/widgets/wp-graph/wp-graph.component.html b/frontend/src/app/shared/components/grids/widgets/wp-graph/wp-graph.component.html index 2d2917cff4a8..07d812ba4a0a 100644 --- a/frontend/src/app/shared/components/grids/widgets/wp-graph/wp-graph.component.html +++ b/frontend/src/app/shared/components/grids/widgets/wp-graph/wp-graph.component.html @@ -5,7 +5,7 @@ + (onConfigured)="updateGraph()" /> { this.repaint(); diff --git a/frontend/src/app/shared/components/modal/modal.types.ts b/frontend/src/app/shared/components/modal/modal.types.ts index 832bfa5414e6..992502a64029 100644 --- a/frontend/src/app/shared/components/modal/modal.types.ts +++ b/frontend/src/app/shared/components/modal/modal.types.ts @@ -30,5 +30,5 @@ import { OpModalService } from './modal.service'; export interface OpModalLocalsMap { service:OpModalService; - [key:string]:any; + [key:string]:unknown; } diff --git a/frontend/src/app/shared/components/modals/editor/macro-child-pages-modal/child-pages-macro.modal.ts b/frontend/src/app/shared/components/modals/editor/macro-child-pages-modal/child-pages-macro.modal.ts index d8990ed6458c..5aa4c99f2aa3 100644 --- a/frontend/src/app/shared/components/modals/editor/macro-child-pages-modal/child-pages-macro.modal.ts +++ b/frontend/src/app/shared/components/modals/editor/macro-child-pages-modal/child-pages-macro.modal.ts @@ -55,7 +55,7 @@ export class ChildPagesMacroModalComponent extends OpModalComponent implements A @ViewChild('selectedPageInput', { static: true }) selectedPageInput:ElementRef; - public text:any = { + public text = { title: this.I18n.t('js.editor.macro.child_pages.button'), hint: this.I18n.t('js.editor.macro.child_pages.hint'), page: this.I18n.t('js.editor.macro.child_pages.page'), @@ -68,8 +68,8 @@ export class ChildPagesMacroModalComponent extends OpModalComponent implements A constructor() { super(); - this.selectedPage = this.page = this.locals.page; - this.selectedIncludeParent = this.includeParent = this.locals.includeParent; + this.selectedPage = this.page = this.locals.page as string; + this.selectedIncludeParent = this.includeParent = this.locals.includeParent as boolean; // We could provide an autocompleter here to get correct page names } diff --git a/frontend/src/app/shared/components/modals/editor/macro-code-block-modal/code-block-macro.modal.ts b/frontend/src/app/shared/components/modals/editor/macro-code-block-modal/code-block-macro.modal.ts index 000562428ecb..1dda91bc2044 100644 --- a/frontend/src/app/shared/components/modals/editor/macro-code-block-modal/code-block-macro.modal.ts +++ b/frontend/src/app/shared/components/modals/editor/macro-code-block-modal/code-block-macro.modal.ts @@ -68,7 +68,7 @@ export class CodeBlockMacroModalComponent extends OpModalComponent implements Af readonly I18n = inject(I18nService); readonly codeMirrorLoader = inject(CodeMirrorLoaderService); - public text:any = { + public text = { title: this.I18n.t('js.editor.macro.code_block.title'), language: this.I18n.t('js.editor.macro.code_block.language'), language_hint: this.I18n.t('js.editor.macro.code_block.language_hint'), diff --git a/frontend/src/app/shared/components/modals/editor/macro-wiki-include-page-modal/wiki-include-page-macro.modal.ts b/frontend/src/app/shared/components/modals/editor/macro-wiki-include-page-modal/wiki-include-page-macro.modal.ts index ed02883395af..13ed41c4e21c 100644 --- a/frontend/src/app/shared/components/modals/editor/macro-wiki-include-page-modal/wiki-include-page-macro.modal.ts +++ b/frontend/src/app/shared/components/modals/editor/macro-wiki-include-page-modal/wiki-include-page-macro.modal.ts @@ -51,7 +51,7 @@ export class WikiIncludePageMacroModalComponent extends OpModalComponent impleme @ViewChild('selectedPageInput', { static: true }) selectedPageInput:ElementRef; - public text:any = { + public text = { title: this.I18n.t('js.editor.macro.wiki_page_include.button'), hint: this.I18n.t('js.editor.macro.wiki_page_include.hint'), page: this.I18n.t('js.editor.macro.wiki_page_include.page'), @@ -63,7 +63,7 @@ export class WikiIncludePageMacroModalComponent extends OpModalComponent impleme constructor() { super(); - this.selectedPage = this.page = this.locals.page; + this.selectedPage = this.page = this.locals.page as string; // We could provide an autocompleter here to get correct page names } diff --git a/frontend/src/app/shared/components/modals/editor/macro-wp-button-modal/wp-button-macro.modal.ts b/frontend/src/app/shared/components/modals/editor/macro-wp-button-modal/wp-button-macro.modal.ts index 03a3e812ae19..ff6ad113bfbb 100644 --- a/frontend/src/app/shared/components/modals/editor/macro-wp-button-modal/wp-button-macro.modal.ts +++ b/frontend/src/app/shared/components/modals/editor/macro-wp-button-modal/wp-button-macro.modal.ts @@ -60,7 +60,7 @@ export class WpButtonMacroModalComponent extends OpModalComponent implements Aft @ViewChild('typeSelect', { static: true }) typeSelect:ElementRef; - public text:any = { + public text = { title: this.I18n.t('js.editor.macro.work_package_button.button'), none: this.I18n.t('js.label_none'), selected_type: this.I18n.t('js.editor.macro.work_package_button.type'), @@ -74,8 +74,8 @@ export class WpButtonMacroModalComponent extends OpModalComponent implements Aft constructor() { super(); - this.selectedType = this.type = this.locals.type; - this.classes = this.locals.classes; + this.selectedType = this.type = this.locals.type as string; + this.classes = this.locals.classes as string; this.buttonStyle = this.classes === 'button'; this diff --git a/frontend/src/app/shared/components/option-list/option-list.component.ts b/frontend/src/app/shared/components/option-list/option-list.component.ts index d43ad4aa2413..d86ec57dba2e 100644 --- a/frontend/src/app/shared/components/option-list/option-list.component.ts +++ b/frontend/src/app/shared/components/option-list/option-list.component.ts @@ -92,11 +92,11 @@ export class OpOptionListComponent implements ControlValueAccessor { this.cdRef.markForCheck(); } - registerOnChange(fn:any) { + registerOnChange(fn:(_:IOpOptionListValue) => void) { this.onChange = fn; } - registerOnTouched(fn:any) { + registerOnTouched(fn:(_:IOpOptionListValue) => void) { this.onTouched = fn; } } diff --git a/frontend/src/app/shared/components/principal/principal-types.ts b/frontend/src/app/shared/components/principal/principal-types.ts index 34c100b3d0d5..1c6c2603edac 100644 --- a/frontend/src/app/shared/components/principal/principal-types.ts +++ b/frontend/src/app/shared/components/principal/principal-types.ts @@ -38,5 +38,5 @@ export type PrincipalLike = export interface PrincipalData { principal:PrincipalLike|null; - customFields:Record, + customFields:Record, } diff --git a/frontend/src/app/shared/components/remote-field-updater/remote-field-updater.component.ts b/frontend/src/app/shared/components/remote-field-updater/remote-field-updater.component.ts index 04da91526c67..44ec22156843 100644 --- a/frontend/src/app/shared/components/remote-field-updater/remote-field-updater.component.ts +++ b/frontend/src/app/shared/components/remote-field-updater/remote-field-updater.component.ts @@ -133,7 +133,7 @@ export class RemoteFieldUpdaterComponent implements OnInit, OnDestroy { this .request(params) .subscribe((response:object) => { - Object.entries(response).forEach(([selector, val]) => { + Object.entries(response as Record).forEach(([selector, val]) => { const element = document.getElementById(selector) as HTMLElement|HTMLInputElement; if (element instanceof HTMLInputElement) { diff --git a/frontend/src/app/shared/components/time_entries/edit/trigger-actions-entry.component.ts b/frontend/src/app/shared/components/time_entries/edit/trigger-actions-entry.component.ts index 9e287e91af00..b119fe942d28 100644 --- a/frontend/src/app/shared/components/time_entries/edit/trigger-actions-entry.component.ts +++ b/frontend/src/app/shared/components/time_entries/edit/trigger-actions-entry.component.ts @@ -37,6 +37,7 @@ import { TimeEntryResource } from 'core-app/features/hal/resources/time-entry-re import { Observable, switchMap } from 'rxjs'; import { PathHelperService } from 'core-app/core/path-helper/path-helper.service'; import { TurboRequestsService } from 'core-app/core/turbo/turbo-requests.service'; +import { HttpErrorResponse } from '@angular/common/http'; @Component({ selector: 'opce-time-entry-trigger-actions', @@ -114,7 +115,7 @@ export class TriggerActionsEntryComponent { ) .subscribe( () => window.location.reload(), - (error) => this.toastService.addError(error || this.text.error), + (error:HttpErrorResponse) => this.toastService.addError(error || this.text.error), ); } diff --git a/frontend/src/app/shared/components/work-package-graphs/configuration-modal/wp-graph-configuration.modal.ts b/frontend/src/app/shared/components/work-package-graphs/configuration-modal/wp-graph-configuration.modal.ts index cee7178c858a..4eea1c8e3fbc 100644 --- a/frontend/src/app/shared/components/work-package-graphs/configuration-modal/wp-graph-configuration.modal.ts +++ b/frontend/src/app/shared/components/work-package-graphs/configuration-modal/wp-graph-configuration.modal.ts @@ -42,7 +42,7 @@ import { WpGraphConfigurationService } from 'core-app/shared/components/work-pac import { WpGraphConfiguration } from 'core-app/shared/components/work-package-graphs/configuration/wp-graph-configuration'; import { WorkPackageNotificationService } from 'core-app/features/work-packages/services/notifications/work-package-notification.service'; -export const WpTableConfigurationModalPrependToken = new InjectionToken>('WpTableConfigurationModalPrependComponent'); +export const WpTableConfigurationModalPrependToken = new InjectionToken>('WpTableConfigurationModalPrependComponent'); @Component({ templateUrl: '../../../../features/work-packages/components/wp-table/configuration-modal/wp-table-configuration.modal.html', diff --git a/frontend/src/app/shared/components/work-package-graphs/configuration/wp-graph-configuration.service.ts b/frontend/src/app/shared/components/work-package-graphs/configuration/wp-graph-configuration.service.ts index 8535b58f4d50..8f7842b1a39e 100644 --- a/frontend/src/app/shared/components/work-package-graphs/configuration/wp-graph-configuration.service.ts +++ b/frontend/src/app/shared/components/work-package-graphs/configuration/wp-graph-configuration.service.ts @@ -128,7 +128,6 @@ export class WpGraphConfigurationService { .apiv3Service .queries .find( - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument { pageSize: 0, ...params.props }, params.id, this.projectIdentifier(), diff --git a/frontend/src/app/shared/components/work-package-graphs/configuration/wp-graph-configuration.ts b/frontend/src/app/shared/components/work-package-graphs/configuration/wp-graph-configuration.ts index 3a8679a93cd2..5443c2e71137 100644 --- a/frontend/src/app/shared/components/work-package-graphs/configuration/wp-graph-configuration.ts +++ b/frontend/src/app/shared/components/work-package-graphs/configuration/wp-graph-configuration.ts @@ -32,18 +32,11 @@ import { I18nService } from 'core-app/core/i18n/i18n.service'; export interface WpGraphQueryParams { id?:string; - props?:any; + props?:object; name?:string; } -export interface WpGraphConfiguration { - queries:QueryResource[]; - queryParams:WpGraphQueryParams[]; - chartType:string; - chartOptions:ChartOptions; -} - -export class WpGraphConfiguration implements WpGraphConfiguration { +export class WpGraphConfiguration { public queries:QueryResource[] = []; constructor( diff --git a/frontend/src/app/shared/components/work-package-graphs/embedded/wp-embedded-graph.component.ts b/frontend/src/app/shared/components/work-package-graphs/embedded/wp-embedded-graph.component.ts index c219d3fdff97..eb340633d9a7 100644 --- a/frontend/src/app/shared/components/work-package-graphs/embedded/wp-embedded-graph.component.ts +++ b/frontend/src/app/shared/components/work-package-graphs/embedded/wp-embedded-graph.component.ts @@ -38,7 +38,7 @@ import { chartTypeLocaleKey } from './../chart-type'; export interface WorkPackageEmbeddedGraphDataset { label:string; - queryProps:any; + queryProps:unknown; queryId?:number|string; groups?:GroupObject[]; } @@ -106,24 +106,24 @@ export class WorkPackageEmbeddedGraphComponent implements OnChanges { } private updateChartData() { - let uniqLabels = Array.from(new Set(this.datasets.reduce((array, dataset) => { - const groups = (dataset.groups || []).map((group) => group.value) as any; + const uniqLabels = Array.from(new Set(this.datasets.reduce<(string|null)[]>((array, dataset) => { + const groups = (dataset.groups ?? []).map((group) => group.value as string|null); return array.concat(groups); - }, []))) as string[]; + }, []))); const labelCountMaps = this.datasets.map((dataset) => { - const countMap = (dataset.groups || []).reduce((hash, group) => ({ + const countMap = (dataset.groups ?? []).reduce>((hash, group) => ({ ...hash, [group.value]: group.count, }), {}); return { label: dataset.label, - data: uniqLabels.map((label) => countMap[label] || 0), + data: uniqLabels.map((label) => countMap[String(label)] || 0), }; }); - uniqLabels = uniqLabels.map((label) => { + const displayLabels = uniqLabels.map((label) => { if (label === null) { return this.i18n.t('js.placeholders.default'); } @@ -134,7 +134,7 @@ export class WorkPackageEmbeddedGraphComponent implements OnChanges { // keep the array in order to update the labels this.chartLabels.length = 0; - this.chartLabels.push(...uniqLabels); + this.chartLabels.push(...displayLabels); this.chartData.length = 0; this.chartData.push(...labelCountMaps); } diff --git a/frontend/src/app/spot/components/drop-modal/drop-modal-teleportation.service.ts b/frontend/src/app/spot/components/drop-modal/drop-modal-teleportation.service.ts index ac395fcbe7ec..bb9c26b32cb0 100644 --- a/frontend/src/app/spot/components/drop-modal/drop-modal-teleportation.service.ts +++ b/frontend/src/app/spot/components/drop-modal/drop-modal-teleportation.service.ts @@ -36,7 +36,7 @@ import { } from 'rxjs'; import { distinctUntilChanged, filter, take } from 'rxjs/operators'; -export type TeleportInstance = TemplateRef; +export type TeleportInstance = TemplateRef; @Injectable({ providedIn: 'root' }) export class SpotDropModalTeleportationService {