Skip to content

Commit b1de66e

Browse files
Merge pull request #1689 from karinakharchenko/dashboard-configuring-banner
Add configuring status banner and auto-configure redesign
2 parents 04731c8 + f110a32 commit b1de66e

9 files changed

Lines changed: 419 additions & 80 deletions

File tree

Lines changed: 203 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,223 @@
1-
.auto-configure {
1+
/* ── Page ── */
2+
3+
.page {
24
display: flex;
3-
flex-direction: column;
45
justify-content: center;
56
align-items: center;
6-
gap: 24px;
77
height: 100vh;
8+
background: var(--color-primaryPalette-50);
89
}
910

10-
.auto-configure__title {
11-
color: var(--mat-sidenav-content-text-color);
12-
margin: 0;
13-
font-weight: 500;
11+
@media (prefers-color-scheme: dark) {
12+
.page {
13+
background: var(--surface-dark-color);
14+
}
1415
}
1516

16-
.auto-configure__text {
17-
color: var(--mat-sidenav-content-text-color);
18-
opacity: 0.7;
17+
/* ── Card ── */
18+
19+
.card {
20+
width: 100%;
21+
max-width: 480px;
22+
border-radius: 16px;
23+
background: var(--color-whitePalette-500);
24+
box-shadow:
25+
0 1px 3px rgba(0, 0, 0, 0.08),
26+
0 4px 24px rgba(0, 0, 0, 0.06);
27+
overflow: hidden;
28+
}
29+
30+
@media (prefers-color-scheme: dark) {
31+
.card {
32+
background: var(--color-primaryPalette-900);
33+
box-shadow:
34+
0 1px 3px rgba(0, 0, 0, 0.3),
35+
0 4px 24px rgba(0, 0, 0, 0.2);
36+
}
37+
}
38+
39+
@media (width <= 600px) {
40+
.card {
41+
margin: 0 16px;
42+
}
43+
}
44+
45+
.card__body {
46+
display: flex;
47+
flex-direction: column;
48+
align-items: center;
49+
padding: 48px 32px 36px;
50+
gap: 16px;
51+
}
52+
53+
.card__title {
1954
margin: 0;
20-
max-width: 400px;
55+
font-size: 20px;
56+
font-weight: 700;
57+
color: var(--color-primaryPalette-900);
2158
text-align: center;
2259
}
2360

24-
.auto-configure__open-btn {
25-
margin-top: 8px;
26-
font-size: 16px;
27-
padding: 0 32px;
61+
@media (prefers-color-scheme: dark) {
62+
.card__title {
63+
color: var(--color-primaryPalette-50);
64+
}
2865
}
2966

30-
.auto-configure__hint {
31-
color: var(--mat-sidenav-content-text-color);
32-
opacity: 0.5;
67+
.card__subtitle {
3368
margin: 0;
34-
font-size: 13px;
69+
font-size: 14px;
70+
color: var(--color-primaryPalette-400);
71+
text-align: center;
72+
line-height: 1.5;
73+
max-width: 360px;
3574
}
3675

37-
.auto-configure__notice {
38-
color: var(--mat-sidenav-content-text-color);
39-
opacity: 0.7;
76+
@media (prefers-color-scheme: dark) {
77+
.card__subtitle {
78+
color: var(--color-primaryPalette-300);
79+
}
80+
}
81+
82+
.card__notice {
4083
margin: 0;
84+
font-size: 14px;
85+
color: var(--color-primaryPalette-400);
4186
text-align: center;
42-
max-width: 400px;
87+
max-width: 360px;
88+
line-height: 1.5;
89+
}
90+
91+
@media (prefers-color-scheme: dark) {
92+
.card__notice {
93+
color: var(--color-primaryPalette-300);
94+
}
95+
}
96+
97+
/* ── Footer ── */
98+
99+
.card__footer {
100+
display: flex;
101+
align-items: center;
102+
justify-content: space-between;
103+
gap: 16px;
104+
padding: 16px 24px;
105+
border-top: 1px solid var(--color-primaryPalette-200);
106+
}
107+
108+
@media (prefers-color-scheme: dark) {
109+
.card__footer {
110+
border-top-color: var(--color-primaryPalette-800);
111+
}
112+
}
113+
114+
@media (width <= 600px) {
115+
.card__footer {
116+
flex-direction: column;
117+
text-align: center;
118+
}
119+
}
120+
121+
.card__footer-text {
122+
margin: 0;
123+
font-size: 13px;
124+
color: var(--color-primaryPalette-300);
125+
line-height: 1.4;
126+
flex: 1;
127+
}
128+
129+
@media (prefers-color-scheme: dark) {
130+
.card__footer-text {
131+
color: var(--color-primaryPalette-400);
132+
}
133+
}
134+
135+
/* ── CTA button ── */
136+
137+
.card__cta {
138+
flex-shrink: 0;
139+
background: var(--color-accentedPalette-500) !important;
140+
color: var(--color-accentedPalette-500-contrast) !important;
141+
border-radius: 8px;
142+
font-weight: 600;
143+
font-size: 14px;
144+
padding: 0 20px;
145+
height: 40px;
146+
text-decoration: none;
147+
}
148+
149+
.card__cta:hover {
150+
background: var(--color-accentedPalette-700) !important;
151+
}
152+
153+
.card__cta-arrow {
154+
margin-left: 6px;
155+
}
156+
157+
/* ── Concentric spinning rings ── */
158+
159+
.spinner {
160+
position: relative;
161+
width: 72px;
162+
height: 72px;
163+
margin-bottom: 8px;
164+
}
165+
166+
.spinner__ring {
167+
position: absolute;
168+
border-radius: 50%;
169+
border: 3px solid transparent;
170+
}
171+
172+
.spinner__ring--outer {
173+
inset: 0;
174+
border-top-color: var(--color-accentedPalette-500);
175+
border-right-color: var(--color-accentedPalette-500);
176+
animation: spin-outer 1.8s linear infinite;
177+
}
178+
179+
.spinner__ring--inner {
180+
inset: 10px;
181+
border-bottom-color: var(--color-accentedPalette-500);
182+
border-left-color: var(--color-accentedPalette-500);
183+
animation: spin-inner 1.2s linear infinite;
184+
}
185+
186+
@keyframes spin-outer {
187+
to { transform: rotate(360deg); }
188+
}
189+
190+
@keyframes spin-inner {
191+
to { transform: rotate(-360deg); }
192+
}
193+
194+
/* ── Indeterminate progress bar ── */
195+
196+
.progress-bar {
197+
width: 100%;
198+
max-width: 320px;
199+
height: 4px;
200+
border-radius: 2px;
201+
background: var(--color-primaryPalette-200);
202+
overflow: hidden;
203+
margin-top: 4px;
204+
}
205+
206+
@media (prefers-color-scheme: dark) {
207+
.progress-bar {
208+
background: var(--color-primaryPalette-800);
209+
}
210+
}
211+
212+
.progress-bar__fill {
213+
width: 40%;
214+
height: 100%;
215+
border-radius: 2px;
216+
background: var(--color-accentedPalette-500);
217+
animation: indeterminate 1.5s ease-in-out infinite;
218+
}
219+
220+
@keyframes indeterminate {
221+
0% { transform: translateX(-100%); }
222+
100% { transform: translateX(350%); }
43223
}
Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
1-
@if (loading()) {
2-
<div class="auto-configure">
3-
<mat-spinner diameter="48"></mat-spinner>
4-
<h2 class="auto-configure__title">Setting up your dashboard</h2>
5-
<p class="auto-configure__text">We're analyzing your database structure and applying the best configuration. This may take a while.</p>
6-
<a mat-flat-button class="auto-configure__open-btn" [routerLink]="'/dashboard/' + connectionId()">Open tables</a>
7-
<p class="auto-configure__hint">Setup will continue in the background</p>
1+
<div class="page">
2+
<div class="card">
3+
<div class="card__body">
4+
<div class="spinner">
5+
<div class="spinner__ring spinner__ring--outer"></div>
6+
<div class="spinner__ring spinner__ring--inner"></div>
7+
</div>
8+
<h2 class="card__title">Configuring your database</h2>
9+
<p class="card__subtitle">We're analyzing your structure and applying the best settings. This is running in the background.</p>
10+
<div class="progress-bar">
11+
<div class="progress-bar__fill"></div>
12+
</div>
13+
</div>
14+
<div class="card__footer">
15+
<p class="card__footer-text">You can start working — setup will continue in the background.</p>
16+
<a mat-flat-button class="card__cta" [routerLink]="'/dashboard/' + connectionId()">
17+
Open tables
18+
<span class="card__cta-arrow">&rarr;</span>
19+
</a>
20+
</div>
821
</div>
9-
} @else if (errorMessage()) {
10-
<div class="auto-configure">
11-
<p class="auto-configure__notice">{{ errorMessage() }}</p>
12-
<a mat-flat-button [routerLink]="'/dashboard/' + connectionId()">Continue to dashboard</a>
13-
</div>
14-
}
22+
</div>
Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,31 @@
11
import { Component, inject, OnInit, signal } from '@angular/core';
22
import { MatButtonModule } from '@angular/material/button';
3-
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
43
import { ActivatedRoute, Router, RouterModule } from '@angular/router';
54

6-
import { ApiService } from '../../services/api.service';
5+
import { ConfigurationStateService } from '../../services/configuration-state.service';
76

87
@Component({
98
selector: 'app-auto-configure',
109
templateUrl: './auto-configure.component.html',
1110
styleUrls: ['./auto-configure.component.css'],
12-
imports: [MatProgressSpinnerModule, MatButtonModule, RouterModule],
11+
imports: [MatButtonModule, RouterModule],
1312
})
1413
export class AutoConfigureComponent implements OnInit {
1514
private _route = inject(ActivatedRoute);
1615
private _router = inject(Router);
17-
private _api = inject(ApiService);
16+
private _configState = inject(ConfigurationStateService);
1817

1918
protected connectionId = signal<string | null>(null);
20-
protected loading = signal(true);
21-
protected errorMessage = signal<string | null>(null);
2219

23-
ngOnInit(): void {
20+
async ngOnInit(): Promise<void> {
2421
const connectionId = this._route.snapshot.paramMap.get('connection-id');
2522
if (!connectionId) {
2623
this._router.navigate(['/connections-list']);
2724
return;
2825
}
2926

3027
this.connectionId.set(connectionId);
31-
this._configure(connectionId);
32-
}
33-
34-
private async _configure(connectionId: string): Promise<void> {
35-
const result = await this._api.get<string>(`/ai/v2/setup/${connectionId}`, { responseType: 'text' });
36-
37-
if (result !== null) {
38-
this._router.navigate([`/dashboard/${connectionId}`]);
39-
} else {
40-
this.loading.set(false);
41-
this.errorMessage.set('Auto-configuration could not be completed. You can still configure your tables manually.');
42-
}
28+
await this._configState.startConfiguring(connectionId);
29+
this._router.navigate(['/dashboard', connectionId]);
4330
}
4431
}

0 commit comments

Comments
 (0)