Skip to content

Commit aa7638d

Browse files
authored
add scilog-token and copy-to-clipboard functionality in user-profile dialog (#460)
1 parent 21ec755 commit aa7638d

File tree

5 files changed

+107
-27
lines changed

5 files changed

+107
-27
lines changed

scilog/src/app/core/auth-services/auth.service.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,7 @@ export class AuthService {
4040
return Math.floor((Math.random() * 1000) + 1).toString();
4141
}
4242

43+
getScilogToken(): string | null {
44+
return localStorage.getItem('id_token');
45+
}
4346
}
Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
.profile {
2-
display: flex;
3-
justify-content: center;
4-
align-items: center;
5-
flex-direction: column;
6-
}
2+
display: flex;
3+
justify-content: center;
4+
align-items: center;
5+
flex-direction: column;
6+
}
77

8-
input:disabled {
9-
color: rgba(0, 0, 0, 1);
10-
}
8+
input:disabled {
9+
color: rgba(0, 0, 0, 1);
10+
}
11+
12+
button[matSuffix] {
13+
color: gray;
14+
}

scilog/src/app/logbook/core/settings/profile-settings/profile-settings.component.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@
2626
<input matInput placeholder="Title of the view" [formControl]="profileFormGroup.get('username')">
2727
</mat-form-field>
2828
</div>
29+
30+
<div>
31+
<mat-form-field required>
32+
<mat-label>SciLog token</mat-label>
33+
<input matInput [formControl]="profileFormGroup.get('token')">
34+
<button mat-icon-button matSuffix (click)="copyToClipboard()">
35+
<mat-icon>content_copy</mat-icon>
36+
</button>
37+
</mat-form-field>
38+
</div>
2939
</form>
3040

3141
</div>

scilog/src/app/logbook/core/settings/profile-settings/profile-settings.component.spec.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { ProfileSettingsComponent } from './profile-settings.component';
44
import { UserPreferencesService } from '@shared/user-preferences.service';
55
import { UntypedFormBuilder } from '@angular/forms';
66
import { AppConfigService } from 'src/app/app-config.service';
7+
import { MatSnackBar } from '@angular/material/snack-bar';
8+
import { AuthService } from '@shared/auth-services/auth.service';
79

810

911
class UserPreferencesMock {
@@ -13,6 +15,16 @@ class UserPreferencesMock {
1315
}
1416
}
1517

18+
class AuthServiceMock {
19+
getScilogToken() {
20+
return 'mock-token-123';
21+
}
22+
}
23+
24+
class MatSnackBarMock {
25+
open() {}
26+
}
27+
1628
const getConfig = () => ({});
1729

1830
describe('ProfileSettingsComponent', () => {
@@ -25,7 +37,9 @@ describe('ProfileSettingsComponent', () => {
2537
providers: [
2638
UntypedFormBuilder,
2739
{ provide: UserPreferencesService, useClass: UserPreferencesMock },
28-
{ provide: AppConfigService, useValue: { getConfig } }
40+
{ provide: AppConfigService, useValue: { getConfig } },
41+
{ provide: MatSnackBar, useClass: MatSnackBarMock },
42+
{ provide: AuthService, useClass: AuthServiceMock }
2943
]
3044
})
3145
.compileComponents();
@@ -40,4 +54,10 @@ describe('ProfileSettingsComponent', () => {
4054
it('should create', () => {
4155
expect(component).toBeTruthy();
4256
});
57+
58+
it('copies token to clipboard', () => {
59+
const clipboardSpy = spyOn(navigator.clipboard, 'writeText').and.resolveTo(void 0);
60+
component.copyToClipboard();
61+
expect(clipboardSpy).toHaveBeenCalledWith('mock-token-123');
62+
});
4363
});
Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,82 @@
11
import { Component, OnInit } from '@angular/core';
22
import { UserPreferencesService } from '@shared/user-preferences.service';
33
import { UntypedFormBuilder, UntypedFormGroup, UntypedFormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
4-
import { MatFormField, MatLabel } from '@angular/material/form-field';
5-
import { MatInput } from '@angular/material/input';
4+
import { MatFormFieldModule } from '@angular/material/form-field';
5+
import { MatInputModule } from '@angular/material/input';
6+
import { AuthService } from '@shared/auth-services/auth.service';
7+
import { MatIconModule } from "@angular/material/icon";
8+
import { MatButtonModule } from '@angular/material/button';
9+
import { MatSnackBar } from '@angular/material/snack-bar';
610

711
@Component({
8-
selector: 'app-profile-settings',
9-
templateUrl: './profile-settings.component.html',
10-
styleUrls: ['./profile-settings.component.css'],
11-
imports: [FormsModule, ReactiveFormsModule, MatFormField, MatLabel, MatInput]
12+
selector: 'app-profile-settings',
13+
templateUrl: './profile-settings.component.html',
14+
styleUrls: ['./profile-settings.component.css'],
15+
imports: [
16+
FormsModule,
17+
ReactiveFormsModule,
18+
MatFormFieldModule,
19+
MatInputModule,
20+
MatButtonModule,
21+
MatIconModule,
22+
],
1223
})
1324
export class ProfileSettingsComponent implements OnInit {
14-
1525
formBuilder: UntypedFormBuilder;
1626
profileFormGroup: UntypedFormGroup;
1727

18-
1928
constructor(
2029
private userPreferences: UserPreferencesService,
21-
fb: UntypedFormBuilder,
22-
) {
30+
private authService: AuthService,
31+
private snackBar: MatSnackBar,
32+
fb: UntypedFormBuilder
33+
) {
2334
this.formBuilder = fb;
24-
2535
}
2636

2737
ngOnInit(): void {
2838
this.profileFormGroup = this.formBuilder.group({
29-
name: new UntypedFormControl({ value: this.userPreferences.userInfo.firstName, disabled: true }),
30-
lastname: new UntypedFormControl({ value: this.userPreferences.userInfo.lastName, disabled: true }),
31-
email: new UntypedFormControl({ value: this.userPreferences.userInfo.email, disabled: true }),
32-
username: new UntypedFormControl({ value: this.userPreferences.userInfo.email, disabled: true }),
33-
39+
name: new UntypedFormControl({
40+
value: this.userPreferences.userInfo.firstName,
41+
disabled: true,
42+
}),
43+
lastname: new UntypedFormControl({
44+
value: this.userPreferences.userInfo.lastName,
45+
disabled: true,
46+
}),
47+
email: new UntypedFormControl({
48+
value: this.userPreferences.userInfo.email,
49+
disabled: true,
50+
}),
51+
username: new UntypedFormControl({
52+
value: this.userPreferences.userInfo.email,
53+
disabled: true,
54+
}),
55+
token: new UntypedFormControl({
56+
value: this.authService.getScilogToken(),
57+
disabled: true,
58+
}),
3459
});
35-
console.log(this.userPreferences.userInfo)
36-
3760
}
3861

62+
copyToClipboard() {
63+
const token = this.profileFormGroup.get('token')?.value;
64+
if (token) {
65+
navigator.clipboard
66+
.writeText(token)
67+
.then(() => {
68+
this.snackBar.open('Token copied to clipboard', 'Dismiss', {
69+
duration: 3000,
70+
verticalPosition: 'top',
71+
});
72+
})
73+
.catch((err) => {
74+
console.error('Failed to copy token: ', err);
75+
this.snackBar.open('Failed to copy token to clipboard', 'Dismiss', {
76+
duration: 3000,
77+
verticalPosition: 'top',
78+
});
79+
});
80+
}
81+
}
3982
}

0 commit comments

Comments
 (0)