Skip to content

Commit

Permalink
Merge pull request #635 from energywebfoundation/verifiable_presentation
Browse files Browse the repository at this point in the history
Verifiable presentation
  • Loading branch information
whitneypurdum authored Apr 28, 2022
2 parents 2df2374 + f23671b commit bef7107
Show file tree
Hide file tree
Showing 37 changed files with 522 additions and 125 deletions.
164 changes: 54 additions & 110 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion src/app/routes/dashboard/dashboard.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export class DashboardComponent implements AfterViewInit {
.subscribe((redirectUrl) => {
this.store.dispatch(LayoutActions.setRedirectUrl({ url: redirectUrl }));
});

this.store.dispatch(AuthActions.reinitializeAuth());
}

Expand Down
1 change: 1 addition & 0 deletions src/app/routes/router-const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const RouterConst = {
SearchResult: 'search-result',
Enrol: 'enrol',
Welcome: 'welcome',
VerifiablePresentation: 'vp',

AssetEnrolment: '/assets/enrolment/',
MyEnrolments: '/enrolment?selectedTab=1',
Expand Down
7 changes: 7 additions & 0 deletions src/app/routes/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ export const routes = [
path: RouterConst.Enrol,
component: RequestClaimComponent,
},
{
path: RouterConst.VerifiablePresentation,
loadChildren: () =>
import('./verifiable-presentation/verifiable-presentation.module').then(
(m) => m.VerifiablePresentationModule
),
},
{
path: RouterConst.Welcome,
children: [
Expand Down
1 change: 0 additions & 1 deletion src/app/routes/search-result/search-result.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ export class SearchResultComponent implements OnInit {
);
this.filteredOptions.next(options);
});

this.activeRoute.queryParams.subscribe(async (queryParams: any) => {
// Get requested claims
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface IOOBPresentation {
type: string;
url: string;
ssiSession: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<app-vp-card>
<h4><strong>Prepare</strong> credentials for presentation</h4>
<div class="col-lg-12">
<mat-label class="ml-3 pl-1">Subject</mat-label>
<mat-form-field class="mt-2 md-enroll" appearance="outline">
<mat-select class="md-enroll" placeholder="Subject">
<mat-option class="md-enroll" [value]="'myself'">Myself</mat-option>
</mat-select>
</mat-form-field>
</div>
<mat-divider></mat-divider>
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container matColumnDef="select">
<th mat-header-cell *matHeaderCellDef>
<mat-checkbox
(change)="$event ? masterToggle() : null"
[checked]="selection.hasValue() && isAllSelected()"
[indeterminate]="selection.hasValue() && !isAllSelected()"
[aria-label]="checkboxLabel()">
</mat-checkbox>
</th>
<td mat-cell *matCellDef="let row">
<mat-checkbox
(click)="$event.stopPropagation()"
(change)="$event ? selection.toggle(row) : null"
[checked]="selection.isSelected(row)"
[aria-label]="checkboxLabel(row)">
</mat-checkbox>
</td>
</ng-container>
<ng-container matColumnDef="namespace">
<th mat-header-cell *matHeaderCellDef>Namespace</th>
<td mat-cell *matCellDef="let element">{{ element.namespace }}</td>
</ng-container>

<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef>Status</th>
<td mat-cell *matCellDef="let element">{{ element.status }}</td>
</ng-container>

<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
<app-report-problem class="mt-3 d-block" *ngIf="!isAllSelected()">
All requested credentials must be selected in order to get successfull verification.
</app-report-problem>
<div class="mt-3">
<button
mat-raised-button
data-qa-id="submit-request"
class="btn btn-primary md-enroll w-100"
type="submit"
[disabled]="!isAllSelected()">
Submit Request
</button>
</div>
</app-vp-card>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { PresentationCredentialsComponent } from './presentation-credentials.component';

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

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [PresentationCredentialsComponent],
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(PresentationCredentialsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Component } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
import { SelectionModel } from '@angular/cdk/collections';

@Component({
selector: 'app-presentation-credentials',
templateUrl: './presentation-credentials.component.html',
styleUrls: ['./presentation-credentials.component.scss'],
})
export class PresentationCredentialsComponent {
displayedColumns: string[] = ['select', 'namespace', 'status'];
dataSource = new MatTableDataSource([
{ namespace: 'installer', status: 'Approved' },
{ namespace: 'installer2', status: 'Approved' },
]);

selection = new SelectionModel(true, []);

/** Whether the number of selected elements matches the total number of rows. */
isAllSelected() {
const numSelected = this.selection.selected.length;
const numRows = this.dataSource.data.length;
return numSelected === numRows;
}

/** Selects all rows if they are not all selected; otherwise clear selection. */
masterToggle() {
if (this.isAllSelected()) {
this.selection.clear();
return;
}

this.selection.select(...this.dataSource.data);
}

/** The label for the checkbox on the passed row */
checkboxLabel(row?): string {
if (!row) {
return `${this.isAllSelected() ? 'deselect' : 'select'} all`;
}
return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${
row.position + 1
}`;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<app-vp-card>
<h4><strong>Received</strong> presentation request</h4>
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container matColumnDef="namespace">
<th mat-header-cell *matHeaderCellDef>Namespace</th>
<td mat-cell *matCellDef="let element">{{ element.namespace }}</td>
</ng-container>

<ng-container matColumnDef="reason">
<th mat-header-cell *matHeaderCellDef>Reason</th>
<td mat-cell *matCellDef="let element">{{ element.reason }}</td>
</ng-container>

<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</app-vp-card>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
:host ::ng-deep {
th.mat-header-cell {
background: transparent !important;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ReceivedPresentationsComponent } from './received-presentations.component';

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

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ReceivedPresentationsComponent],
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(ReceivedPresentationsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Component } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
@Component({
selector: 'app-received-presentations',
templateUrl: './received-presentations.component.html',
styleUrls: ['./received-presentations.component.scss'],
})
export class ReceivedPresentationsComponent {
displayedColumns: string[] = ['namespace', 'reason'];
dataSource = new MatTableDataSource([
{ namespace: 'installer', reason: 'asdf dsa' },
{ namespace: 'installer2', reason: 'Some other reason' },
]);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { VerifiablePresentationComponent } from './verifiable-presentation/verifiable-presentation.component';
import { RouterModule } from '@angular/router';
import { VpHeaderComponent } from './vp-header/vp-header.component';
import { ReceivedPresentationsComponent } from './received-presentations/received-presentations.component';
import { SharedModule } from '../../shared/shared.module';
import { PresentationCredentialsComponent } from './presentation-credentials/presentation-credentials.component';
import { VpCardComponent } from './vp-card/vp-card.component';
import { LayoutModule } from '../../layout/layout.module';
@NgModule({
declarations: [
VerifiablePresentationComponent,
VpHeaderComponent,
ReceivedPresentationsComponent,
PresentationCredentialsComponent,
VpCardComponent,
],
imports: [
CommonModule,
SharedModule,
LayoutModule,
RouterModule.forChild([
{ path: '', component: VerifiablePresentationComponent },
]),
],
})
export class VerifiablePresentationModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<div class="color-default d-flex justify-content-center flex-column align-items-center w-100">
<app-vp-header></app-vp-header>
<app-received-presentations></app-received-presentations>
<app-presentation-credentials></app-presentation-credentials>
<app-loading></app-loading>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { VerifiablePresentationComponent } from './verifiable-presentation.component';

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

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [VerifiablePresentationComponent],
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(VerifiablePresentationComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

xit('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { IamService } from '../../../shared/services/iam.service';
import { LoadingService } from '../../../shared/services/loading.service';
import { ConnectToWalletDialogComponent } from '../../../modules/connect-to-wallet/connect-to-wallet-dialog/connect-to-wallet-dialog.component';
import { LoginService } from 'src/app/shared/services/login/login.service';
import { AuthActions } from '@state';
import { Store } from '@ngrx/store';
import { filter, take } from 'rxjs/operators';
import { MatDialog } from '@angular/material/dialog';
import { isUserLoggedIn } from '../../../state/auth/auth.selectors';
@Component({
selector: 'app-verifiable-presentation',
templateUrl: './verifiable-presentation.component.html',
styleUrls: ['./verifiable-presentation.component.scss'],
})
export class VerifiablePresentationComponent implements OnInit {
oob$: Observable<string>;
public isLoggedIn = false;
constructor(
private route: ActivatedRoute,
private loadingService: LoadingService,
private loginService: LoginService,
private store: Store,
public dialog: MatDialog,
private iamService: IamService
) {}
isAutolistLoading = {
requests: [],
value: false,
};
ngOnInit(): void {
this._initSearch();
}
private _initSearch() {
this.route.queryParams.subscribe(async (params: any) => {
//this.loadingService.show()
await this.initLoginUser();
if (params._oob) {
const paramsDecoded = atob(params._oob);
const parsedToObj = JSON.parse(paramsDecoded);
const { url } = parsedToObj;
console.log(url);
/*
TO DO: Call ICL when persistence of pres def is implemented:
try {
await this.iamService.verifiableCredentialsService.initiateExchange({type: 'https://energyweb.org/out-of-band-invitation/vc-api-exchange', url: url})
this.loadingService.hide();
} catch (e) {
console.log(e)
} finally {
this.loadingService.hide();
}
*/
}
});
}
private async initLoginUser() {
// Check Login
if (this.loginService.isSessionActive()) {
this.store.dispatch(AuthActions.reinitializeAuthForEnrol());
// Set Loggedin Flag to true
this.isLoggedIn = await this.store
.select(isUserLoggedIn)
.pipe(filter<boolean>(Boolean), take(1))
.toPromise();
} else {
this.loadingService.hide();
// Launch Login Dialog
await this.dialog
.open(ConnectToWalletDialogComponent, {
width: '434px',
panelClass: 'connect-to-wallet',
maxWidth: '100%',
disableClose: true,
})
.afterClosed()
.toPromise();

// Set Loggedin Flag to true
this.isLoggedIn = true;
this.loadingService.show();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<mat-card class="card-enroll color-default pt-4 pl-4 pr-4">
<ng-content></ng-content>
</mat-card>
Empty file.
Loading

0 comments on commit bef7107

Please sign in to comment.