Browse Source

Task/enable strictTemplates for the client app (#8108)

Enable strictTemplates
main
Kenrick Tandrian 5 hours ago
committed by GitHub
parent
commit
9439b9ef1f
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts
  2. 1
      apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html
  3. 2
      apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts
  4. 1
      apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html
  5. 24
      apps/client/src/app/components/markets/markets.component.ts
  6. 2
      apps/client/src/app/components/markets/markets.html
  7. 2
      apps/client/src/app/components/rule/rule-settings-dialog/interfaces/interfaces.ts
  8. 26
      apps/client/src/app/components/rule/rule.component.ts
  9. 11
      apps/client/src/app/components/rules/rules.component.ts
  10. 2
      apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html
  11. 2
      apps/client/src/app/pages/portfolio/fire/fire-page.html
  12. 32
      apps/client/src/app/pages/pricing/pricing-page.html
  13. 20
      apps/client/tsconfig.json

2
apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts

@ -35,7 +35,6 @@ import {
inject, inject,
OnInit OnInit
} from '@angular/core'; } from '@angular/core';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
@ -82,7 +81,6 @@ import {
MatTabsModule, MatTabsModule,
NgxSkeletonLoaderModule NgxSkeletonLoaderModule
], ],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
selector: 'gf-account-detail-dialog', selector: 'gf-account-detail-dialog',
styleUrls: ['./account-detail-dialog.component.scss'], styleUrls: ['./account-detail-dialog.component.scss'],
templateUrl: 'account-detail-dialog.html' templateUrl: 'account-detail-dialog.html'

1
apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html

@ -153,7 +153,6 @@
[hasPermissionToCreateActivity]="data.hasPermissionToCreateActivity" [hasPermissionToCreateActivity]="data.hasPermissionToCreateActivity"
[hasPermissionToDeleteActivity]="false" [hasPermissionToDeleteActivity]="false"
[hasPermissionToExportActivities]="!showValuesInPercentage()" [hasPermissionToExportActivities]="!showValuesInPercentage()"
[hasPermissionToFilter]="false"
[hasPermissionToOpenDetails]="false" [hasPermissionToOpenDetails]="false"
[hasPermissionToUpdateActivity]="data.hasPermissionToUpdateActivity" [hasPermissionToUpdateActivity]="data.hasPermissionToUpdateActivity"
[locale]="user?.settings?.locale" [locale]="user?.settings?.locale"

2
apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts

@ -41,7 +41,6 @@ import { GfTagsSelectorComponent } from '@ghostfolio/ui/tags-selector';
import { GfValueComponent } from '@ghostfolio/ui/value'; import { GfValueComponent } from '@ghostfolio/ui/value';
import { import {
CUSTOM_ELEMENTS_SCHEMA,
ChangeDetectionStrategy, ChangeDetectionStrategy,
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
@ -116,7 +115,6 @@ import {
ReactiveFormsModule, ReactiveFormsModule,
RouterModule RouterModule
], ],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
selector: 'gf-holding-detail-dialog', selector: 'gf-holding-detail-dialog',
styleUrls: ['./holding-detail-dialog.component.scss'], styleUrls: ['./holding-detail-dialog.component.scss'],
templateUrl: 'holding-detail-dialog.html' templateUrl: 'holding-detail-dialog.html'

1
apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.html

@ -383,7 +383,6 @@
[hasPermissionToExportActivities]=" [hasPermissionToExportActivities]="
!data.impersonationId && !user?.settings?.isRestrictedView !data.impersonationId && !user?.settings?.isRestrictedView
" "
[hasPermissionToFilter]="false"
[hasPermissionToOpenDetails]="false" [hasPermissionToOpenDetails]="false"
[hasPermissionToUpdateActivity]="data.hasPermissionToUpdateActivity" [hasPermissionToUpdateActivity]="data.hasPermissionToUpdateActivity"
[locale]="data.locale" [locale]="data.locale"

24
apps/client/src/app/components/markets/markets.component.ts

@ -3,8 +3,8 @@ import { DEFAULT_LOCALE } from '@ghostfolio/common/config';
import { resetHours } from '@ghostfolio/common/helper'; import { resetHours } from '@ghostfolio/common/helper';
import { import {
Benchmark, Benchmark,
HistoricalDataItem,
InfoItem, InfoItem,
LineChartItem,
MarketDataOfMarketsResponse, MarketDataOfMarketsResponse,
User User
} from '@ghostfolio/common/interfaces'; } from '@ghostfolio/common/interfaces';
@ -28,6 +28,7 @@ import {
signal signal
} from '@angular/core'; } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { isNumber } from 'lodash-es';
import { DeviceDetectorService } from 'ngx-device-detector'; import { DeviceDetectorService } from 'ngx-device-detector';
@Component({ @Component({
@ -66,7 +67,7 @@ export class GfMarketsComponent implements OnInit {
protected fearAndGreedIndexMode: FearAndGreedIndexMode = 'STOCKS'; protected fearAndGreedIndexMode: FearAndGreedIndexMode = 'STOCKS';
protected hasPermissionToAccessFearAndGreedIndex: boolean; protected hasPermissionToAccessFearAndGreedIndex: boolean;
protected hasPermissionToReadMarketDataOfMarkets: boolean; protected hasPermissionToReadMarketDataOfMarkets: boolean;
protected historicalDataItems: HistoricalDataItem[]; protected historicalDataItems: LineChartItem[];
protected isLoadingFearAndGreedIndex = true; protected isLoadingFearAndGreedIndex = true;
protected user: User; protected user: User;
@ -158,13 +159,20 @@ export class GfMarketsComponent implements OnInit {
this.fearAndGreedIndex = this.fearAndGreedIndex =
this.fearAndGreedIndexData[this.fearAndGreedIndexMode]?.marketPrice; this.fearAndGreedIndexData[this.fearAndGreedIndexMode]?.marketPrice;
this.historicalDataItems = [ const historicalDataItems = (
...(this.fearAndGreedIndexData[this.fearAndGreedIndexMode] this.fearAndGreedIndexData[this.fearAndGreedIndexMode]?.historicalData ??
?.historicalData ?? []), []
{ ).filter((item): item is LineChartItem => {
return isNumber(item.value);
});
if (isNumber(this.fearAndGreedIndex)) {
historicalDataItems.push({
date: resetHours(new Date()).toISOString(), date: resetHours(new Date()).toISOString(),
value: this.fearAndGreedIndex value: this.fearAndGreedIndex
} });
]; }
this.historicalDataItems = historicalDataItems;
} }
} }

2
apps/client/src/app/components/markets/markets.html

@ -29,7 +29,7 @@
[colorScheme]="user?.settings?.colorScheme" [colorScheme]="user?.settings?.colorScheme"
[historicalDataItems]="historicalDataItems" [historicalDataItems]="historicalDataItems"
[isAnimated]="true" [isAnimated]="true"
[locale]="user?.settings?.locale || undefined" [locale]="user?.settings?.locale ?? DEFAULT_LOCALE"
[showXAxis]="true" [showXAxis]="true"
[showYAxis]="true" [showYAxis]="true"
[yMax]="100" [yMax]="100"

2
apps/client/src/app/components/rule/rule-settings-dialog/interfaces/interfaces.ts

@ -5,7 +5,7 @@ import {
export interface RuleSettingsDialogParams { export interface RuleSettingsDialogParams {
categoryName: string; categoryName: string;
locale: string; locale?: string;
rule: PortfolioReportRule; rule: PortfolioReportRule;
settings: XRayRulesSettings['AccountClusterRiskCurrentInvestment']; settings: XRayRulesSettings['AccountClusterRiskCurrentInvestment'];
} }

26
apps/client/src/app/components/rule/rule.component.ts

@ -8,11 +8,10 @@ import {
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
computed,
DestroyRef, DestroyRef,
EventEmitter,
Input, Input,
OnInit, output
Output
} from '@angular/core'; } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
@ -41,17 +40,20 @@ import { GfRuleSettingsDialogComponent } from './rule-settings-dialog/rule-setti
styleUrls: ['./rule.component.scss'], styleUrls: ['./rule.component.scss'],
templateUrl: './rule.component.html' templateUrl: './rule.component.html'
}) })
export class GfRuleComponent implements OnInit { export class GfRuleComponent {
@Input() categoryName: string; @Input() categoryName: string;
@Input() hasPermissionToUpdateUserSettings: boolean; @Input() hasPermissionToUpdateUserSettings: boolean;
@Input() isLoading: boolean; @Input() isLoading: boolean;
@Input() locale: string; @Input() locale?: string;
@Input() rule: PortfolioReportRule; @Input() rule: PortfolioReportRule;
@Input() settings: XRayRulesSettings['AccountClusterRiskCurrentInvestment']; @Input() settings: XRayRulesSettings['AccountClusterRiskCurrentInvestment'];
@Output() ruleUpdated = new EventEmitter<UpdateUserSettingDto>(); public readonly ruleUpdated = output<UpdateUserSettingDto>();
private readonly deviceType = computed(() => {
return this.deviceDetectorService.deviceInfo().deviceType;
});
private deviceType: string;
public constructor( public constructor(
private destroyRef: DestroyRef, private destroyRef: DestroyRef,
private deviceDetectorService: DeviceDetectorService, private deviceDetectorService: DeviceDetectorService,
@ -67,11 +69,7 @@ export class GfRuleComponent implements OnInit {
}); });
} }
public ngOnInit() { protected onCustomizeRule(rule: PortfolioReportRule) {
this.deviceType = this.deviceDetectorService.getDeviceInfo().deviceType;
}
public onCustomizeRule(rule: PortfolioReportRule) {
const dialogRef = this.dialog.open< const dialogRef = this.dialog.open<
GfRuleSettingsDialogComponent, GfRuleSettingsDialogComponent,
RuleSettingsDialogParams RuleSettingsDialogParams
@ -82,7 +80,7 @@ export class GfRuleComponent implements OnInit {
locale: this.locale, locale: this.locale,
settings: this.settings settings: this.settings
}, },
width: this.deviceType === 'mobile' ? '100vw' : '50rem' width: this.deviceType() === 'mobile' ? '100vw' : '50rem'
}); });
dialogRef dialogRef
@ -99,7 +97,7 @@ export class GfRuleComponent implements OnInit {
}); });
} }
public onUpdateRule(rule: PortfolioReportRule) { protected onUpdateRule(rule: PortfolioReportRule) {
const settings: UpdateUserSettingDto = { const settings: UpdateUserSettingDto = {
xRayRules: { xRayRules: {
[rule.key]: { isActive: !rule.isActive } [rule.key]: { isActive: !rule.isActive }

11
apps/client/src/app/components/rules/rules.component.ts

@ -8,9 +8,8 @@ import {
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
EventEmitter,
Input, Input,
Output output
} from '@angular/core'; } from '@angular/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
@ -26,13 +25,13 @@ export class GfRulesComponent {
@Input() categoryName: string; @Input() categoryName: string;
@Input() hasPermissionToUpdateUserSettings: boolean; @Input() hasPermissionToUpdateUserSettings: boolean;
@Input() isLoading: boolean; @Input() isLoading: boolean;
@Input() locale: string; @Input() locale?: string;
@Input() rules: PortfolioReportRule[]; @Input() rules: PortfolioReportRule[];
@Input() settings: XRayRulesSettings; @Input() settings?: XRayRulesSettings;
@Output() rulesUpdated = new EventEmitter<UpdateUserSettingDto>(); public readonly rulesUpdated = output<UpdateUserSettingDto>();
public onRuleUpdated(event: UpdateUserSettingDto) { protected onRuleUpdated(event: UpdateUserSettingDto) {
this.rulesUpdated.emit(event); this.rulesUpdated.emit(event);
} }
} }

2
apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.html

@ -128,14 +128,12 @@
[hasPermissionToCreateActivity]="false" [hasPermissionToCreateActivity]="false"
[hasPermissionToDeleteActivity]="false" [hasPermissionToDeleteActivity]="false"
[hasPermissionToExportActivities]="false" [hasPermissionToExportActivities]="false"
[hasPermissionToFilter]="false"
[hasPermissionToOpenDetails]="false" [hasPermissionToOpenDetails]="false"
[locale]="data?.user?.settings?.locale" [locale]="data?.user?.settings?.locale"
[pageIndex]="pageIndex" [pageIndex]="pageIndex"
[pageSize]="pageSize" [pageSize]="pageSize"
[showActions]="false" [showActions]="false"
[showCheckbox]="true" [showCheckbox]="true"
[showSymbolColumn]="false"
[sortColumn]="sortColumn" [sortColumn]="sortColumn"
[sortDirection]="sortDirection" [sortDirection]="sortDirection"
[sortDisabled]="true" [sortDisabled]="true"

2
apps/client/src/app/pages/portfolio/fire/fire-page.html

@ -178,7 +178,7 @@
[isPercent]="true" [isPercent]="true"
[locale]="user?.settings?.locale" [locale]="user?.settings?.locale"
[precision]="2" [precision]="2"
[value]="user?.settings?.annualInterestRate / 100" [value]="(user?.settings?.annualInterestRate ?? 0) / 100"
/></span> /></span>
annual interest rate.</ng-container annual interest rate.</ng-container
> >

32
apps/client/src/app/pages/pricing/pricing-page.html

@ -258,21 +258,23 @@
</ul> </ul>
</div> </div>
<p i18n>Fully managed Ghostfolio cloud offering.</p> <p i18n>Fully managed Ghostfolio cloud offering.</p>
<p class="h5 text-right" [hidden]="!price"> @if (price) {
<span class="font-weight-normal"> <p class="h5 text-right">
@if (coupon) { <span class="font-weight-normal">
<del class="text-muted" @if (coupon) {
>{{ baseCurrency }}&nbsp;{{ price }}</del <del class="text-muted"
>&nbsp;{{ baseCurrency }}&nbsp;<strong>{{ >{{ baseCurrency }}&nbsp;{{ price }}</del
price - coupon >&nbsp;{{ baseCurrency }}&nbsp;<strong>{{
}}</strong> price - coupon
} @else { }}</strong>
{{ baseCurrency }}&nbsp;<strong>{{ price }}</strong> } @else {
} {{ baseCurrency }}&nbsp;<strong>{{ price }}</strong>
<span>&nbsp;</span> }
<span i18n>per year</span></span <span>&nbsp;</span>
> <span i18n>per year</span></span
</p> >
</p>
}
@if ( @if (
hasPermissionToUpdateUserSettings && hasPermissionToUpdateUserSettings &&
user?.subscription?.type === 'Basic' user?.subscription?.type === 'Basic'

20
apps/client/tsconfig.json

@ -14,20 +14,16 @@
} }
], ],
"angularCompilerOptions": { "angularCompilerOptions": {
"extendedDiagnostics": {
"checks": {
// TODO: Remove once the fields are typed as optional
"nullishCoalescingNotNullable": "suppress",
"optionalChainNotNullable": "suppress"
}
},
"strictInjectionParameters": true, "strictInjectionParameters": true,
// TODO: Remove these subsets once strictTemplates is enabled
"strictAttributeTypes": true,
"strictContextGenerics": true,
"strictDomEventTypes": true,
"strictDomLocalRefTypes": true,
"strictInputAccessModifiers": true, "strictInputAccessModifiers": true,
"strictInputTypes": true, "strictTemplates": true
"strictLiteralTypes": true,
"strictNullInputTypes": true,
"strictOutputEventTypes": true,
"strictSafeNavigationTypes": true,
// TODO: Enable stricter rules for this project
"strictTemplates": false
}, },
"compilerOptions": { "compilerOptions": {
"module": "preserve", "module": "preserve",

Loading…
Cancel
Save