diff --git a/src/app/core-ui/work-context-menu/work-context-menu.component.ts b/src/app/core-ui/work-context-menu/work-context-menu.component.ts index e0ed8c9a87..ebdaa6f957 100644 --- a/src/app/core-ui/work-context-menu/work-context-menu.component.ts +++ b/src/app/core-ui/work-context-menu/work-context-menu.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, input } from '@angular/core'; import { WorkContextType } from '../../features/work-context/work-context.model'; import { T } from 'src/app/t.const'; import { TODAY_TAG } from '../../features/tag/tag.const'; @@ -21,7 +21,10 @@ import { ProjectService } from '../../features/project/project.service'; imports: [RouterLink, UiModule, RouterModule], }) export class WorkContextMenuComponent { - @Input() project!: Project; + readonly project = input.required(); + // TODO: Skipped for migration because: + // This input is used in a control flow expression (e.g. `@if` or `*ngIf`) + // and migrating would break narrowing currently. @Input() contextId!: string; T: typeof T = T; TODAY_TAG_ID: string = TODAY_TAG.id as string; @@ -36,6 +39,8 @@ export class WorkContextMenuComponent { private _router: Router, ) {} + // TODO: Skipped for migration because: + // Accessor inputs cannot be migrated as they are too complex. @Input('contextType') set contextTypeSet(v: WorkContextType) { this.isForProject = v === WorkContextType.PROJECT; this.base = this.isForProject ? 'project' : 'tag'; diff --git a/src/app/features/add-tasks-for-tomorrow/add-scheduled-for-tomorrow/add-scheduled-today-or-tomorrow-btn.component.html b/src/app/features/add-tasks-for-tomorrow/add-scheduled-for-tomorrow/add-scheduled-today-or-tomorrow-btn.component.html index b083d57afd..6975b70321 100644 --- a/src/app/features/add-tasks-for-tomorrow/add-scheduled-for-tomorrow/add-scheduled-today-or-tomorrow-btn.component.html +++ b/src/app/features/add-tasks-for-tomorrow/add-scheduled-for-tomorrow/add-scheduled-today-or-tomorrow-btn.component.html @@ -1,4 +1,4 @@ -@if (workContextService.isToday &&(isAlwaysShowIfAny || +@if (workContextService.isToday &&(isAlwaysShowIfAny() || (workContextService.activeWorkContext$|async)?.taskIds.length ===0) && (addTasksForTomorrowService.allPlannedForTodayNotOnToday$|async); as plannedForToday) {
diff --git a/src/app/features/add-tasks-for-tomorrow/add-scheduled-for-tomorrow/add-scheduled-today-or-tomorrow-btn.component.ts b/src/app/features/add-tasks-for-tomorrow/add-scheduled-for-tomorrow/add-scheduled-today-or-tomorrow-btn.component.ts index 51244e6611..24de79e142 100644 --- a/src/app/features/add-tasks-for-tomorrow/add-scheduled-for-tomorrow/add-scheduled-today-or-tomorrow-btn.component.ts +++ b/src/app/features/add-tasks-for-tomorrow/add-scheduled-for-tomorrow/add-scheduled-today-or-tomorrow-btn.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { ChangeDetectionStrategy, Component, input } from '@angular/core'; import { T } from '../../../t.const'; import { AsyncPipe } from '@angular/common'; import { MatButton } from '@angular/material/button'; @@ -18,7 +18,7 @@ import { AddTasksForTomorrowService } from '../add-tasks-for-tomorrow.service'; export class AddScheduledTodayOrTomorrowBtnComponent { protected readonly T = T; - @Input() public isAlwaysShowIfAny: boolean = false; + public readonly isAlwaysShowIfAny = input(false); constructor( public workContextService: WorkContextService, diff --git a/src/app/features/bookmark/bookmark-link/bookmark-link.directive.ts b/src/app/features/bookmark/bookmark-link/bookmark-link.directive.ts index 46767ac2fe..b5df4843bd 100644 --- a/src/app/features/bookmark/bookmark-link/bookmark-link.directive.ts +++ b/src/app/features/bookmark/bookmark-link/bookmark-link.directive.ts @@ -1,4 +1,4 @@ -import { Directive, HostListener, Input } from '@angular/core'; +import { Directive, HostListener, input } from '@angular/core'; import { IS_ELECTRON } from '../../../app.constants'; import { BookmarkType } from '../bookmark.model'; import { SnackService } from '../../../core/snack/snack.service'; @@ -9,13 +9,15 @@ import { T } from '../../../t.const'; standalone: false, }) export class BookmarkLinkDirective { - @Input() type?: BookmarkType; - @Input() href?: BookmarkType; + readonly type = input(); + readonly href = input(); constructor(private _snackService: SnackService) {} @HostListener('click', ['$event']) onClick(ev: Event): void { - if (!this.type || !this.href) { + const type = this.type(); + const href = this.href(); + if (!type || !href) { return; } @@ -25,20 +27,20 @@ export class BookmarkLinkDirective { } if (IS_ELECTRON) { ev.preventDefault(); - if (!this.type || this.type === 'LINK') { - this._openExternalUrl(this.href); - } else if (this.type === 'FILE') { - window.ea.openPath(this.href); - } else if (this.type === 'COMMAND') { + if (!type || type === 'LINK') { + this._openExternalUrl(href); + } else if (type === 'FILE') { + window.ea.openPath(href); + } else if (type === 'COMMAND') { this._snackService.open({ msg: T.GLOBAL_SNACK.RUNNING_X, - translateParams: { str: this.href }, + translateParams: { str: href }, ico: 'laptop_windows', }); - this._exec(this.href); + this._exec(href); } - } else if (this.type === 'LINK') { - this._openExternalUrl(this.href); + } else if (type === 'LINK') { + this._openExternalUrl(href); } } diff --git a/src/app/features/config/config-form/config-form.component.ts b/src/app/features/config/config-form/config-form.component.ts index b50dc5a332..70991cff22 100644 --- a/src/app/features/config/config-form/config-form.component.ts +++ b/src/app/features/config/config-form/config-form.component.ts @@ -4,6 +4,7 @@ import { EventEmitter, Input, Output, + input, } from '@angular/core'; import { FormlyFieldConfig, FormlyFormOptions } from '@ngx-formly/core'; import { UntypedFormGroup } from '@angular/forms'; @@ -23,7 +24,7 @@ import { adjustToLiveFormlyForm } from '../../../util/adjust-to-live-formly-form export class ConfigFormComponent { T: typeof T = T; config?: Record; - @Input() sectionKey?: GlobalConfigSectionKey | ProjectCfgFormKey; + readonly sectionKey = input(); @Output() save: EventEmitter<{ sectionKey: GlobalConfigSectionKey | ProjectCfgFormKey; config: unknown; @@ -34,6 +35,8 @@ export class ConfigFormComponent { constructor() {} + // TODO: Skipped for migration because: + // Accessor inputs cannot be migrated as they are too complex. @Input() set cfg(cfg: Record) { this.config = { ...cfg }; } @@ -41,18 +44,20 @@ export class ConfigFormComponent { // NOTE: updating the input before assigning to local var is somehow needed for the form to work // NOTE2: since we don't have a save button anymore we need to debounce inputs + // TODO: Skipped for migration because: + // Accessor inputs cannot be migrated as they are too complex. @Input() set formCfg(val: FormlyFieldConfig[]) { this.fields = adjustToLiveFormlyForm(val); } updateCfg(cfg: Record): void { if (!cfg) { - throw new Error('No config for ' + this.sectionKey); + throw new Error('No config for ' + this.sectionKey()); } this.config = cfg; if (this.form.valid) { this.save.emit({ - sectionKey: exists(this.sectionKey), + sectionKey: exists(this.sectionKey()), config: this.config, }); } else { diff --git a/src/app/features/config/config-section/config-section.component.ts b/src/app/features/config/config-section/config-section.component.ts index 13f67107a8..3884bf8399 100644 --- a/src/app/features/config/config-section/config-section.component.ts +++ b/src/app/features/config/config-section/config-section.component.ts @@ -35,6 +35,9 @@ import { exists } from '../../../util/exists'; standalone: false, }) export class ConfigSectionComponent implements OnInit, OnDestroy { + // TODO: Skipped for migration because: + // This input is used in a control flow expression (e.g. `@if` or `*ngIf`) + // and migrating would break narrowing currently. @Input() section?: ConfigFormSection<{ [key: string]: any }>; @Output() save: EventEmitter<{ sectionKey: GlobalConfigSectionKey | ProjectCfgFormKey | TagCfgFormKey; @@ -59,6 +62,8 @@ export class ConfigSectionComponent implements OnInit, OnDestroy { return this._cfg; } + // TODO: Skipped for migration because: + // Accessor inputs cannot be migrated as they are too complex. @Input() set cfg(v: any) { this._cfg = v; if (v && this._instance) { diff --git a/src/app/features/config/config-sound-form/config-sound-form.component.ts b/src/app/features/config/config-sound-form/config-sound-form.component.ts index e9169569d6..cdaafbd4ca 100644 --- a/src/app/features/config/config-sound-form/config-sound-form.component.ts +++ b/src/app/features/config/config-sound-form/config-sound-form.component.ts @@ -18,6 +18,8 @@ const sectionKey = 'sound'; standalone: false, }) export class ConfigSoundFormComponent { + // TODO: Skipped for migration because: + // Accessor inputs cannot be migrated as they are too complex. @Input() set cfg(cfg: SoundConfig) { this.config = { ...cfg }; this.patchForm(); diff --git a/src/app/features/issue/issue-content/issue-content.component.html b/src/app/features/issue/issue-content/issue-content.component.html index 4e6d1918f4..d8ea6cd205 100644 --- a/src/app/features/issue/issue-content/issue-content.component.html +++ b/src/app/features/issue/issue-content/issue-content.component.html @@ -1,36 +1,36 @@ @if (task?.issueType===JIRA_TYPE) { } @if (task?.issueType===GITHUB_TYPE) { } @if (task?.issueType===REDMINE_TYPE) { } @if (task?.issueType===GITLAB_TYPE) { } @if (task?.issueType===CALDAV_TYPE) { } @if (task?.issueType===OPEN_PROJECT_TYPE) { } @if (task?.issueType===GITEA_TYPE) { } diff --git a/src/app/features/issue/issue-content/issue-content.component.ts b/src/app/features/issue/issue-content/issue-content.component.ts index 658a37595b..cd213dfa21 100644 --- a/src/app/features/issue/issue-content/issue-content.component.ts +++ b/src/app/features/issue/issue-content/issue-content.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, input } from '@angular/core'; import { TaskWithSubTasks } from '../../tasks/task.model'; import { CALDAV_TYPE, @@ -19,8 +19,11 @@ import { IssueData } from '../issue.model'; standalone: false, }) export class IssueContentComponent { + // TODO: Skipped for migration because: + // This input is used in a control flow expression (e.g. `@if` or `*ngIf`) + // and migrating would break narrowing currently. @Input() task?: TaskWithSubTasks; - @Input() issueData?: IssueData; + readonly issueData = input(); readonly GITLAB_TYPE: string = GITLAB_TYPE; readonly GITHUB_TYPE: string = GITHUB_TYPE; readonly REDMINE_TYPE: string = REDMINE_TYPE; diff --git a/src/app/features/issue/issue-header/issue-header.component.ts b/src/app/features/issue/issue-header/issue-header.component.ts index dd0c06adba..7f0a5b43a4 100644 --- a/src/app/features/issue/issue-header/issue-header.component.ts +++ b/src/app/features/issue/issue-header/issue-header.component.ts @@ -18,6 +18,9 @@ import { standalone: false, }) export class IssueHeaderComponent { + // TODO: Skipped for migration because: + // This input is used in a control flow expression (e.g. `@if` or `*ngIf`) + // and migrating would break narrowing currently. @Input() task?: TaskWithSubTasks; readonly GITLAB_TYPE: string = GITLAB_TYPE; diff --git a/src/app/features/issue/providers/caldav/caldav-issue/caldav-issue-content/caldav-issue-content.component.html b/src/app/features/issue/providers/caldav/caldav-issue/caldav-issue-content/caldav-issue-content.component.html index 86177bb134..df28eb487f 100644 --- a/src/app/features/issue/providers/caldav/caldav-issue/caldav-issue-content/caldav-issue-content.component.html +++ b/src/app/features/issue/providers/caldav/caldav-issue/caldav-issue-content/caldav-issue-content.component.html @@ -1,5 +1,5 @@ - @if (task?.issueWasUpdated) { + @if (task()?.issueWasUpdated) {
(); T: typeof T = T; constructor(private readonly _taskService: TaskService) {} hideUpdates(): void { - if (!this.task) { + const task = this.task(); + if (!task) { throw new Error('No task'); } if (!this.issue) { throw new Error('No issue'); } - this._taskService.markIssueUpdatesAsRead(this.task.id); + this._taskService.markIssueUpdatesAsRead(task.id); } trackByIndex(i: number, p: any): number { diff --git a/src/app/features/issue/providers/caldav/caldav-issue/caldav-issue-header/caldav-issue-header.component.html b/src/app/features/issue/providers/caldav/caldav-issue/caldav-issue-header/caldav-issue-header.component.html index 735ff2725f..c147cbb27b 100644 --- a/src/app/features/issue/providers/caldav/caldav-issue/caldav-issue-header/caldav-issue-header.component.html +++ b/src/app/features/issue/providers/caldav/caldav-issue/caldav-issue-header/caldav-issue-header.component.html @@ -1,10 +1,10 @@ -@if (task?.issueWasUpdated) { +@if (task()?.issueWasUpdated) { update -} @if (!task?.issueWasUpdated) { +} @if (!task()?.issueWasUpdated) { (); constructor() {} } diff --git a/src/app/features/issue/providers/gitea/gitea-issue/gitea-issue-content/gitea-issue-content.component.html b/src/app/features/issue/providers/gitea/gitea-issue/gitea-issue-content/gitea-issue-content.component.html index b499362f62..dc19770448 100644 --- a/src/app/features/issue/providers/gitea/gitea-issue/gitea-issue-content/gitea-issue-content.component.html +++ b/src/app/features/issue/providers/gitea/gitea-issue/gitea-issue-content/gitea-issue-content.component.html @@ -1,5 +1,5 @@ - @if (task?.issueWasUpdated) { + @if (task()?.issueWasUpdated) {
(); T: typeof T = T; constructor(private readonly _taskService: TaskService) {} hideUpdates(): void { - if (!this.task) { + const task = this.task(); + if (!task) { throw new Error('No task'); } if (!this.issue) { throw new Error('No issue'); } - this._taskService.markIssueUpdatesAsRead(this.task.id); + this._taskService.markIssueUpdatesAsRead(task.id); } trackByIndex(i: number, p: any): number { diff --git a/src/app/features/issue/providers/gitea/gitea-issue/gitea-issue-header/gitea-issue-header.component.html b/src/app/features/issue/providers/gitea/gitea-issue/gitea-issue-header/gitea-issue-header.component.html index 098cd5c883..76529c3d24 100644 --- a/src/app/features/issue/providers/gitea/gitea-issue/gitea-issue-header/gitea-issue-header.component.html +++ b/src/app/features/issue/providers/gitea/gitea-issue/gitea-issue-header/gitea-issue-header.component.html @@ -1,10 +1,10 @@ -@if (task?.issueWasUpdated) { +@if (task()?.issueWasUpdated) { update -} @if (!task?.issueWasUpdated) { +} @if (!task()?.issueWasUpdated) { (); constructor() {} } diff --git a/src/app/features/issue/providers/github/github-issue/github-issue-content/github-issue-content.component.html b/src/app/features/issue/providers/github/github-issue/github-issue-content/github-issue-content.component.html index 2579b1a388..7477bb0135 100644 --- a/src/app/features/issue/providers/github/github-issue/github-issue-content/github-issue-content.component.html +++ b/src/app/features/issue/providers/github/github-issue/github-issue-content/github-issue-content.component.html @@ -1,5 +1,5 @@ - @if (task?.issueWasUpdated) { + @if (task()?.issueWasUpdated) {
(); T: typeof T = T; @@ -45,13 +48,14 @@ export class GithubIssueContentComponent { } hideUpdates(): void { - if (!this.task) { + const task = this.task(); + if (!task) { throw new Error('No task'); } if (!this.issue) { throw new Error('No issue'); } - this._taskService.markIssueUpdatesAsRead(this.task.id); + this._taskService.markIssueUpdatesAsRead(task.id); } trackByIndex(i: number, p: any): number { diff --git a/src/app/features/issue/providers/github/github-issue/github-issue-header/github-issue-header.component.html b/src/app/features/issue/providers/github/github-issue/github-issue-header/github-issue-header.component.html index 321214b070..306a65cebf 100644 --- a/src/app/features/issue/providers/github/github-issue/github-issue-header/github-issue-header.component.html +++ b/src/app/features/issue/providers/github/github-issue/github-issue-header/github-issue-header.component.html @@ -1,10 +1,10 @@ -@if (task?.issueWasUpdated) { +@if (task()?.issueWasUpdated) { update -} @if (!task?.issueWasUpdated) { +} @if (!task()?.issueWasUpdated) { (); constructor() {} } diff --git a/src/app/features/issue/providers/gitlab/gitlab-issue/gitlab-issue-content/gitlab-issue-content.component.html b/src/app/features/issue/providers/gitlab/gitlab-issue/gitlab-issue-content/gitlab-issue-content.component.html index f01db5968f..a1996327f0 100644 --- a/src/app/features/issue/providers/gitlab/gitlab-issue/gitlab-issue-content/gitlab-issue-content.component.html +++ b/src/app/features/issue/providers/gitlab/gitlab-issue/gitlab-issue-content/gitlab-issue-content.component.html @@ -1,5 +1,5 @@ - @if (task?.issueWasUpdated) { + @if (task()?.issueWasUpdated) {
(); T: typeof T = T; constructor(private readonly _taskService: TaskService) {} hideUpdates(): void { - if (!this.task) { + const task = this.task(); + if (!task) { throw new Error('No task'); } if (!this.issue) { throw new Error('No issue'); } - this._taskService.markIssueUpdatesAsRead(this.task.id); + this._taskService.markIssueUpdatesAsRead(task.id); } trackByIndex(i: number, p: any): number { diff --git a/src/app/features/issue/providers/gitlab/gitlab-issue/gitlab-issue-header/gitlab-issue-header.component.html b/src/app/features/issue/providers/gitlab/gitlab-issue/gitlab-issue-header/gitlab-issue-header.component.html index 9e9830e125..4582f0c585 100644 --- a/src/app/features/issue/providers/gitlab/gitlab-issue/gitlab-issue-header/gitlab-issue-header.component.html +++ b/src/app/features/issue/providers/gitlab/gitlab-issue/gitlab-issue-header/gitlab-issue-header.component.html @@ -1,10 +1,10 @@ -@if (task?.issueWasUpdated) { +@if (task()?.issueWasUpdated) { update -} @if (!task?.issueWasUpdated) { +} @if (!task()?.issueWasUpdated) { (); constructor() {} } diff --git a/src/app/features/issue/providers/jira/jira-issue/jira-issue-content/jira-issue-content.component.ts b/src/app/features/issue/providers/jira/jira-issue/jira-issue-content/jira-issue-content.component.ts index dd8fd5f5e1..23d3498806 100644 --- a/src/app/features/issue/providers/jira/jira-issue/jira-issue-content/jira-issue-content.component.ts +++ b/src/app/features/issue/providers/jira/jira-issue/jira-issue-content/jira-issue-content.component.ts @@ -91,6 +91,8 @@ export class JiraIssueContentComponent { private readonly _jiraCommonInterfacesService: JiraCommonInterfacesService, ) {} + // TODO: Skipped for migration because: + // Accessor inputs cannot be migrated as they are too complex. @Input('issue') set issueIn(i: JiraIssue) { this.issue = i; this._issue$.next(i); @@ -103,6 +105,8 @@ export class JiraIssueContentComponent { } } + // TODO: Skipped for migration because: + // Accessor inputs cannot be migrated as they are too complex. @Input('task') set taskIn(v: TaskWithSubTasks) { this.task = v; this._task$.next(v); diff --git a/src/app/features/issue/providers/jira/jira-issue/jira-issue-header/jira-issue-header.component.html b/src/app/features/issue/providers/jira/jira-issue/jira-issue-header/jira-issue-header.component.html index 166634849a..99f62c71e4 100644 --- a/src/app/features/issue/providers/jira/jira-issue/jira-issue-header/jira-issue-header.component.html +++ b/src/app/features/issue/providers/jira/jira-issue/jira-issue-header/jira-issue-header.component.html @@ -1,10 +1,10 @@ -@if ((isOnline$|async)) { @if (task?.issueWasUpdated) { +@if ((isOnline$|async)) { @if (task()?.issueWasUpdated) { update -} @if (!task?.issueWasUpdated) { +} @if (!task()?.issueWasUpdated) { (); isOnline$: Observable = isOnline$; constructor() {} diff --git a/src/app/features/issue/providers/jira/jira-view-components/jira-cfg/jira-additional-cfg.component.ts b/src/app/features/issue/providers/jira/jira-view-components/jira-cfg/jira-additional-cfg.component.ts index bcad89a397..2b9700778f 100644 --- a/src/app/features/issue/providers/jira/jira-view-components/jira-cfg/jira-additional-cfg.component.ts +++ b/src/app/features/issue/providers/jira/jira-view-components/jira-cfg/jira-additional-cfg.component.ts @@ -6,6 +6,7 @@ import { OnDestroy, OnInit, Output, + input, } from '@angular/core'; import { ConfigFormSection } from '../../../../../config/global-config.model'; import { FormlyFormOptions } from '@ngx-formly/core'; @@ -33,7 +34,7 @@ import { assertTruthy } from '../../../../../../util/assert-truthy'; standalone: false, }) export class JiraAdditionalCfgComponent implements OnInit, OnDestroy { - @Input() section?: ConfigFormSection; + readonly section = input>(); @Output() modelChange: EventEmitter = new EventEmitter(); @@ -92,6 +93,8 @@ export class JiraAdditionalCfgComponent implements OnInit, OnDestroy { } // NOTE: this is legit because it might be that there is no issue provider cfg yet + // TODO: Skipped for migration because: + // Accessor inputs cannot be migrated as they are too complex. @Input() set cfg(cfg: IssueProviderJira) { const newCfg: IssueProviderJira = { ...cfg }; const isEqual = JSON.stringify(newCfg) === JSON.stringify(this._cfg); diff --git a/src/app/features/issue/providers/open-project/open-project-issue/open-project-issue-content/open-project-issue-content.component.html b/src/app/features/issue/providers/open-project/open-project-issue/open-project-issue-content/open-project-issue-content.component.html index 78d072357c..5c19620076 100644 --- a/src/app/features/issue/providers/open-project/open-project-issue/open-project-issue-content/open-project-issue-content.component.html +++ b/src/app/features/issue/providers/open-project/open-project-issue/open-project-issue-content/open-project-issue-content.component.html @@ -1,5 +1,5 @@ - @if (task?.issueWasUpdated) { + @if (task()?.issueWasUpdated) {
(); T: typeof T = T; constructor(private readonly _taskService: TaskService) {} hideUpdates(): void { - if (!this.task) { + const task = this.task(); + if (!task) { throw new Error('No task'); } if (!this.issue) { throw new Error('No issue'); } - this._taskService.markIssueUpdatesAsRead(this.task.id); + this._taskService.markIssueUpdatesAsRead(task.id); } trackByIndex(i: number, p: any): number { diff --git a/src/app/features/issue/providers/open-project/open-project-issue/open-project-issue-header/open-project-issue-header.component.html b/src/app/features/issue/providers/open-project/open-project-issue/open-project-issue-header/open-project-issue-header.component.html index 5269afb099..11b612af79 100644 --- a/src/app/features/issue/providers/open-project/open-project-issue/open-project-issue-header/open-project-issue-header.component.html +++ b/src/app/features/issue/providers/open-project/open-project-issue/open-project-issue-header/open-project-issue-header.component.html @@ -1,10 +1,10 @@ -@if (task?.issueWasUpdated) { +@if (task()?.issueWasUpdated) { update -} @if (!task?.issueWasUpdated) { +} @if (!task()?.issueWasUpdated) { (); constructor() {} } diff --git a/src/app/features/issue/providers/open-project/open-project-view-components/openproject-cfg/open-project-additional-cfg.component.ts b/src/app/features/issue/providers/open-project/open-project-view-components/openproject-cfg/open-project-additional-cfg.component.ts index cab68a93d0..b86faa4681 100644 --- a/src/app/features/issue/providers/open-project/open-project-view-components/openproject-cfg/open-project-additional-cfg.component.ts +++ b/src/app/features/issue/providers/open-project/open-project-view-components/openproject-cfg/open-project-additional-cfg.component.ts @@ -6,6 +6,7 @@ import { OnDestroy, OnInit, Output, + input, } from '@angular/core'; import { FormsModule, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; import { FormlyFieldConfig, FormlyFormOptions } from '@ngx-formly/core'; @@ -44,7 +45,7 @@ import { assertTruthy } from '../../../../../../util/assert-truthy'; animations: [expandAnimation], }) export class OpenProjectAdditionalCfgComponent implements OnInit, OnDestroy { - @Input() section?: ConfigFormSection; + readonly section = input>(); @Output() modelChange: EventEmitter = new EventEmitter(); T: typeof T = T; HelperClasses: typeof HelperClasses = HelperClasses; @@ -86,6 +87,8 @@ export class OpenProjectAdditionalCfgComponent implements OnInit, OnDestroy { } // NOTE: this is legit because it might be that there is no issue provider cfg yet + // TODO: Skipped for migration because: + // Accessor inputs cannot be migrated as they are too complex. @Input() set cfg(cfg: IssueProviderOpenProject) { const newCfg: IssueProviderOpenProject = { ...cfg }; const isEqual = JSON.stringify(newCfg) === JSON.stringify(this._cfg); @@ -121,7 +124,7 @@ export class OpenProjectAdditionalCfgComponent implements OnInit, OnDestroy { } ngOnInit(): void { - this.fields = (this.section as ConfigFormSection).items; + this.fields = (this.section() as ConfigFormSection).items; } ngOnDestroy(): void { diff --git a/src/app/features/issue/providers/redmine/redmine-issue/redmine-issue-content/redmine-issue-content.component.html b/src/app/features/issue/providers/redmine/redmine-issue/redmine-issue-content/redmine-issue-content.component.html index 26a2b8ffd9..d506d63125 100644 --- a/src/app/features/issue/providers/redmine/redmine-issue/redmine-issue-content/redmine-issue-content.component.html +++ b/src/app/features/issue/providers/redmine/redmine-issue/redmine-issue-content/redmine-issue-content.component.html @@ -34,7 +34,7 @@
- @if (task?.issueWasUpdated) { + @if (task()?.issueWasUpdated) {
(); T: typeof T = T; constructor(private readonly _taskService: TaskService) {} hideUpdates(): void { - if (!this.task) { + const task = this.task(); + if (!task) { throw new Error('No task'); } if (!this.issue) { throw new Error('No issue'); } - this._taskService.markIssueUpdatesAsRead(this.task.id); + this._taskService.markIssueUpdatesAsRead(task.id); } trackByIndex(i: number, p: any): number { diff --git a/src/app/features/issue/providers/redmine/redmine-issue/redmine-issue-header/redmine-issue-header.component.html b/src/app/features/issue/providers/redmine/redmine-issue/redmine-issue-header/redmine-issue-header.component.html index e80abdd380..27e914dcad 100644 --- a/src/app/features/issue/providers/redmine/redmine-issue/redmine-issue-header/redmine-issue-header.component.html +++ b/src/app/features/issue/providers/redmine/redmine-issue/redmine-issue-header/redmine-issue-header.component.html @@ -1,10 +1,10 @@ -@if (task?.issueWasUpdated) { +@if (task()?.issueWasUpdated) { update -} @if (!task?.issueWasUpdated) { +} @if (!task()?.issueWasUpdated) { (); constructor() {} } diff --git a/src/app/features/metric/evaluation-sheet/evaluation-sheet.component.ts b/src/app/features/metric/evaluation-sheet/evaluation-sheet.component.ts index 34be5c0c89..d9bcd1679c 100644 --- a/src/app/features/metric/evaluation-sheet/evaluation-sheet.component.ts +++ b/src/app/features/metric/evaluation-sheet/evaluation-sheet.component.ts @@ -50,6 +50,8 @@ export class EvaluationSheetComponent implements OnDestroy, OnInit { private _dateService: DateService, ) {} + // TODO: Skipped for migration because: + // Accessor inputs cannot be migrated as they are too complex. @Input() set day(val: string) { this.day$.next(val); } diff --git a/src/app/features/note/note/note.component.html b/src/app/features/note/note/note.component.html index 2bc8498c8e..faa40277da 100644 --- a/src/app/features/note/note/note.component.html +++ b/src/app/features/note/note/note.component.html @@ -1,6 +1,6 @@ @if (note) {
diff --git a/src/app/features/note/note/note.component.ts b/src/app/features/note/note/note.component.ts index 2e8559aae2..93c493a835 100644 --- a/src/app/features/note/note/note.component.ts +++ b/src/app/features/note/note/note.component.ts @@ -5,6 +5,7 @@ import { OnChanges, SimpleChanges, viewChild, + input, } from '@angular/core'; import { Note } from '../note.model'; import { NoteService } from '../note.service'; @@ -30,12 +31,14 @@ export class NoteComponent implements OnChanges { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion note!: Note; + // TODO: Skipped for migration because: + // Accessor inputs cannot be migrated as they are too complex. @Input('note') set noteSet(v: Note) { this.note = v; this._note$.next(v); } - @Input() isFocus?: boolean; + readonly isFocus = input(); readonly markdownEl = viewChild('markdownEl'); diff --git a/src/app/features/planner/add-task-inline/add-task-inline.component.html b/src/app/features/planner/add-task-inline/add-task-inline.component.html index f2a322bb6e..50bd5f5373 100644 --- a/src/app/features/planner/add-task-inline/add-task-inline.component.html +++ b/src/app/features/planner/add-task-inline/add-task-inline.component.html @@ -14,6 +14,6 @@ [isHideTagTitles]="true " (blurred)="isShowAddTask = false" (done)="isShowAddTask = false" - [planForDay]="planForDay" + [planForDay]="planForDay()" > } diff --git a/src/app/features/planner/add-task-inline/add-task-inline.component.ts b/src/app/features/planner/add-task-inline/add-task-inline.component.ts index d0063c106d..83adcf9712 100644 --- a/src/app/features/planner/add-task-inline/add-task-inline.component.ts +++ b/src/app/features/planner/add-task-inline/add-task-inline.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { ChangeDetectionStrategy, Component, input } from '@angular/core'; import { TasksModule } from '../../tasks/tasks.module'; import { UiModule } from '../../../ui/ui.module'; @@ -14,7 +14,7 @@ import { T } from 'src/app/t.const'; export class AddTaskInlineComponent { T: typeof T = T; - @Input() planForDay?: string; + readonly planForDay = input(); isShowAddTask = false; } diff --git a/src/app/features/planner/planner-calendar-event/planner-calendar-event.component.html b/src/app/features/planner/planner-calendar-event/planner-calendar-event.component.html index eb631927b4..578a429e91 100644 --- a/src/app/features/planner/planner-calendar-event/planner-calendar-event.component.html +++ b/src/app/features/planner/planner-calendar-event/planner-calendar-event.component.html @@ -1,7 +1,7 @@ -{{ calendarEvent.icon || 'event' }} +{{ calendarEvent().icon || 'event' }} add
- {{ calendarEvent.title }} + {{ calendarEvent().title }}
-
{{ calendarEvent.duration|msToString }}
+
{{ calendarEvent().duration|msToString }}
diff --git a/src/app/features/planner/planner-calendar-event/planner-calendar-event.component.ts b/src/app/features/planner/planner-calendar-event/planner-calendar-event.component.ts index 73489084ca..78ea4c9f1f 100644 --- a/src/app/features/planner/planner-calendar-event/planner-calendar-event.component.ts +++ b/src/app/features/planner/planner-calendar-event/planner-calendar-event.component.ts @@ -4,7 +4,7 @@ import { HostBinding, HostListener, inject, - Input, + input, } from '@angular/core'; import { ScheduleFromCalendarEvent } from '../../schedule/schedule.model'; import { IssueService } from '../../issue/issue.service'; @@ -19,7 +19,7 @@ import { IssueService } from '../../issue/issue.service'; export class PlannerCalendarEventComponent { private _issueService = inject(IssueService); - @Input({ required: true }) calendarEvent!: ScheduleFromCalendarEvent; + readonly calendarEvent = input.required(); isBeingSubmitted = false; @HostBinding('attr.title') title = `Convert to task`; @@ -37,8 +37,8 @@ export class PlannerCalendarEventComponent { this.isBeingSubmitted = true; this._issueService.addTaskFromIssue({ - issueDataReduced: this.calendarEvent, - issueProviderId: this.calendarEvent.calProviderId, + issueDataReduced: this.calendarEvent(), + issueProviderId: this.calendarEvent().calProviderId, issueProviderKey: 'ICAL', isForceDefaultProject: true, }); diff --git a/src/app/features/planner/planner-day/planner-day.component.ts b/src/app/features/planner/planner-day/planner-day.component.ts index ff08b3273c..b9ae6561df 100644 --- a/src/app/features/planner/planner-day/planner-day.component.ts +++ b/src/app/features/planner/planner-day/planner-day.component.ts @@ -25,6 +25,9 @@ import { dateStrToUtcDate } from '../../../util/date-str-to-utc-date'; standalone: false, }) export class PlannerDayComponent { + // TODO: Skipped for migration because: + // This input is used in a control flow expression (e.g. `@if` or `*ngIf`) + // and migrating would break narrowing currently. @Input() day!: PlannerDay; protected readonly T = T; diff --git a/src/app/features/planner/planner-task/planner-task.component.ts b/src/app/features/planner/planner-task/planner-task.component.ts index d7320e09e2..71270215c0 100644 --- a/src/app/features/planner/planner-task/planner-task.component.ts +++ b/src/app/features/planner/planner-task/planner-task.component.ts @@ -8,6 +8,7 @@ import { OnDestroy, OnInit, viewChild, + input, } from '@angular/core'; import { TaskCopy } from '../../tasks/task.model'; import { EMPTY, Observable } from 'rxjs'; @@ -30,8 +31,11 @@ import { TaskContextMenuComponent } from '../../tasks/task-context-menu/task-con standalone: false, }) export class PlannerTaskComponent extends BaseComponent implements OnInit, OnDestroy { + // TODO: Skipped for migration because: + // This input is used in a control flow expression (e.g. `@if` or `*ngIf`) + // and migrating would break narrowing currently. @Input({ required: true }) task!: TaskCopy; - @Input() day?: string; + readonly day = input(); isRepeatTaskCreatedToday = false; diff --git a/src/app/features/right-panel/right-panel.component.html b/src/app/features/right-panel/right-panel.component.html index b6feab9d41..b4b639c957 100644 --- a/src/app/features/right-panel/right-panel.component.html +++ b/src/app/features/right-panel/right-panel.component.html @@ -1,7 +1,7 @@ @@ -17,7 +17,7 @@ } @if (selectedTaskWithDelayForNone$|async; as selectedTaskWithDelayForNone) { (false); // to still display its data when panel is closing selectedTaskWithDelayForNone$: Observable = diff --git a/src/app/features/schedule/schedule-event/schedule-event.component.ts b/src/app/features/schedule/schedule-event/schedule-event.component.ts index 3e89a3fbd0..5debd57f53 100644 --- a/src/app/features/schedule/schedule-event/schedule-event.component.ts +++ b/src/app/features/schedule/schedule-event/schedule-event.component.ts @@ -86,6 +86,8 @@ export class ScheduleEventComponent implements OnInit { private _isBeingSubmitted: boolean = false; private _projectId$ = new BehaviorSubject(null); + // TODO: Skipped for migration because: + // Accessor inputs cannot be migrated as they are too complex. @Input({ required: true }) set event(event: ScheduleEvent) { this.se = event; diff --git a/src/app/features/simple-counter/simple-counter-cfg/simple-counter-cfg.component.ts b/src/app/features/simple-counter/simple-counter-cfg/simple-counter-cfg.component.ts index 2e4ef30cc8..e7f5d8540b 100644 --- a/src/app/features/simple-counter/simple-counter-cfg/simple-counter-cfg.component.ts +++ b/src/app/features/simple-counter/simple-counter-cfg/simple-counter-cfg.component.ts @@ -5,6 +5,7 @@ import { Input, OnDestroy, Output, + input, } from '@angular/core'; import { ConfigFormSection, @@ -30,8 +31,10 @@ import { adjustToLiveFormlyForm } from '../../../util/adjust-to-live-formly-form standalone: false, }) export class SimpleCounterCfgComponent implements OnDestroy { - @Input() cfg?: SimpleCounterConfig; + readonly cfg = input(); + // TODO: Skipped for migration because: + // Accessor inputs cannot be migrated as they are too complex. @Input() set section(section: ConfigFormSection) { if (section.items) { this.items = adjustToLiveFormlyForm(section.items); diff --git a/src/app/features/tasks/select-task/select-task.component.ts b/src/app/features/tasks/select-task/select-task.component.ts index 851049bf97..9f38ce2411 100644 --- a/src/app/features/tasks/select-task/select-task.component.ts +++ b/src/app/features/tasks/select-task/select-task.component.ts @@ -6,6 +6,7 @@ import { OnDestroy, OnInit, Output, + input, } from '@angular/core'; import { UntypedFormControl } from '@angular/forms'; import { Task } from '../task.model'; @@ -35,8 +36,8 @@ export class SelectTaskComponent implements OnInit, OnDestroy { projectMap: { [key: string]: Project } = {}; isCreate: boolean = false; @Output() taskChange: EventEmitter = new EventEmitter(); - @Input() isLimitToProject: boolean = false; - @Input() isIncludeDoneTasks: boolean = false; + readonly isLimitToProject = input(false); + readonly isIncludeDoneTasks = input(false); private _destroy$: Subject = new Subject(); constructor( @@ -44,6 +45,8 @@ export class SelectTaskComponent implements OnInit, OnDestroy { private _store: Store, ) {} + // TODO: Skipped for migration because: + // Accessor inputs cannot be migrated as they are too complex. @Input() set initialTask(task: Task) { if ((task && !this.taskSelectCtrl.value) || this.taskSelectCtrl.value === '') { this.isCreate = false; @@ -60,11 +63,11 @@ export class SelectTaskComponent implements OnInit, OnDestroy { this.projectMap[project.id] = project; }); }); - const tasks$: Observable = this.isLimitToProject - ? this.isIncludeDoneTasks + const tasks$: Observable = this.isLimitToProject() + ? this.isIncludeDoneTasks() ? this._workContextService.trackableTasksForActiveContext$ : this._workContextService.startableTasksForActiveContext$ - : this.isIncludeDoneTasks + : this.isIncludeDoneTasks() ? this._store.select(selectTrackableTasksActiveContextFirst) : this._store.select(selectStartableTasksActiveContextFirst); diff --git a/src/app/features/tasks/task-attachment/task-attachment-link/task-attachment-link.directive.ts b/src/app/features/tasks/task-attachment/task-attachment-link/task-attachment-link.directive.ts index 10e8702566..c3d30f84c1 100644 --- a/src/app/features/tasks/task-attachment/task-attachment-link/task-attachment-link.directive.ts +++ b/src/app/features/tasks/task-attachment/task-attachment-link/task-attachment-link.directive.ts @@ -1,4 +1,4 @@ -import { Directive, HostListener, Input } from '@angular/core'; +import { Directive, HostListener, input } from '@angular/core'; import { IS_ELECTRON } from '../../../../app.constants'; import { TaskAttachmentType } from '../task-attachment.model'; import { SnackService } from '../../../../core/snack/snack.service'; @@ -9,13 +9,14 @@ import { T } from '../../../../t.const'; standalone: false, }) export class TaskAttachmentLinkDirective { - @Input() type?: TaskAttachmentType; - @Input() href?: string; + readonly type = input(); + readonly href = input(); constructor(private _snackService: SnackService) {} @HostListener('click', ['$event']) onClick(ev: Event): void { - if (!this.href) { + const href = this.href(); + if (!href) { throw new Error('No href'); } @@ -25,20 +26,21 @@ export class TaskAttachmentLinkDirective { } if (IS_ELECTRON) { ev.preventDefault(); - if (!this.type || this.type === 'LINK') { - this._openExternalUrl(this.href); - } else if (this.type === 'FILE') { - window.ea.openPath(this.href); - } else if (this.type === 'COMMAND') { + const type = this.type(); + if (!type || type === 'LINK') { + this._openExternalUrl(href); + } else if (type === 'FILE') { + window.ea.openPath(href); + } else if (type === 'COMMAND') { this._snackService.open({ msg: T.GLOBAL_SNACK.RUNNING_X, - translateParams: { str: this.href }, + translateParams: { str: href }, ico: 'laptop_windows', }); - this._exec(this.href); + this._exec(href); } - } else if (this.type === 'LINK') { - this._openExternalUrl(this.href); + } else if (this.type() === 'LINK') { + this._openExternalUrl(href); } } diff --git a/src/app/features/tasks/task-attachment/task-attachment-list/task-attachment-list.component.html b/src/app/features/tasks/task-attachment/task-attachment-list/task-attachment-list.component.html index ebcc7b79b1..7853f9de5c 100644 --- a/src/app/features/tasks/task-attachment/task-attachment-list/task-attachment-list.component.html +++ b/src/app/features/tasks/task-attachment/task-attachment-list/task-attachment-list.component.html @@ -1,8 +1,8 @@