Skip to content

Commit 4ee4f6e

Browse files
committed
feat(settings): access tokens
1 parent d20ae17 commit 4ee4f6e

File tree

9 files changed

+183
-42
lines changed

9 files changed

+183
-42
lines changed

src/api/db/migrations.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ export function create(): Promise<null> {
1414
t.string('avatar').notNullable().defaultTo('/avatars/user.svg');
1515
t.timestamps();
1616
})
17+
.then(() => schema.createTableIfNotExists('access_tokens', (t: knex.TableBuilder) => {
18+
t.increments('id').unsigned().primary();
19+
t.string('description').notNullable();
20+
t.string('token').notNullable();
21+
t.integer('users_id').notNullable();
22+
t.foreign('users_id').references('users.id');
23+
t.timestamps();
24+
}))
1725
.then(() => schema.createTableIfNotExists('repositories', (t: knex.TableBuilder) => {
1826
t.increments('id').unsigned().primary();
1927
t.integer('github_id');
Lines changed: 12 additions & 0 deletions
Loading
Lines changed: 12 additions & 0 deletions
Loading

src/app/components/app-repository/app-repository.component.html

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ <h1>{{ repo?.full_name }}</h1>
1111
<div class="nav-center"></div>
1212
<div class="nav-right">
1313
<div class="group-buttons">
14-
<button class="group-button is-active">Builds</button>
15-
<button class="group-button">Settings</button>
14+
<button class="group-button" [class.is-active]="tab === 'builds'" (click)="tab = 'builds'">Builds</button>
15+
<button class="group-button" [class.is-active]="tab === 'settings'" (click)="tab = 'settings'">Settings</button>
1616
</div>
1717
</div>
1818
</div>
@@ -51,18 +51,31 @@ <h1>{{ repo?.full_name }}</h1>
5151
</div>
5252
</div>
5353

54-
<div class="column is-12" *ngIf="!repo?.builds.length">
54+
<div class="column is-12" *ngIf="!repo?.builds.length && tab === 'builds'">
5555
<div class="notification is-info">
5656
No builds has been runned yet.
5757
</div>
5858
</div>
5959

60-
<div class="column is-12" *ngIf="repo?.builds.length">
60+
<div class="column is-12" *ngIf="repo?.builds.length && tab === 'builds'">
6161
<div class="columns list-item" *ngFor="let build of repo.builds; let i = index;" [ngClass]="{ 'is-queued': build.status === 'queued', 'is-success': build.status === 'success', 'is-running': build.status === 'running', 'is-errored': build.status === 'failed' }" (click)="gotoBuild(build.id)">
6262
<app-build-item [build]="build"></app-build-item>
6363
</div>
6464
</div>
6565

66+
<div class="column is-12" *ngIf="tab === 'settings'">
67+
<div class="columns is-multiline">
68+
<div class="column is-12">
69+
<h2>Settings</h2>
70+
</div>
71+
<div class="column is-12">
72+
<form class="form" #repoForm="ngForm" (ngSubmit)="saveRepoSettings($event)">
73+
74+
</form>
75+
</div>
76+
</div>
77+
</div>
78+
6679
</div>
6780
</div>
6881
</div>

src/app/components/app-repository/app-repository.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { format, distanceInWordsToNow } from 'date-fns';
1313
export class AppRepositoryComponent implements OnInit, OnDestroy {
1414
loading: boolean;
1515
sub: Subscription;
16+
tab: 'builds' | 'settings';
1617
id: string;
1718
repo: any;
1819
url: string;
@@ -29,6 +30,7 @@ export class AppRepositoryComponent implements OnInit, OnDestroy {
2930
}
3031

3132
ngOnInit() {
33+
this.tab = 'settings';
3234
this.url = this.config.url;
3335

3436
this.route.params.subscribe(params => {

src/app/components/app-settings/app-settings.component.html

Lines changed: 79 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -29,45 +29,89 @@ <h1>My Settings</h1>
2929
</figure>
3030
</div>
3131
<div class="column is-8">
32-
<form method="post" #profileForm="ngForm" (ngSubmit)="updateProfile($event)">
33-
<div class="notification is-success" *ngIf="userSaved">
34-
<button class="delete" (click)="userSaved = false"></button>
35-
Data successfully updated.
36-
</div>
32+
33+
<div class="settings-container">
3734
<h2>User Settings</h2>
38-
<div class="form-field">
39-
<label class="form-label">Email (Username)</label>
40-
<input class="form-input" type="text" placeholder="Email" name="email" required readonly [(ngModel)]="user.email">
41-
</div>
42-
<div class="form-field">
43-
<label class="form-label">Full Name</label>
44-
<input class="form-input" type="text" placeholder="Full Name" name="fullname" required [(ngModel)]="user.fullname">
45-
</div>
46-
<input type="hidden" name="id" [(ngModel)]="user.id">
47-
<div class="form-field">
48-
<button type="submit" class="button green float-right" [disabled]="!profileForm.form.valid">Save Details</button>
49-
</div>
50-
</form>
35+
<form method="post" #profileForm="ngForm" (ngSubmit)="updateProfile($event)">
36+
<div class="notification is-success" *ngIf="userSaved">
37+
<button class="delete" (click)="userSaved = false"></button>
38+
Data successfully updated.
39+
</div>
40+
<div class="form-field">
41+
<label class="form-label">Email (Username)</label>
42+
<input class="form-input" type="text" placeholder="Email" name="email" required readonly [(ngModel)]="user.email">
43+
</div>
44+
<div class="form-field">
45+
<label class="form-label">Full Name</label>
46+
<input class="form-input" type="text" placeholder="Full Name" name="fullname" required [(ngModel)]="user.fullname">
47+
</div>
48+
<input type="hidden" name="id" [(ngModel)]="user.id">
49+
<div class="form-field">
50+
<button type="submit" class="button green float-right" [disabled]="!profileForm.form.valid">Save Details</button>
51+
</div>
52+
</form>
53+
</div>
5154

52-
<form method="post" #passwordForm="ngForm" (ngSubmit)="updatePassword($event)">
53-
<div class="notification is-success" *ngIf="userPasswordSaved">
54-
<button class="delete" (click)="userPasswordSaved = false"></button>
55-
Password successfully updated.
55+
<div class="settings-container">
56+
<h2>Access Tokens</h2>
57+
58+
<div class="tokens">
59+
<div class="token-item">
60+
<div class="columns">
61+
<div class="column is-1">
62+
<img src="images/icons/key.svg" class="token-icon">
63+
</div>
64+
<div class="column is-10">
65+
<p>GitHub Access Token</p>
66+
</div>
67+
<div class="column is-1">
68+
<span class="icon" title="Delete Token">
69+
<img src="images/icons/remove.svg">
70+
</span>
71+
</div>
72+
</div>
73+
</div>
5674
</div>
75+
76+
<form #tokenForm="ngForm" (ngSubmit)="updateToken($event)">
77+
<h2>Add New Access Token</h2>
78+
<div class="form-field">
79+
<label class="form-label">Token Description</label>
80+
<input class="form-input" type="text" placeholder="Access Token Description" name="token_description" required [(ngModel)]="token.description">
81+
</div>
82+
<div class="form-field">
83+
<label class="form-label">Token</label>
84+
<input class="form-input" type="password" placeholder="Access Token" name="token" required [(ngModel)]="token.token">
85+
</div>
86+
<input type="hidden" name="id" [(ngModel)]="user.id">
87+
<div class="form-field">
88+
<button type="submit" class="button green float-right" [disabled]="!tokenForm.form.valid">Add Token</button>
89+
</div>
90+
</form>
91+
</div>
92+
93+
<div class="settings-container">
5794
<h2>Password Update</h2>
58-
<div class="form-field">
59-
<label class="form-label">New Password</label>
60-
<input class="form-input" type="password" placeholder="New Password" name="password" required [(ngModel)]="userPass.password">
61-
</div>
62-
<div class="form-field">
63-
<label class="form-label">Repeat New Password</label>
64-
<input class="form-input" type="password" placeholder="Repeat New Password" name="repeat_password" required [(ngModel)]="userPass.repeat_password" validateEqual="password">
65-
</div>
66-
<input type="hidden" name="id" [(ngModel)]="userPass.id">
67-
<div class="form-field">
68-
<button type="submit" class="button green float-right" [disabled]="!passwordForm.form.valid">Save Details</button>
69-
</div>
70-
</form>
95+
<form method="post" #passwordForm="ngForm" (ngSubmit)="updatePassword($event)">
96+
<div class="notification is-success" *ngIf="userPasswordSaved">
97+
<button class="delete" (click)="userPasswordSaved = false"></button>
98+
Password successfully updated.
99+
</div>
100+
<div class="form-field">
101+
<label class="form-label">New Password</label>
102+
<input class="form-input" type="password" placeholder="New Password" name="password" required [(ngModel)]="userPass.password">
103+
</div>
104+
<div class="form-field">
105+
<label class="form-label">Repeat New Password</label>
106+
<input class="form-input" type="password" placeholder="Repeat New Password" name="repeat_password" required [(ngModel)]="userPass.repeat_password" validateEqual="password">
107+
</div>
108+
<input type="hidden" name="id" [(ngModel)]="userPass.id">
109+
<div class="form-field">
110+
<button type="submit" class="button green float-right" [disabled]="!passwordForm.form.valid">Update Password</button>
111+
</div>
112+
</form>
113+
</div>
114+
71115
</div>
72116
</div>
73117
</div>

src/app/components/app-settings/app-settings.component.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ export interface IUserPass {
1717
repeat_password;
1818
}
1919

20+
export interface IAccessToken {
21+
token: string;
22+
description: string;
23+
}
24+
2025
@Component({
2126
selector: 'app-settings',
2227
templateUrl: 'app-settings.component.html'
@@ -28,6 +33,7 @@ export class AppSettingsComponent implements OnInit {
2833
userPasswordSaved: boolean;
2934
userPass: IUserPass;
3035
avatarUrl: string;
36+
token: IAccessToken;
3137

3238
constructor(private api: ApiService, private auth: AuthService, private config: ConfigService) { }
3339

@@ -47,7 +53,9 @@ export class AppSettingsComponent implements OnInit {
4753
repeat_password: ''
4854
};
4955

50-
this.avatarUrl = this.config.url + '/' + data.avatar;
56+
this.avatarUrl = this.config.url + data.avatar;
57+
58+
this.token = { token: '', description: '' };
5159
}
5260

5361
updateProfile(e: MouseEvent): void {

src/app/styles/forms.sass

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
form
2-
margin: 0 0 30px
2+
margin: 0 0 20px
33
border-radius: 4px
44
border: 1px solid $border
55
background: $background
66

7-
87
.form-field
98
display: inline-block
109
width: 100%

src/app/styles/settings.sass

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,48 @@
11
.profile-image
2+
background: $background
3+
padding: 20px
4+
border-radius: 10px
5+
border: 1px solid $divider
6+
27
img
38
border-radius: 4px
49

10+
.settings-container
11+
padding: 20px
12+
background: $background-secondary
13+
border-radius: 4px
14+
border: 1px solid $divider
15+
margin: 0 0 20px 0
16+
17+
h2
18+
display: block
19+
margin-bottom: 10px
20+
font-weight: 700
21+
22+
.tokens
23+
width: 100%
24+
margin: 10px 0 20px 0
25+
display: inline-block
26+
27+
.token-item
28+
display: block
29+
padding: 10px 5px
30+
background: linear-gradient(to bottom, $background, $background-secondary)
31+
border: 1px solid $divider
32+
border-radius: 10px
33+
34+
.token-icon
35+
display: block
36+
width: 12px
37+
margin: 0 auto
38+
39+
.column
40+
display: flex
41+
align-items: center
42+
43+
.icon
44+
display: block
545

46+
p
47+
font-size: 14px
48+
font-weight: bold

0 commit comments

Comments
 (0)