Skip to content

Commit

Permalink
Feat: Add dark design (#54)
Browse files Browse the repository at this point in the history
* feat: add dark design choice

Signed-off-by: Mirko Mollik <[email protected]>

* Feat/extension (#47)

* fix: set correct docker image names

Signed-off-by: Mirko Mollik <[email protected]>

* fix: extension

Signed-off-by: Mirko Mollik <[email protected]>

---------

Signed-off-by: Mirko Mollik <[email protected]>

* fix: extension

Signed-off-by: Mirko Mollik <[email protected]>

* fix: readme

Signed-off-by: Mustafa Alsalfiti <[email protected]>

* fix: holder-app test

Signed-off-by: Mustafa Alsalfiti <[email protected]>

* remove comment from theme file

Signed-off-by: Mirko Mollik <[email protected]>

* fix: remove warnings from ci build

Signed-off-by: Mirko Mollik <[email protected]>

* fix: verifier build

Signed-off-by: Mirko Mollik <[email protected]>

---------

Signed-off-by: Mirko Mollik <[email protected]>
Signed-off-by: Mirko Mollik <[email protected]>
Signed-off-by: Mustafa Alsalfiti <[email protected]>
Co-authored-by: Mirko Mollik <[email protected]>
Co-authored-by: Mirko Mollik <[email protected]>
  • Loading branch information
3 people authored Jun 3, 2024
1 parent ed4a788 commit d2fd65c
Show file tree
Hide file tree
Showing 45 changed files with 227 additions and 189 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
CredHub is comprehensive monorepo including a cloud wallet for natural persons together with a minimal issuer and verifier service. The cloud wallet will host all credentials and key pairs, including the business logic to receive and present credentials.

# Why a cloud wallet
A cloud wallet is able to move the whole complexity of the SSI algorithms to the server side, so the clients only need to render the data. This makes the development of new clients or integration into existing applications much easier. It also provides an equal security level for all users amd does not exclude any smartphones because of their hardware capabilities. Besides it allows the user to access his credentials from multiple devices without the need to sync them.
A cloud wallet is able to move the whole complexity of the SSI algorithms to the server side, so the clients only need to render the data. This makes the development of new clients or integration into existing applications much easier. It also provides an equal security level for all users and does not exclude any smartphones because of their hardware capabilities. Besides that it allows the user to access his credentials from multiple devices without the need to sync them.

Of course the user is loosing offline capabilities and has to trust the server to not misuse personal data. But this is a tradeoff that can be acceptable for many use cases when you want to start with verifiable credentials with great user experience and low development effort.
Of course the user is losing offline capabilities and has to trust the server to not misuse personal data. But this is a tradeoff that can be acceptable for many use cases when you want to start with verifiable credentials with great user experience and low development effort.

# Tech Stack
- Programming language: Typescript, Node >= v18
Expand Down
12 changes: 5 additions & 7 deletions apps/holder-app/src/app/app.component.scss
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
.mat-toolbar {
background-color: #D7E3FF;
.mat-toolbar{
padding: 10px 40px;
height: 84px;
position: fixed;
bottom: 0px;
}

.info {
font-size: 14px;
}

.content {
height: calc(100vh - 84px);
overflow: auto;
width: 100%;
padding-bottom: 84px;
}

.info {
font-size: 14px;
}
5 changes: 4 additions & 1 deletion apps/holder-app/src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ import { AppComponent } from './app.component';
import { CheckForUpdatesService } from './check-for-updates.service';
import { SwUpdate } from '@angular/service-worker';
import { of } from 'rxjs';
import { SettingsService } from '@my-wallet/holder-shared';
import { HttpClientModule } from '@angular/common/http';

describe('AppComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
let checkForUpdatesService: CheckForUpdatesService;
let settingsService: SettingsService;

beforeAll(() => {
Object.defineProperty(window, 'matchMedia', {
Expand All @@ -24,7 +27,7 @@ describe('AppComponent', () => {

beforeEach(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule, AppComponent],
imports: [RouterTestingModule, AppComponent, HttpClientModule],
providers: [
CheckForUpdatesService,
{ provide: SwUpdate, useValue: { available: of() } }, // Mock SwUpdate
Expand Down
13 changes: 10 additions & 3 deletions apps/holder-app/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';
import { MatToolbarModule } from '@angular/material/toolbar';
Expand All @@ -7,6 +7,7 @@ import { FlexLayoutModule } from 'ng-flex-layout';
import { MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon';
import { CheckForUpdatesService } from './check-for-updates.service';
import { SettingsService } from '@my-wallet/holder-shared';

@Component({
selector: 'app-root',
Expand All @@ -26,6 +27,12 @@ import { CheckForUpdatesService } from './check-for-updates.service';
templateUrl: './app.component.html',
styleUrl: './app.component.scss',
})
export class AppComponent {
constructor(private checkForUpdatesService: CheckForUpdatesService) {}
export class AppComponent implements OnInit {
constructor(
private checkForUpdatesService: CheckForUpdatesService,
private settingsService: SettingsService
) {}
async ngOnInit(): Promise<void> {
this.settingsService.setThemeToApplication();
}
}
2 changes: 1 addition & 1 deletion apps/holder-app/src/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
ApiModule,
Configuration,
AuthServiceInterface,
} from '@my-wallet/-holder-shared';
} from '@my-wallet/holder-shared';
import { AuthService } from './auth/auth.service';
import { provideServiceWorker } from '@angular/service-worker';

Expand Down
2 changes: 1 addition & 1 deletion apps/holder-app/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
HistoryListComponent,
HistoryShowComponent,
SettingsComponent,
} from '@my-wallet/-holder-shared';
} from '@my-wallet/holder-shared';

export const routes: Routes = [
{
Expand Down
7 changes: 6 additions & 1 deletion apps/holder-app/src/app/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { OAuthService } from 'angular-oauth2-oidc';
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
import { filter, map } from 'rxjs/operators';
import { authConfig } from '../authConfig';
import { AuthServiceInterface } from '@my-wallet/-holder-shared';
import { AuthServiceInterface } from '@my-wallet/holder-shared';
import { environment } from '../../environments/environment';

@Injectable({ providedIn: 'root' })
export class AuthService implements AuthServiceInterface {
Expand Down Expand Up @@ -40,6 +41,10 @@ export class AuthService implements AuthServiceInterface {
this.init();
}

getSettingsLink(): string {
return `${environment.keycloakHost}/realms/${environment.keycloakRealm}/account`;
}

private init() {
// Useful for debugging:
// this.oauthService.events.subscribe((event) => {
Expand Down
2 changes: 1 addition & 1 deletion apps/holder-app/src/app/scanner/scanner.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { CommonModule } from '@angular/common';
import {
VerifyRequestComponent,
IssuanceRequestComponent,
} from '@my-wallet/-holder-shared';
} from '@my-wallet/holder-shared';
import { MatDividerModule } from '@angular/material/divider';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { FlexLayoutModule } from 'ng-flex-layout';
Expand Down
4 changes: 2 additions & 2 deletions apps/holder-app/src/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
Expand All @@ -16,7 +16,7 @@
<meta name="theme-color" content="#D7E3FF" />
<script src="assets/config/config.js"></script>
</head>
<body>
<body class="mat-app-background">
<app-root></app-root>
<noscript
>Please enable JavaScript to continue using this application.</noscript
Expand Down
1 change: 0 additions & 1 deletion apps/holder-app/src/styles.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/* You can add global styles to this file, and also import other style files */

body {
font-family: 'Roboto', sans-serif;
margin: 0;
Expand Down
32 changes: 25 additions & 7 deletions apps/holder-app/src/theme.scss
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
@use '@angular/material' as mat;
@use '@angular/material-experimental' as matx;
@import '@angular/cdk/overlay-prebuilt.css';
@include mat.core();

$theme: mat.define-theme((
$light-theme: mat.define-theme((
color: (
theme-type: light,
primary: mat.$azure-palette,
tertiary: mat.$blue-palette,
),
typography: (
brand-family: '"Roboto", sans-serif',
Expand All @@ -17,9 +16,28 @@ $theme: mat.define-theme((
)
));

@include mat.core();
@include mat.color-variants-backwards-compatibility($theme);
$dark-theme: mat.define-theme((
color: (
theme-type: dark,
primary: mat.$orange-palette,
),
));

@mixin background($theme) {
.mat-toolbar {
@if mat.get-theme-type($theme) == dark {
background: mat.get-theme-color($theme, primary, 10);
} @else {
background: mat.get-theme-color($theme, primary, 90);
}
}
}

:root {
@include mat.all-component-themes($theme);
html {
@include mat.all-component-themes($light-theme);
@include background($light-theme);
.dark-theme {
@include mat.all-component-colors($dark-theme);
@include background($dark-theme);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { Column, Entity, PrimaryColumn, PrimaryGeneratedColumn } from 'typeorm';
import { ApiHideProperty } from '@nestjs/swagger';
import { Column, Entity, PrimaryColumn } from 'typeorm';

@Entity()
export class Setting {
/**
* The user that owns the key
*/
@ApiHideProperty()
@PrimaryColumn()
user: string;

@Column({ default: false })
auto: boolean;

@Column({ default: false })
darkTheme: boolean;
}
9 changes: 8 additions & 1 deletion apps/holder-browser-extension/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,14 @@
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
"namedChunks": true,
"watch": true,
"fileReplacements": [
{
"replace": "apps/holder-browser-extension/src/environments/environment.ts",
"with": "apps/holder-browser-extension/src/environments/environment.development.ts"
}
]
}
},
"defaultConfiguration": "production"
Expand Down
2 changes: 0 additions & 2 deletions apps/holder-browser-extension/src/app/app.component.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
.mat-toolbar {
background-color: #D7E3FF;
padding: 10px 40px;
height: 84px;
position: fixed;
Expand All @@ -10,7 +9,6 @@
height: calc(100vh - 84px);
overflow: auto;
width: 100%;
padding-bottom: 84px;
}


Expand Down
1 change: 1 addition & 0 deletions apps/holder-browser-extension/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { FlexLayoutModule } from 'ng-flex-layout';
import { MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon';
import { AuthService } from './auth/auth.service';
import { SettingsService } from '@my-wallet/holder-shared';

@Component({
selector: 'app-root',
Expand Down
33 changes: 14 additions & 19 deletions apps/holder-browser-extension/src/app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type ApplicationConfig, importProvidersFrom } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import {} from '@angular/common/http';
import { provideHttpClient } from '@angular/common/http';
import { provideAnimations } from '@angular/platform-browser/animations';
import { MAT_DIALOG_DEFAULT_OPTIONS } from '@angular/material/dialog';
import { provideOAuthClient } from 'angular-oauth2-oidc';
Expand All @@ -10,31 +10,16 @@ import {
ApiModule,
Configuration,
AuthServiceInterface,
} from '@my-wallet/-holder-shared';
} from '@my-wallet/holder-shared';
import { AuthService } from './auth/auth.service';
import { HashLocationStrategy, LocationStrategy } from '@angular/common';

// eslint-disable-next-line @typescript-eslint/no-namespace
export declare namespace globalThis {
let token: string;
}

function getConfiguration() {
return new Configuration({
//TODO: the basepath is static, therefore we can not set it during the login process.
basePath: environment.backendUrl,
credentials: {
// we fetch the token via globalThis since we can not access it via the chrome.storage API since it's async.
oauth2: () => globalThis.token,
},
});
}

export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
{ provide: LocationStrategy, useClass: HashLocationStrategy },
provideAnimations(),
provideHttpClient(),
provideOAuthClient(),
importProvidersFrom(ApiModule),
{ provide: MAT_DIALOG_DEFAULT_OPTIONS, useValue: { hasBackdrop: true } },
Expand All @@ -43,8 +28,18 @@ export const appConfig: ApplicationConfig = {
useClass: AuthService,
},
{
//TODO: maybe instead of a factory, we can use a class where we inject a provider to fetch the token.
provide: Configuration,
useFactory: getConfiguration,
useFactory: (authService: AuthService) =>
new Configuration({
//TODO: the basepath is static, therefore we can not set it during the login process.
basePath: environment.backendUrl,
credentials: {
oauth2: authService.getToken.bind(authService),
},
}),
deps: [AuthService],
multi: false,
},
],
};
2 changes: 1 addition & 1 deletion apps/holder-browser-extension/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
HistoryListComponent,
HistoryShowComponent,
SettingsComponent,
} from '@my-wallet/-holder-shared';
} from '@my-wallet/holder-shared';
export const routes: Routes = [
{
path: '',
Expand Down
11 changes: 5 additions & 6 deletions apps/holder-browser-extension/src/app/auth/auth.guard.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { inject } from '@angular/core';
import { CanActivateFn } from '@angular/router';
import { AuthService } from './auth.service';

// eslint-disable-next-line @typescript-eslint/no-namespace
export declare namespace globalThis {
let token: string;
}
import { SettingsService } from '@my-wallet/holder-shared';

export const authGuard: CanActivateFn = async () => {
const authService: AuthService = inject(AuthService);
const settingsService = inject(SettingsService);
return authService
.isAuthenticated()
.then(async () => {
globalThis.token = await authService.getToken();
await authService.setToken();
//set the theme here. We can not do this in the app.component because it gets loaded before the login process is finished.
settingsService.setThemeToApplication();
return true;
})
.catch(() => {
Expand Down
Loading

0 comments on commit d2fd65c

Please sign in to comment.