Skip to content

Commit 0c228e8

Browse files
authored
signals migration (#2905)
### Fixes # <!-- Mention the issues this PR addresses --> ### Checks - [ ] Ran `yarn test-build` - [ ] Updated relevant documentations - [ ] Updated matching config options in altair-static ### Changes proposed in this pull request: <!-- Describe the changes being introduced in this PR --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Refactor** - Migrated numerous UI components and services to use Angular reactive signals for inputs and state, replacing traditional @input bindings and constructor injection. This unifies data access patterns across dialogs, editors, viewers, headers, panels, and services. - Transitioned dependency injection from constructor parameters to inline Angular inject() calls throughout components, services, effects, and directives, simplifying initialization. - Updated templates to use function-call bindings for data and state, improving consistency and reactivity. - **Performance** - Enhanced reactive state management and effect-driven updates in key components like doc viewer, query editor, and collection dialogs for smoother UI responsiveness. - **Bug Fixes** - Improved null-safety in account-related UI displays and conditional rendering. - Added explicit button type attributes to prevent accidental form submissions. - Refined safer bindings and signal usage eliminated binding inconsistencies. - **Tests** - Updated unit and integration tests to adapt to reactive input patterns and new signal-based public APIs, ensuring robust coverage of refactored components and effects. - **Style** - Standardized HTML templates with self-closing tags for components and icons, cleaner bindings, and consistent attribute formatting. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent d820893 commit 0c228e8

File tree

178 files changed

+2738
-2464
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

178 files changed

+2738
-2464
lines changed

packages/altair-app/.eslintrc.js

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module.exports = {
1010
createDefaultProgram: true,
1111
},
1212
extends: [
13-
'plugin:@angular-eslint/recommended',
13+
'plugin:@angular-eslint/all',
1414
'plugin:@angular-eslint/template/process-inline-templates',
1515
'plugin:@typescript-eslint/recommended',
1616
// 'plugin:@ngrx/all',
@@ -38,6 +38,17 @@ module.exports = {
3838
type: 'attribute',
3939
},
4040
],
41+
'@angular-eslint/prefer-on-push-component-change-detection': 'warn',
42+
// '@angular-eslint/prefer-standalone-component': 'warn',
43+
'@angular-eslint/prefer-standalone': 'warn',
44+
'@angular-eslint/consistent-component-styles': 'off',
45+
'@angular-eslint/sort-keys-in-type-decorator': 'off',
46+
'@angular-eslint/use-injectable-provided-in': 'warn',
47+
'@angular-eslint/prefer-output-readonly': 'warn',
48+
'@angular-eslint/prefer-output-emitter-ref': 'warn',
49+
'@angular-eslint/sort-lifecycle-methods': 'warn',
50+
'@angular-eslint/use-component-selector': 'warn',
51+
'@angular-eslint/prefer-signals': 'warn',
4152
'prettier/prettier': 0,
4253
'require-await': 'off',
4354
'@typescript-eslint/require-await': 'off',
@@ -51,8 +62,23 @@ module.exports = {
5162
},
5263
{
5364
files: ['*.html'],
54-
extends: ['plugin:@angular-eslint/template/recommended'],
55-
rules: {},
65+
extends: ['plugin:@angular-eslint/template/all'],
66+
rules: {
67+
'@angular-eslint/template/conditional-complexity': 'off',
68+
'@angular-eslint/template/i18n': 'off', // Disable for now as we don't have i18n setup
69+
'@angular-eslint/template/attributes-order': 'off',
70+
'@angular-eslint/template/no-call-expression': 'off',
71+
'@angular-eslint/template/cyclomatic-complexity': 'warn',
72+
'@angular-eslint/template/no-nested-tags': 'warn',
73+
'@angular-eslint/template/no-inline-styles': 'off',
74+
'@angular-eslint/template/label-has-associated-control': 'off',
75+
'@angular-eslint/template/button-has-type': 'warn',
76+
77+
// TODO: Revisit these later
78+
'@angular-eslint/template/interactive-supports-focus': 'warn',
79+
'@angular-eslint/template/click-events-have-key-events': 'warn',
80+
'@angular-eslint/template/prefer-ngsrc': 'warn',
81+
},
5682
},
5783
{
5884
files: ['*.js'],

packages/altair-app/e2e/.eslintrc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
"type": "element",
2727
"style": "kebab-case"
2828
}
29-
]
29+
],
30+
"@angular-eslint/no-uncalled-signals": ["error"]
3031
}
3132
},
3233
{

packages/altair-app/package.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,11 @@
107107
},
108108
"devDependencies": {
109109
"@altairgraphql/iframe-sandbox": "workspace:*",
110-
"@angular-eslint/builder": "17.1.1",
111-
"@angular-eslint/eslint-plugin": "17.1.1",
112-
"@angular-eslint/eslint-plugin-template": "17.1.1",
113-
"@angular-eslint/schematics": "17.1.1",
114-
"@angular-eslint/template-parser": "17.1.1",
110+
"@angular-eslint/builder": "20.3.0",
111+
"@angular-eslint/eslint-plugin": "20.3.0",
112+
"@angular-eslint/eslint-plugin-template": "20.3.0",
113+
"@angular-eslint/schematics": "20.3.0",
114+
"@angular-eslint/template-parser": "20.3.0",
115115
"@angular/build": "^20.3.4",
116116
"@angular/compiler": "20.3.3",
117117
"@angular/compiler-cli": "20.3.3",
@@ -141,8 +141,8 @@
141141
"@types/to-snake-case": "^1.0.0",
142142
"@types/uuid": "^9.0.5",
143143
"@types/zen-observable": "^0.8.1",
144-
"@typescript-eslint/eslint-plugin": "^7.4.0",
145-
"@typescript-eslint/parser": "^7.4.0",
144+
"@typescript-eslint/eslint-plugin": "^8.46.0",
145+
"@typescript-eslint/parser": "^8.46.0",
146146
"babel-plugin-transform-async-to-generator": "6.24.1",
147147
"babel-preset-env": "1.7.0",
148148
"babel-preset-react": "6.24.1",
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<app-altair></app-altair>
1+
<app-altair />

packages/altair-app/src/app/modules/altair/altair.module.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,11 @@ const providers = [
179179
providers,
180180
})
181181
export class AltairModule {
182-
constructor(
183-
applicationInitStatus: ApplicationInitStatus,
184-
store: Store<RootState>,
185-
reducerBootstrapper: ReducerBootstrapper
186-
) {
182+
constructor() {
183+
const applicationInitStatus = inject(ApplicationInitStatus);
184+
const store = inject<Store<RootState>>(Store);
185+
const reducerBootstrapper = inject(ReducerBootstrapper);
186+
187187
applicationInitStatus.donePromise.then(() =>
188188
store.dispatch(
189189
new AppInitAction({ initialState: reducerBootstrapper.initialState })

packages/altair-app/src/app/modules/altair/components/account-dialog/__snapshots__/account-dialog.component.spec.ts.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,13 @@ exports[`AccountDialogComponent should create 1`] = `
7878
>
7979
<button
8080
class="btn btn--bordered"
81+
type="button"
8182
>
8283
SIGNIN_WITH_GOOGLE
8384
</button>
8485
<button
8586
class="btn btn--bordered"
87+
type="button"
8688
>
8789
<app-icon
8890
name="github"

packages/altair-app/src/app/modules/altair/components/account-dialog/account-dialog.component.html

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
<app-dialog
2-
[showDialog]="showDialog"
2+
[showDialog]="showDialog()"
33
[heading]="'ACCOUNT_TITLE' | translate"
44
[subheading]="'ACCOUNT_SUB_TEXT' | translate"
55
[showFooter]="false"
66
(toggleDialog)="toggleDialogChange.emit($event)"
77
>
88
<div class="account-signin-wrapper">
9-
@if (!account?.loggedIn) {
9+
@if (!account()?.loggedIn) {
1010
<div class="account-dialog__not-logged-in">
1111
<div class="account-dialog__not-logged-in__inner">
12-
<nz-avatar
13-
nzText="?"
14-
nzSrc="assets/img/altair_logo.svg"
15-
nzSize="large"
16-
></nz-avatar>
12+
<nz-avatar nzText="?" nzSrc="assets/img/altair_logo.svg" nzSize="large" />
1713

1814
<h2>Login to get started</h2>
1915
<p>
@@ -24,40 +20,49 @@ <h2>Login to get started</h2>
2420
/></a>
2521
</p>
2622
<div class="account-dialog__signin-actions">
27-
<button class="btn btn--bordered" (click)="submitLogin('GOOGLE')">
23+
<button
24+
type="button"
25+
class="btn btn--bordered"
26+
(click)="submitLogin('GOOGLE')"
27+
>
2828
<!-- <app-icon name="google"></app-icon> -->
2929
{{ 'SIGNIN_WITH_GOOGLE' | translate }}
3030
</button>
31-
<button class="btn btn--bordered" (click)="submitLogin('GITHUB')">
32-
<app-icon name="github"></app-icon>
31+
<button
32+
type="button"
33+
class="btn btn--bordered"
34+
(click)="submitLogin('GITHUB')"
35+
>
36+
<app-icon name="github" />
3337
{{ 'SIGNIN_WITH_GITHUB' | translate }}
3438
</button>
3539
</div>
3640
</div>
3741
</div>
3842
}
3943

40-
@if (account?.loggedIn) {
44+
@if (account()?.loggedIn) {
4145
<div class="app-dialog-section">
4246
<div class="account-dialog__welcome">
4347
<nz-avatar
44-
[nzText]="account?.firstName?.at(0)"
45-
[nzSrc]="account?.picture"
46-
></nz-avatar>
47-
{{ 'ACCOUNT_HELLO' | translate }}, {{ account?.firstName }}
48+
[nzText]="account()?.firstName?.at(0)"
49+
[nzSrc]="account()?.picture"
50+
/>
51+
{{ 'ACCOUNT_HELLO' | translate }}, {{ account()?.firstName }}
4852
</div>
4953
</div>
5054
<p>
5155
<a class="link" target="_blank" (click)="openBillingPage($event)">
5256
Billing
53-
<app-icon name="external-link"></app-icon>
57+
<app-icon name="external-link" />
5458
</a>
55-
@if (account?.plan?.canUpgradePro) {
59+
@if (account()?.plan?.canUpgradePro) {
5660
<button
61+
type="button"
5762
class="btn btn--primary btn--light btn--small"
5863
(click)="openUpgradeProUrl($event)"
5964
>
60-
<app-icon name="sparkles"></app-icon> Upgrade plan
65+
<app-icon name="sparkles" /> Upgrade plan
6166
</button>
6267
}
6368
</p>
@@ -68,34 +73,35 @@ <h2>Login to get started</h2>
6873
name="info"
6974
nz-tooltip
7075
[nzTooltipTitle]="'ACCOUNT_PLAN_STATS_DESCRIPTION' | translate"
71-
></app-icon>
76+
/>
7277
</div>
73-
<div>Plan: {{ account?.plan?.id }}</div>
78+
<div>Plan: {{ account()?.plan?.id }}</div>
7479
<div>
75-
Queries: {{ account?.stats?.queriesCount ?? 0 }} /
76-
{{ account?.plan?.maxQueriesCount ?? 0 }}
80+
Queries: {{ account()?.stats?.queriesCount ?? 0 }} /
81+
{{ account()?.plan?.maxQueriesCount ?? 0 }}
7782
</div>
7883
<div>
79-
Teams: {{ account?.stats?.teamsCount ?? 0 }} /
80-
{{ account?.plan?.maxTeamsCount ?? 0 }}
84+
Teams: {{ account()?.stats?.teamsCount ?? 0 }} /
85+
{{ account()?.plan?.maxTeamsCount ?? 0 }}
8186
</div>
82-
<div>Fixed Credits: {{ account?.availableCredits?.fixed ?? 0 }}</div>
87+
<div>Fixed Credits: {{ account()?.availableCredits?.fixed ?? 0 }}</div>
8388
<div>
8489
Monthly Credits (Pro users only):
85-
{{ account?.availableCredits?.monthly ?? 0 }}
90+
{{ account()?.availableCredits?.monthly ?? 0 }}
8691
</div>
8792
<button
93+
type="button"
8894
class="btn btn--primary btn--light btn--small"
8995
(click)="buyCredits($event)"
90-
[disabled]="account?.plan?.canUpgradePro"
96+
[disabled]="account()?.plan?.canUpgradePro"
9197
>
92-
<app-icon name="coins"></app-icon> Buy Credits
93-
@if (account?.plan?.canUpgradePro) {
98+
<app-icon name="coins" /> Buy Credits
99+
@if (account()?.plan?.canUpgradePro) {
94100
(Pro users only)
95101
}
96102
</button>
97103
</div>
98-
<button class="btn" (click)="logoutChange.emit()">
104+
<button type="button" class="btn" (click)="logoutChange.emit()">
99105
{{ 'LOGOUT_TEXT' | translate }}
100106
</button>
101107
}

packages/altair-app/src/app/modules/altair/components/account-dialog/account-dialog.component.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@ import {
22
ChangeDetectionStrategy,
33
Component,
44
EventEmitter,
5-
Input,
6-
OnInit,
75
Output,
6+
input,
87
} from '@angular/core';
9-
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
108
import { AccountState } from 'altair-graphql-core/build/types/state/account.interfaces';
11-
import { environment } from 'environments/environment';
129
import { apiClient } from '../../services/api/api.service';
1310
import { externalLink } from '../../utils';
1411
import { IdentityProvider } from '@altairgraphql/db';
@@ -21,8 +18,8 @@ import { IdentityProvider } from '@altairgraphql/db';
2118
standalone: false,
2219
})
2320
export class AccountDialogComponent {
24-
@Input() showDialog = true;
25-
@Input() account: AccountState | undefined;
21+
readonly showDialog = input(true);
22+
readonly account = input<AccountState>();
2623
@Output() toggleDialogChange = new EventEmitter<boolean>();
2724
@Output() handleLoginChange = new EventEmitter<IdentityProvider>();
2825
@Output() logoutChange = new EventEmitter();

packages/altair-app/src/app/modules/altair/components/action-bar/__snapshots__/action-bar.component.spec.ts.snap

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,31 @@ exports[`ActionBarComponent should render correctly 1`] = `
77
>
88
<button
99
class="app-button prettify-button"
10+
type="button"
1011
>
1112
1213
</button>
1314
<button
1415
class="app-button clear-editor-button"
16+
type="button"
1517
>
1618
1719
</button>
1820
<button
1921
class="app-button set-headers-button"
22+
type="button"
2023
>
2124
2225
</button>
2326
<button
2427
class="app-button set-variables-button"
28+
type="button"
2529
>
2630
2731
</button>
2832
<button
2933
class="app-button set-subscription-url-button"
34+
type="button"
3035
>
3136
3237
</button>
@@ -35,11 +40,13 @@ exports[`ActionBarComponent should render correctly 1`] = `
3540
>
3641
<button
3742
class="app-button reload-docs-button"
43+
type="button"
3844
>
3945
4046
</button>
4147
<button
4248
class="app-button show-docs-button"
49+
type="button"
4350
>
4451
4552
</button>

packages/altair-app/src/app/modules/altair/components/action-bar/action-bar.component.html

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,52 @@
11
<div class="action-bar">
22
<button
3+
type="button"
34
class="app-button prettify-button"
45
(click)="this.prettifyCodeChange.emit()"
56
>
67
{{ 'PRETTIFY_BUTTON' | translate }}
78
</button>
89
<button
10+
type="button"
911
class="app-button clear-editor-button"
1012
(click)="this.clearEditorChange.emit()"
1113
>
1214
{{ 'CLEAR_BUTTON' | translate }}
1315
</button>
1416
<button
17+
type="button"
1518
class="app-button set-headers-button"
1619
(click)="this.toggleHeaderDialog.emit()"
1720
>
1821
{{ 'SET_HEADERS_BUTTON' | translate }}
1922
</button>
2023
<button
24+
type="button"
2125
class="app-button set-variables-button"
2226
(click)="this.toggleVariableDialog.emit()"
2327
>
2428
{{ 'SET_VARIABLES_BUTTON' | translate }}
2529
</button>
2630
<button
31+
type="button"
2732
class="app-button set-subscription-url-button"
2833
(click)="this.toggleSubscriptionUrlDialog.emit()"
2934
>
3035
{{ 'SUBSCRIPTION_URL_TEXT' | translate }}
3136
</button>
3237
<div class="actions-right right">
33-
<button class="app-button reload-docs-button" (click)="reloadDocsChange.emit()">
38+
<button
39+
type="button"
40+
class="app-button reload-docs-button"
41+
(click)="reloadDocsChange.emit()"
42+
>
3443
{{ 'RELOAD_DOCS_BUTTON' | translate }}
3544
</button>
3645
<button
46+
type="button"
3747
class="app-button show-docs-button"
3848
(click)="toggleDocsChange.emit()"
39-
[ngClass]="{ 'active-grey': showDocs }"
49+
[ngClass]="{ 'active-grey': showDocs() }"
4050
>
4151
{{ 'SHOW_DOCS_BUTTON' | translate }}
4252
</button>

0 commit comments

Comments
 (0)