diff --git a/src/app/core/components/nav-menu/nav-menu.component.scss b/src/app/core/components/nav-menu/nav-menu.component.scss index 69ad3b05b..1ee1f02cf 100644 --- a/src/app/core/components/nav-menu/nav-menu.component.scss +++ b/src/app/core/components/nav-menu/nav-menu.component.scss @@ -3,7 +3,7 @@ :host { .nav-menu { width: 100%; - max-width: 15.5rem; + max-width: 17rem; .active { font-weight: 700; diff --git a/src/app/core/components/sidenav/sidenav.component.scss b/src/app/core/components/sidenav/sidenav.component.scss index fc2d00567..282d9b612 100644 --- a/src/app/core/components/sidenav/sidenav.component.scss +++ b/src/app/core/components/sidenav/sidenav.component.scss @@ -3,6 +3,6 @@ aside { @include mix.flex-column; gap: 1.8rem; - width: 19rem; - padding: 1.8rem; + width: 19.5rem; + padding: 1.8rem 1rem 1.8rem 1.6rem; } diff --git a/src/app/core/components/topnav/topnav.component.scss b/src/app/core/components/topnav/topnav.component.scss index ff2146555..d2a0a06f1 100644 --- a/src/app/core/components/topnav/topnav.component.scss +++ b/src/app/core/components/topnav/topnav.component.scss @@ -7,7 +7,7 @@ .nav-container { @include mix.flex-center-between; background: var.$dark-blue-1; - padding: 1.8rem; + padding: 1.8rem 1.6rem; color: white; .topnav-icon { diff --git a/src/app/core/helpers/nav-items.constant.ts b/src/app/core/helpers/nav-items.constant.ts index fab14df27..75b9a2860 100644 --- a/src/app/core/helpers/nav-items.constant.ts +++ b/src/app/core/helpers/nav-items.constant.ts @@ -28,7 +28,7 @@ export const NAV_ITEMS: NavItem[] = [ }, { path: '/settings/addons', - label: 'Addon Accounts', + label: 'Configure Addon Accounts', useExactMatch: false, }, { @@ -42,7 +42,7 @@ export const NAV_ITEMS: NavItem[] = [ useExactMatch: true, }, { - path: '/settings/personal-access-tokens', + path: '/settings/tokens', label: 'Personal Access Tokens', useExactMatch: true, }, diff --git a/src/app/features/settings/addons/addons.component.ts b/src/app/features/settings/addons/addons.component.ts index 90d7dc18f..56db17acb 100644 --- a/src/app/features/settings/addons/addons.component.ts +++ b/src/app/features/settings/addons/addons.component.ts @@ -48,7 +48,7 @@ export class AddonsComponent implements OnInit { protected readonly isMobile = toSignal(inject(IS_XSMALL)); protected readonly searchValue = signal(''); protected readonly cards = signal([]); - protected readonly selectedTab = this.defaultTabValue; + protected selectedTab = this.defaultTabValue; protected readonly tabOptions: TabOption[] = [ { label: 'All Add-ons', value: 0 }, { label: 'Connected Add-ons', value: 1 }, diff --git a/src/app/features/settings/addons/connect-addon/connect-addon.component.html b/src/app/features/settings/addons/connect-addon/connect-addon.component.html index ae967b61d..fb9be27d4 100644 --- a/src/app/features/settings/addons/connect-addon/connect-addon.component.html +++ b/src/app/features/settings/addons/connect-addon/connect-addon.component.html @@ -80,7 +80,7 @@

Account Name

> diff --git a/src/app/features/settings/developer-apps/developer-app-details/developer-app-details.component.html b/src/app/features/settings/developer-apps/developer-app-details/developer-app-details.component.html index f229fbbfc..3ce019244 100644 --- a/src/app/features/settings/developer-apps/developer-app-details/developer-app-details.component.html +++ b/src/app/features/settings/developer-apps/developer-app-details/developer-app-details.component.html @@ -2,11 +2,11 @@ -
+

{{ developerApp().appName + developerAppId() }}

Edit app
diff --git a/src/app/features/settings/developer-apps/developer-app-details/developer-app-details.component.scss b/src/app/features/settings/developer-apps/developer-app-details/developer-app-details.component.scss index 6a9a327fb..a6dd08ec9 100644 --- a/src/app/features/settings/developer-apps/developer-app-details/developer-app-details.component.scss +++ b/src/app/features/settings/developer-apps/developer-app-details/developer-app-details.component.scss @@ -14,7 +14,7 @@ margin-bottom: 1.7rem; } - .tittle-container { + .title-container { @include mix.flex-center-between; margin-bottom: 3.4rem; @@ -63,7 +63,7 @@ transition: opacity 0.3s ease; white-space: nowrap; border-radius: 8px; - box-shadow: 0px 0px 4px 0px #00000029; + box-shadow: 0 0 4px 0 #00000029; background: var.$white; &.visible { diff --git a/src/app/features/settings/developer-apps/developer-app-details/developer-app-details.component.ts b/src/app/features/settings/developer-apps/developer-app-details/developer-app-details.component.ts index 54884e8b3..a724fa4ee 100644 --- a/src/app/features/settings/developer-apps/developer-app-details/developer-app-details.component.ts +++ b/src/app/features/settings/developer-apps/developer-app-details/developer-app-details.component.ts @@ -32,6 +32,7 @@ import { linkValidator } from '@core/helpers/link-validator.helper'; import { ConfirmationService } from 'primeng/api'; import { defaultConfirmationConfig } from '@shared/helpers/default-confirmation-config.helper'; import { timer } from 'rxjs'; +import { NgClass } from '@angular/common'; @Component({ selector: 'osf-developer-application-details', @@ -45,6 +46,7 @@ import { timer } from 'rxjs'; CdkCopyToClipboard, FormsModule, ReactiveFormsModule, + NgClass, ], templateUrl: './developer-app-details.component.html', styleUrl: './developer-app-details.component.scss', diff --git a/src/app/features/settings/settings-container.component.html b/src/app/features/settings/settings-container.component.html index f58acf390..83c990870 100644 --- a/src/app/features/settings/settings-container.component.html +++ b/src/app/features/settings/settings-container.component.html @@ -1,3 +1,3 @@ -
+
diff --git a/src/app/features/settings/settings-container.component.scss b/src/app/features/settings/settings-container.component.scss index 4bafbf07a..ffcd67626 100644 --- a/src/app/features/settings/settings-container.component.scss +++ b/src/app/features/settings/settings-container.component.scss @@ -5,8 +5,6 @@ flex: 1; .desktop { - @include mix.flex-column; margin-top: 4.5rem; - flex: 1; } } diff --git a/src/app/features/settings/settings.routes.ts b/src/app/features/settings/settings.routes.ts index affc73cdc..c6c794594 100644 --- a/src/app/features/settings/settings.routes.ts +++ b/src/app/features/settings/settings.routes.ts @@ -1,6 +1,7 @@ import { Routes } from '@angular/router'; import { SettingsContainerComponent } from '@osf/features/settings/settings-container.component'; import { developerAppsRoute } from '@osf/features/settings/developer-apps/developer-apps.route'; +import { tokensAppsRoute } from '@osf/features/settings/tokens/tokens.route'; export const settingsRoutes: Routes = [ { @@ -41,6 +42,7 @@ export const settingsRoutes: Routes = [ }, ], }, + tokensAppsRoute, ], }, ]; diff --git a/src/app/features/settings/tokens/token-add-edit-form/token-add-edit-form.component.html b/src/app/features/settings/tokens/token-add-edit-form/token-add-edit-form.component.html new file mode 100644 index 000000000..6d2dcb023 --- /dev/null +++ b/src/app/features/settings/tokens/token-add-edit-form/token-add-edit-form.component.html @@ -0,0 +1,62 @@ +
+
+ + +
+ +
+
+

Scopes

+

+ Scopes limit access for personal access tokens. +

+
+ +
+ @for (scope of availableScopes; track scope.name) { +
+ +
+ + {{ scope.description }} +
+
+ } +
+
+ +
+ @if (isEditMode()) { + + } @else { + + + } +
+
diff --git a/src/app/features/settings/tokens/token-add-edit-form/token-add-edit-form.component.scss b/src/app/features/settings/tokens/token-add-edit-form/token-add-edit-form.component.scss new file mode 100644 index 000000000..23a39d8e5 --- /dev/null +++ b/src/app/features/settings/tokens/token-add-edit-form/token-add-edit-form.component.scss @@ -0,0 +1,12 @@ +@use "assets/styles/variables" as var; + +:host { + label { + font-weight: 700; + color: var.$dark-blue-1; + } + + h3 { + text-transform: none; + } +} diff --git a/src/app/features/settings/tokens/token-add-edit-form/token-add-edit-form.component.spec.ts b/src/app/features/settings/tokens/token-add-edit-form/token-add-edit-form.component.spec.ts new file mode 100644 index 000000000..029ede4b0 --- /dev/null +++ b/src/app/features/settings/tokens/token-add-edit-form/token-add-edit-form.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TokenAddEditFormComponent } from './token-add-edit-form.component'; + +describe('CreateTokenComponent', () => { + let component: TokenAddEditFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TokenAddEditFormComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(TokenAddEditFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/settings/tokens/token-add-edit-form/token-add-edit-form.component.ts b/src/app/features/settings/tokens/token-add-edit-form/token-add-edit-form.component.ts new file mode 100644 index 000000000..30846a8d1 --- /dev/null +++ b/src/app/features/settings/tokens/token-add-edit-form/token-add-edit-form.component.ts @@ -0,0 +1,75 @@ +import { + ChangeDetectionStrategy, + Component, + inject, + input, + OnInit, +} from '@angular/core'; +import { DynamicDialogRef } from 'primeng/dynamicdialog'; +import { Button } from 'primeng/button'; +import { InputText } from 'primeng/inputtext'; +import { Checkbox } from 'primeng/checkbox'; +import { + FormControl, + FormGroup, + ReactiveFormsModule, + Validators, +} from '@angular/forms'; +import { + AVAILABLE_SCOPES, + PersonalAccessToken, + TokenForm, + TokenFormControls, +} from '@osf/features/settings/tokens/tokens.enities'; +import { CommonModule } from '@angular/common'; +import { IS_XSMALL } from '@shared/utils/breakpoints.tokens'; +import { toSignal } from '@angular/core/rxjs-interop'; + +@Component({ + selector: 'osf-token-add-edit-form', + imports: [Button, InputText, ReactiveFormsModule, CommonModule, Checkbox], + templateUrl: './token-add-edit-form.component.html', + styleUrl: './token-add-edit-form.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class TokenAddEditFormComponent implements OnInit { + #isXSmall$ = inject(IS_XSMALL); + isEditMode = input(false); + initialValues = input(null); + protected readonly dialogRef = inject(DynamicDialogRef); + protected readonly TokenFormControls = TokenFormControls; + protected readonly availableScopes = AVAILABLE_SCOPES; + protected readonly isXSmall = toSignal(this.#isXSmall$); + + readonly tokenForm: TokenForm = new FormGroup({ + [TokenFormControls.TokenName]: new FormControl('', { + nonNullable: true, + validators: [Validators.required], + }), + [TokenFormControls.Scopes]: new FormControl([], { + nonNullable: true, + validators: [Validators.required], + }), + }); + + ngOnInit(): void { + if (this.initialValues()) { + this.tokenForm.patchValue({ + [TokenFormControls.TokenName]: this.initialValues()?.tokenName, + [TokenFormControls.Scopes]: this.initialValues()?.scopes, + }); + } + } + + submitForm(): void { + if (!this.tokenForm.valid) { + this.tokenForm.markAllAsTouched(); + this.tokenForm.get(TokenFormControls.TokenName)?.markAsDirty(); + this.tokenForm.get(TokenFormControls.Scopes)?.markAsDirty(); + return; + } + + //TODO integrate API + this.dialogRef.close(); + } +} diff --git a/src/app/features/settings/tokens/token-details/token-details.component.html b/src/app/features/settings/tokens/token-details/token-details.component.html new file mode 100644 index 000000000..6a89fd706 --- /dev/null +++ b/src/app/features/settings/tokens/token-details/token-details.component.html @@ -0,0 +1,26 @@ +
+ + +
+

{{ token().tokenName }}

+ +
+ + +

Edit Token

+ +
+
diff --git a/src/app/features/settings/tokens/token-details/token-details.component.scss b/src/app/features/settings/tokens/token-details/token-details.component.scss new file mode 100644 index 000000000..5b1e2fedc --- /dev/null +++ b/src/app/features/settings/tokens/token-details/token-details.component.scss @@ -0,0 +1,22 @@ +@use "assets/styles/mixins" as mix; +@use "assets/styles/variables" as var; + +:host { + @include mix.flex-column; + flex: 1; + + .mobile { + flex-direction: column; + gap: 1.7rem; + } + + .content-container { + padding: 1.7rem; + color: var.$dark-blue-1; + background-color: white; + + &.mobile { + padding: 1rem; + } + } +} diff --git a/src/app/features/settings/tokens/token-details/token-details.component.spec.ts b/src/app/features/settings/tokens/token-details/token-details.component.spec.ts new file mode 100644 index 000000000..fbea28176 --- /dev/null +++ b/src/app/features/settings/tokens/token-details/token-details.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TokenDetailsComponent } from './token-details.component'; + +describe('TokenDetailsComponent', () => { + let component: TokenDetailsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TokenDetailsComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(TokenDetailsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/settings/tokens/token-details/token-details.component.ts b/src/app/features/settings/tokens/token-details/token-details.component.ts new file mode 100644 index 000000000..41d7b7508 --- /dev/null +++ b/src/app/features/settings/tokens/token-details/token-details.component.ts @@ -0,0 +1,53 @@ +import { + ChangeDetectionStrategy, + Component, + inject, + signal, +} from '@angular/core'; +import { Button } from 'primeng/button'; +import { Card } from 'primeng/card'; +import { FormsModule } from '@angular/forms'; +import { RouterLink } from '@angular/router'; +import { ConfirmationService } from 'primeng/api'; +import { IS_XSMALL } from '@shared/utils/breakpoints.tokens'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { PersonalAccessToken } from '@osf/features/settings/tokens/tokens.enities'; +import { defaultConfirmationConfig } from '@shared/helpers/default-confirmation-config.helper'; +import { TokenAddEditFormComponent } from '@osf/features/settings/tokens/token-add-edit-form/token-add-edit-form.component'; +import { DialogService, DynamicDialogRef } from 'primeng/dynamicdialog'; + +@Component({ + selector: 'osf-token-details', + imports: [Button, Card, FormsModule, RouterLink, TokenAddEditFormComponent], + providers: [DialogService, DynamicDialogRef], + changeDetection: ChangeDetectionStrategy.OnPush, + templateUrl: './token-details.component.html', + styleUrls: ['./token-details.component.scss'], +}) +export class TokenDetailsComponent { + #confirmationService = inject(ConfirmationService); + #isXSmall$ = inject(IS_XSMALL); + readonly token = signal({ + id: '1', + tokenName: 'Token name example', + scopes: ['osf.full_read', 'osf.full_write'], + }); + protected readonly isXSmall = toSignal(this.#isXSmall$); + + deleteToken(): void { + this.#confirmationService.confirm({ + ...defaultConfirmationConfig, + message: + 'Are you sure you want to delete this token? This action cannot be reversed.', + header: `Delete Token ${this.token().tokenName}?`, + acceptButtonProps: { + ...defaultConfirmationConfig.acceptButtonProps, + severity: 'danger', + label: 'Delete', + }, + accept: () => { + //TODO integrate API + }, + }); + } +} diff --git a/src/app/features/settings/tokens/tokens-list/tokens-list.component.html b/src/app/features/settings/tokens/tokens-list/tokens-list.component.html new file mode 100644 index 000000000..533af6aa5 --- /dev/null +++ b/src/app/features/settings/tokens/tokens-list/tokens-list.component.html @@ -0,0 +1,29 @@ +
+

+ Personal access tokens function like ordinary OAuth access tokens. They can + be used to authenticate to the API. +

+ +
+ @for (token of tokens(); track $index) { + +
+ +

{{ token.tokenName }}

+
+
+ +
+
+
+ } +
+
diff --git a/src/app/features/settings/tokens/tokens-list/tokens-list.component.scss b/src/app/features/settings/tokens/tokens-list/tokens-list.component.scss new file mode 100644 index 000000000..0613549c7 --- /dev/null +++ b/src/app/features/settings/tokens/tokens-list/tokens-list.component.scss @@ -0,0 +1,43 @@ +@use "assets/styles/variables" as var; +@use "assets/styles/mixins" as mix; + +:host { + @include mix.flex-column; + flex: 1; + + .content-container { + padding: 1.7rem; + color: var.$dark-blue-1; + background-color: var.$white; + + &.mobile { + padding: 1rem; + } + + p { + margin-bottom: 1.7rem; + } + + .tokens-container { + gap: 0.85rem; + + p-card { + .card-body { + &.mobile { + @include mix.flex-column; + gap: 0.85rem; + + a { + align-self: flex-start; + } + + .button-container { + align-self: flex-end; + width: 50%; + } + } + } + } + } + } +} diff --git a/src/app/features/settings/tokens/tokens-list/tokens-list.component.spec.ts b/src/app/features/settings/tokens/tokens-list/tokens-list.component.spec.ts new file mode 100644 index 000000000..a4175341c --- /dev/null +++ b/src/app/features/settings/tokens/tokens-list/tokens-list.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TokensListComponent } from './tokens-list.component'; + +describe('TokensListComponent', () => { + let component: TokensListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TokensListComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(TokensListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/settings/tokens/tokens-list/tokens-list.component.ts b/src/app/features/settings/tokens/tokens-list/tokens-list.component.ts new file mode 100644 index 000000000..59ca27717 --- /dev/null +++ b/src/app/features/settings/tokens/tokens-list/tokens-list.component.ts @@ -0,0 +1,67 @@ +import { + ChangeDetectionStrategy, + Component, + inject, + signal, +} from '@angular/core'; +import { ConfirmationService } from 'primeng/api'; +import { IS_XSMALL } from '@shared/utils/breakpoints.tokens'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { Button } from 'primeng/button'; +import { Card } from 'primeng/card'; +import { RouterLink } from '@angular/router'; +import { PersonalAccessToken } from '@osf/features/settings/tokens/tokens.enities'; +import { defaultConfirmationConfig } from '@shared/helpers/default-confirmation-config.helper'; + +@Component({ + selector: 'osf-tokens-list', + imports: [Button, Card, RouterLink], + templateUrl: './tokens-list.component.html', + styleUrl: './tokens-list.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class TokensListComponent { + #confirmationService = inject(ConfirmationService); + #isXSmall$ = inject(IS_XSMALL); + protected readonly isXSmall = toSignal(this.#isXSmall$); + + tokens = signal([ + { + id: '1', + tokenName: 'Token name example 1', + scopes: ['osf.full_read', 'osf.full_write'], + }, + { + id: '2', + tokenName: 'Token name example 2', + scopes: ['osf.full_read', 'osf.full_write'], + }, + { + id: '3', + tokenName: 'Token name example 3', + scopes: ['osf.full_read', 'osf.full_write'], + }, + { + id: '4', + tokenName: 'Token name example 4', + scopes: ['osf.full_read', 'osf.full_write'], + }, + ]); + + deleteApp(token: PersonalAccessToken) { + this.#confirmationService.confirm({ + ...defaultConfirmationConfig, + message: + 'Are you sure you want to delete this token? This action cannot be reversed.', + header: `Delete Token ${token.tokenName}?`, + acceptButtonProps: { + ...defaultConfirmationConfig.acceptButtonProps, + severity: 'danger', + label: 'Delete', + }, + accept: () => { + //TODO integrate API + }, + }); + } +} diff --git a/src/app/features/settings/tokens/tokens.component.html b/src/app/features/settings/tokens/tokens.component.html new file mode 100644 index 000000000..0b428d9e1 --- /dev/null +++ b/src/app/features/settings/tokens/tokens.component.html @@ -0,0 +1,11 @@ + + +
+ +
diff --git a/src/app/features/settings/tokens/tokens.component.scss b/src/app/features/settings/tokens/tokens.component.scss new file mode 100644 index 000000000..e9dab5325 --- /dev/null +++ b/src/app/features/settings/tokens/tokens.component.scss @@ -0,0 +1,6 @@ +@use "assets/styles/mixins" as mix; + +:host { + @include mix.flex-column; + flex: 1; +} diff --git a/src/app/features/settings/tokens/tokens.component.spec.ts b/src/app/features/settings/tokens/tokens.component.spec.ts new file mode 100644 index 000000000..534861f4a --- /dev/null +++ b/src/app/features/settings/tokens/tokens.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TokensComponent } from './tokens.component'; + +describe('PersonalAccessTokenComponent', () => { + let component: TokensComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TokensComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(TokensComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/features/settings/tokens/tokens.component.ts b/src/app/features/settings/tokens/tokens.component.ts new file mode 100644 index 000000000..679d94012 --- /dev/null +++ b/src/app/features/settings/tokens/tokens.component.ts @@ -0,0 +1,51 @@ +import { + ChangeDetectionStrategy, + Component, + inject, + signal, +} from '@angular/core'; +import { SubHeaderComponent } from '@shared/components/sub-header/sub-header.component'; +import { DialogService } from 'primeng/dynamicdialog'; +import { IS_MEDIUM, IS_XSMALL } from '@shared/utils/breakpoints.tokens'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { TokenAddEditFormComponent } from '@osf/features/settings/tokens/token-add-edit-form/token-add-edit-form.component'; +import { RouterOutlet } from '@angular/router'; + +@Component({ + selector: 'osf-tokens', + imports: [SubHeaderComponent, RouterOutlet], + templateUrl: './tokens.component.html', + styleUrl: './tokens.component.scss', + providers: [DialogService], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class TokensComponent { + #dialogService = inject(DialogService); + #isXSmall$ = inject(IS_XSMALL); + #isMedium$ = inject(IS_MEDIUM); + tokenValue = signal(''); + protected readonly isXSmall = toSignal(this.#isXSmall$); + protected readonly isMedium = toSignal(this.#isMedium$); + + createToken(): void { + let dialogWidth = '850px'; + if (this.isXSmall()) { + dialogWidth = '345px'; + } else if (this.isMedium()) { + dialogWidth = '500px'; + } + + this.#dialogService.open(TokenAddEditFormComponent, { + width: dialogWidth, + focusOnShow: false, + header: 'Create Personal Access Token', + closeOnEscape: true, + modal: true, + closable: true, + }); + } + + onTokenCreated(): void { + this.tokenValue.set('asdkDh3bhHfEqhndsdk#fo90jNbvt8dd5%1jFkc42kIop'); + } +} diff --git a/src/app/features/settings/tokens/tokens.enities.ts b/src/app/features/settings/tokens/tokens.enities.ts new file mode 100644 index 000000000..ffa3e674d --- /dev/null +++ b/src/app/features/settings/tokens/tokens.enities.ts @@ -0,0 +1,38 @@ +import { FormControl, FormGroup } from '@angular/forms'; + +export interface PersonalAccessToken { + id: string; + tokenName: string; + scopes: string[]; +} + +export enum TokenFormControls { + TokenName = 'tokenName', + Scopes = 'scopes', +} + +export type TokenForm = FormGroup<{ + [TokenFormControls.TokenName]: FormControl; + [TokenFormControls.Scopes]: FormControl; +}>; + +export const AVAILABLE_SCOPES = [ + { + name: 'osf.full_read', + description: + 'View all information associated with this account, including for private projects', + }, + { + name: 'osf.full_write', + description: + 'View and edit all information associated with this account, including for private projects', + }, + { + name: 'osf.users.profile_read', + description: 'Read your profile data', + }, + { + name: 'osf.users.email_read', + description: 'Read your primary email address', + }, +]; diff --git a/src/app/features/settings/tokens/tokens.route.ts b/src/app/features/settings/tokens/tokens.route.ts new file mode 100644 index 000000000..76b317cb9 --- /dev/null +++ b/src/app/features/settings/tokens/tokens.route.ts @@ -0,0 +1,23 @@ +import { Route } from '@angular/router'; +import { TokensComponent } from '@osf/features/settings/tokens/tokens.component'; + +export const tokensAppsRoute: Route = { + path: 'tokens', + component: TokensComponent, + children: [ + { + path: '', + loadComponent: () => + import('./tokens-list/tokens-list.component').then( + (c) => c.TokensListComponent, + ), + }, + { + path: ':id/details', + loadComponent: () => + import('./token-details/token-details.component').then( + (c) => c.TokenDetailsComponent, + ), + }, + ], +}; diff --git a/src/assets/styles/overrides/confirmation-dialog.scss b/src/assets/styles/overrides/confirmation-dialog.scss index b178b6852..e59ae5a8b 100644 --- a/src/assets/styles/overrides/confirmation-dialog.scss +++ b/src/assets/styles/overrides/confirmation-dialog.scss @@ -1,6 +1,9 @@ -.p-confirmdialog { +@use "../variables" as var; + +.p-dialog { min-height: 212px; width: 450px; + margin: 1rem; .p-dialog-header { padding: 24px; @@ -10,6 +13,13 @@ font-weight: 700; text-transform: capitalize; } + + &.ng-star-inserted { + p-button > button { + background: transparent; + color: var.$grey-1; + } + } } .p-dialog-content { diff --git a/src/assets/styles/overrides/drawer.scss b/src/assets/styles/overrides/drawer.scss index 62af99d18..436d88c7c 100644 --- a/src/assets/styles/overrides/drawer.scss +++ b/src/assets/styles/overrides/drawer.scss @@ -3,7 +3,7 @@ .p-drawer.p-drawer-active.p-drawer-left { width: 100%; background-color: var.$dark-blue-1; - padding-left: 1.8rem; + padding-left: 1.6rem; border: none; }