Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added prototype for view service #438

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/app/account/account.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { MaybeNull } from "src/app/common/app.types";
import { AccountNotFoundError } from "src/app/common/errors";
import { AccountPageQueryParams } from "./account.component.model";
import { ModalService } from "../components/modal/modal.service";
import { LoggedUserService } from "../auth/logged-user.service";

@Component({
selector: "app-account",
Expand All @@ -35,7 +34,6 @@ export class AccountComponent extends BaseComponent implements OnInit {
private route = inject(ActivatedRoute);
private modalService = inject(ModalService);
private accountService = inject(AccountService);
private loggedUserService = inject(LoggedUserService);

public ngOnInit(): void {
const accountName$ = this.route.params.pipe(
Expand Down
2 changes: 2 additions & 0 deletions src/app/admin-view/admin-link/admin-link.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<ng-content></ng-content>
<mat-icon *ngIf="adminPrivileges" [class]="'admin-privileges-icon ' + theme"> admin_panel_settings</mat-icon>
25 changes: 25 additions & 0 deletions src/app/admin-view/admin-link/admin-link.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
:host {
position: relative;
}

.admin-privileges-icon {
font-size: 16px;
position: absolute;
top: -4px;
right: -27px;
display: block;
}

.light-theme {
color: #f1f1f1 !important;
}

.dark-theme {
color: #378bb0 !important;
}

@media (width <=768px) {
.admin-privileges-icon {
display: none;
}
}
21 changes: 21 additions & 0 deletions src/app/admin-view/admin-link/admin-link.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { AdminLinkComponent } from './admin-link.component';

describe('AdminLinkComponent', () => {
let component: AdminLinkComponent;
let fixture: ComponentFixture<AdminLinkComponent>;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [AdminLinkComponent]
});
fixture = TestBed.createComponent(AdminLinkComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
12 changes: 12 additions & 0 deletions src/app/admin-view/admin-link/admin-link.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ChangeDetectionStrategy, Component, Input } from "@angular/core";

@Component({
selector: "app-admin-link",
templateUrl: "./admin-link.component.html",
styleUrls: ["./admin-link.component.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AdminLinkComponent {
@Input({ required: true }) adminPrivileges: boolean;
@Input() theme: string = "light-theme";
}
4 changes: 2 additions & 2 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { SetTransformComponent } from "./dataset-view/additional-components/meta
import { LoginGuard } from "./auth/guards/login.guard";
import { ReturnToCliComponent } from "./components/return-to-cli/return-to-cli.component";
import { AddPushSourceComponent } from "./dataset-view/additional-components/metadata-component/components/source-events/add-push-source/add-push-source.component";
import { AdminGuard } from "./auth/guards/admin.guard";
import { adminGuard } from "./auth/guards/admin.guard";
import { AdminDashboardComponent } from "./admin-view/admin-dashboard/admin-dashboard.component";
import { DatasetFlowDetailsComponent } from "./dataset-flow/dataset-flow-details/dataset-flow-details.component";
import { AccountComponent } from "./account/account.component";
Expand All @@ -42,7 +42,7 @@ export const routes: Routes = [
component: DatasetCreateComponent,
},
{
canActivate: [AdminGuard],
canActivate: [adminGuard],
path: ProjectLinks.URL_ADMIN_DASHBOARD,
component: AdminDashboardComponent,
},
Expand Down
13 changes: 9 additions & 4 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { LoginService } from "./auth/login/login.service";
import { loadErrorMessages } from "@apollo/client/dev";
import { isDevMode } from "@angular/core";
import moment from "moment";
import { LoggedUserService } from "./auth/logged-user.service";
import packageFile from "../../package.json";
import { LocalStorageService } from "./services/local-storage.service";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
Expand Down Expand Up @@ -63,7 +62,6 @@ export class AppComponent extends BaseComponent implements OnInit {
private navigationService = inject(NavigationService);
private appConfigService = inject(AppConfigService);
private cdr = inject(ChangeDetectorRef);
private loggedUserService = inject(LoggedUserService);
private localStorageService = inject(LocalStorageService);

public ngOnInit(): void {
Expand Down Expand Up @@ -91,6 +89,13 @@ export class AppComponent extends BaseComponent implements OnInit {
this.loggedAccount = user ? _.cloneDeep(user) : AppComponent.ANONYMOUS_ACCOUNT_INFO;
this.cdr.detectChanges();
});

this.initAdminSlideToggle();
}

private initAdminSlideToggle(): void {
const flag = this.localStorageService.adminPrivileges;
this.loggedUserService.emitAdminPrivilegesChanges(Boolean(flag));
}

private setMomentOptions(): void {
Expand Down Expand Up @@ -175,7 +180,7 @@ export class AppComponent extends BaseComponent implements OnInit {
yesButtonText: "Ok",
}),
);
//TODO: Implement AdminDashBoardComponent
// this.navigationService.navigateToAdminDashBoard();
// TODO: Implement AdminDashBoardComponent
// this.navigationService.navigateToAdminDashBoard();
}
}
2 changes: 2 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import { AccountComponent } from "./account/account.component";
import { DatasetsTabComponent } from "./account/additional-components/datasets-tab/datasets-tab.component";
import { AccessTokensTabComponent } from "./auth/settings/tabs/access-tokens-tab/access-tokens-tab.component";
import { MatSlideToggleModule } from "@angular/material/slide-toggle";
import { AdminLinkComponent } from "./admin-view/admin-link/admin-link.component";

const Services = [
{
Expand Down Expand Up @@ -204,6 +205,7 @@ const MatModules = [
AdminDashboardComponent,
AccessTokensTabComponent,
AccountFlowsTabComponent,
AdminLinkComponent,
],
imports: [
AppRoutingModule,
Expand Down
36 changes: 17 additions & 19 deletions src/app/auth/guards/admin.guard.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
import { inject, Injectable } from "@angular/core";
import { inject } from "@angular/core";
import { NavigationService } from "src/app/services/navigation.service";
import { LoggedUserService } from "../logged-user.service";
import { CanActivateFn } from "@angular/router";
import { combineLatest, map, of } from "rxjs";

@Injectable({
providedIn: "root",
})
export class AdminGuard {
private navigationService = inject(NavigationService);
private loggedUserService = inject(LoggedUserService);
export const adminGuard: CanActivateFn = () => {
const navigationService = inject(NavigationService);
const loggedUserService = inject(LoggedUserService);

public canActivate(): boolean {
if (!this.isAdmin()) {
this.navigationService.navigateToHome();
return false;
}
return true;
}

private isAdmin(): boolean {
return this.loggedUserService.isAdmin;
}
}
return combineLatest([of(loggedUserService.isAdmin), loggedUserService.adminPrivilegesChanges]).pipe(
map(([isAdmin, adminPrivileges]) => {
if (isAdmin && adminPrivileges.value) {
return true;
} else {
navigationService.navigateToHome();
return false;
}
}),
);
};
19 changes: 18 additions & 1 deletion src/app/auth/logged-user.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Injectable } from "@angular/core";
import { catchError, first } from "rxjs/operators";
import { Observable, ReplaySubject, Subject, of } from "rxjs";
import { BehaviorSubject, Observable, ReplaySubject, Subject, of } from "rxjs";
import { NavigationService } from "../services/navigation.service";
import { MaybeNull } from "../common/app.types";
import { isNull } from "lodash";
Expand All @@ -20,6 +20,9 @@ import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
export class LoggedUserService extends UnsubscribeDestroyRefAdapter {
private loggedInUser: MaybeNull<AccountFragment> = null;
private loggedInUser$: Subject<MaybeNull<AccountFragment>> = new ReplaySubject<MaybeNull<AccountFragment>>(1);
private adminPrivileges$: BehaviorSubject<{ value: boolean }> = new BehaviorSubject<{ value: boolean }>({
value: false,
});

constructor(
private loginService: LoginService,
Expand All @@ -38,6 +41,14 @@ export class LoggedUserService extends UnsubscribeDestroyRefAdapter {
.subscribe((user: AccountFragment) => this.changeUser(user));
}

public get adminPrivilegesChanges(): Observable<{ value: boolean }> {
return this.adminPrivileges$.asObservable();
}

public emitAdminPrivilegesChanges(value: boolean): void {
return this.adminPrivileges$.next({ value });
}

public initializeCompletes(): Observable<void> {
const loginInstructions: AppConfigLoginInstructions | null = this.appConfigService.loginInstructions;
if (loginInstructions) {
Expand Down Expand Up @@ -83,6 +94,7 @@ export class LoggedUserService extends UnsubscribeDestroyRefAdapter {
this.changeUser(null);
this.resetAccessToken();
this.clearGraphQLCache();
this.resetAdminPrivileges();
}

private attemptPreviousAuthenticationCompletes(): Observable<void> {
Expand Down Expand Up @@ -116,4 +128,9 @@ export class LoggedUserService extends UnsubscribeDestroyRefAdapter {
private saveAccessToken(token: string): void {
this.localStorageService.setAccessToken(token);
}

private resetAdminPrivileges(): void {
this.localStorageService.setAdminPriveleges(null);
this.emitAdminPrivilegesChanges(false);
}
}
22 changes: 16 additions & 6 deletions src/app/auth/settings/account-settings.component.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<div class="pt-4 p-responsive clearfix" *ngIf="user$ | async as user">
<div class="pt-4 p-responsive clearfix" *ngIf="userData$ | async as data">
<div class="d-md-flex align-items-center justify-content-between mt-1 mb-4">
<div class="d-flex align-items-center mb-2 mb-md-0">
<img
[src]="user.avatarUrl ?? DEFAULT_AVATAR_URL"
[alt]="'@' + user.accountName"
[src]="data.user.avatarUrl ?? DEFAULT_AVATAR_URL"
[alt]="'@' + data.user.accountName"
size="48"
height="48"
width="48"
Expand All @@ -12,17 +12,27 @@
/>
<div class="flex-auto mx-4 mt-3">
<a
[routerLink]="['/', user.accountName]"
[routerLink]="['/', data.user.accountName]"
class="color-fg-default fw-bold-custom fs-5"
data-test-id="user-name-link"
>
{{ user.displayName }} <span class="text-muted">({{ user.accountName }})</span>
{{ data.user.displayName }} <span class="text-muted">({{ data.user.accountName }})</span>
</a>
<div class="d-flex align-items-center flex-wrap">
<p class="color-fg-muted">Your personal account</p>
</div>
</div>
</div>
<div class="box p-4" *ngIf="isAdmin">
<mat-slide-toggle
[(ngModel)]="data.adminPrivileges"
(change)="adminSlideToggleChange($event)"
color="primary"
class="mat-elevation-z0"
>
<span class="ps-2"> Admin priveleges</span>
</mat-slide-toggle>
</div>
</div>
<div
class="d-flex layout layout--flowRow-until-md layout--sidebar-position-start layout--sidebarPosition-flowRow-start"
Expand Down Expand Up @@ -284,7 +294,7 @@
</div>
<div class="content">
<ng-container *ngIf="activeTab === AccountSettingsTabs.ACCESS_TOKENS">
<app-access-tokens-tab [account]="user" />
<app-access-tokens-tab [account]="data.user!" />
</ng-container>
</div>
</div>
Expand Down
16 changes: 16 additions & 0 deletions src/app/auth/settings/account-settings.component.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
@import "var";

:host {
::ng-deep {
.mat-slide-toggle {
.mat-slide-toggle-ripple {
position: relative;
}
}

.mdc-switch {
.mdc-switch__ripple {
display: none;
}
}
}
}

.p-responsive {
padding: 0 60px;

Expand Down
38 changes: 33 additions & 5 deletions src/app/auth/settings/account-settings.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import { AccountFragment } from "src/app/api/kamu.graphql.interface";
import { AccountSettingsTabs } from "./account-settings.constants";
import { ChangeDetectionStrategy, Component, inject, OnInit } from "@angular/core";
import { ActivatedRoute, NavigationEnd, Router } from "@angular/router";
import { filter } from "rxjs/operators";
import { filter, map } from "rxjs/operators";
import { BaseComponent } from "src/app/common/base.component";
import AppValues from "src/app/common/app.values";
import { MaybeNull, MaybeUndefined } from "src/app/common/app.types";
import { Observable } from "rxjs";
import { LoggedUserService } from "../logged-user.service";
import { combineLatest, Observable } from "rxjs";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { MatSlideToggleChange } from "@angular/material/slide-toggle";
import { LocalStorageService } from "src/app/services/local-storage.service";

@Component({
selector: "app-settings",
Expand All @@ -26,7 +27,12 @@ export class AccountSettingsComponent extends BaseComponent implements OnInit {

private router = inject(Router);
private route = inject(ActivatedRoute);
private loggedUserService = inject(LoggedUserService);
private localStorageService = inject(LocalStorageService);

public userData$: Observable<{
user: AccountFragment;
adminPrivileges: boolean;
} | null>;

public ngOnInit(): void {
this.router.events
Expand All @@ -39,13 +45,35 @@ export class AccountSettingsComponent extends BaseComponent implements OnInit {
});

this.extractActiveTabFromRoute();
this.user$ = this.loggedUserService.loggedInUserChanges;

this.userData$ = combineLatest([
this.loggedUserService.loggedInUserChanges,
this.loggedUserService.adminPrivilegesChanges,
]).pipe(
map(([user, adminPrivileges]) => {
return user
? {
user,
adminPrivileges: adminPrivileges.value,
}
: null;
}),
);
}

public getRouteLink(tab: AccountSettingsTabs): string {
return `/${ProjectLinks.URL_SETTINGS}/${tab}`;
}

public get isAdmin(): boolean {
return this.loggedUserService.isAdmin;
}

public adminSlideToggleChange(event: MatSlideToggleChange): void {
this.loggedUserService.emitAdminPrivilegesChanges(event.checked);
this.localStorageService.setAdminPriveleges(event.checked);
}

private extractActiveTabFromRoute(): void {
const categoryParam: MaybeUndefined<string> = this.route.snapshot.params[
ProjectLinks.URL_PARAM_CATEGORY
Expand Down
2 changes: 2 additions & 0 deletions src/app/common/app.values.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export default class AppValues {
public static readonly LOCAL_STORAGE_LOGIN_CALLBACK_URL = "login_callback_url";
public static readonly LOCAL_STORAGE_LOGIN_REDIRECT_URL = "login_redirect_url";
public static readonly LOCAL_STORAGE_ACCOUNT_ID = "account_id";
public static readonly LOCAL_STORAGE_ADMIN_PRIVILEGES = "admin_priveleges";

public static readonly SESSION_STORAGE_SIDE_PANEL_VISIBLE = "side_panel_visible";
public static readonly DEFAULT_USER_DISPLAY_NAME = "anonymous";
public static readonly DEFAULT_AVATAR_URL = "https://avatars.githubusercontent.com/u/11951648?v=4";
Expand Down
Loading
Loading