Skip to content

Commit

Permalink
Fix issue with next button observable used in selectable attributes f…
Browse files Browse the repository at this point in the history
…orm. (#75)

Co-authored-by: Vafeiadis Nikos <[email protected]>
  • Loading branch information
vafeini and vafeini authored Jul 22, 2024
1 parent 6261240 commit 5674982
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 118 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { Subject } from 'rxjs';
import { takeUntil, filter } from 'rxjs/operators';
import { PresentationDefinitionResponse } from '@core/models/presentation-definition-response';
import { DataService } from '@app/core/services/data.service';
Expand All @@ -21,7 +21,6 @@ export class HomeComponent implements OnInit, OnDestroy {
destroy$ = new Subject();
actions: BodyAction[] = PRESENTATION_ACTIONS;
requestCode = '';
presentationDefinition$!: Observable<PresentationDefinitionResponse>;
constructor (
private readonly changeDetectorRef: ChangeDetectorRef,
private readonly router: Router,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { filter } from 'rxjs/operators';
import { CBOR_ACTIONS } from '@app/core/utils/pages-actions';
import { ActionCode } from '@app/shared/elements/body-actions/models/ActionCode';
import { BodyAction } from '@app/shared/elements/body-actions/models/BodyAction';
import { HelperCborSelectableService } from '../../services/helper-cbor-selectable.service';
import { SelectableFormNextAction } from '../../services/selectable-form-next-action.service';
import { NavigateService } from '@app/core/services/navigate.service';

@Component({
Expand All @@ -16,7 +16,7 @@ export class HomeComponent implements OnInit {
actions: BodyAction[] = CBOR_ACTIONS;
isCreatePage = true;
constructor (
private readonly helperCborSelectableService: HelperCborSelectableService,
private readonly selectableFormNextAction: SelectableFormNextAction,
private readonly navigateService: NavigateService,
private readonly router: Router
) {}
Expand All @@ -26,7 +26,7 @@ export class HomeComponent implements OnInit {
filter((event): event is NavigationEnd => event instanceof NavigationEnd)
)
.subscribe((event) => {
this.isCreatePage = event.url.includes('verifiable') ? false : true;
this.isCreatePage = !event.url.includes('verifiable');
if (this.isCreatePage) {
this.actions = CBOR_ACTIONS;
}
Expand All @@ -35,8 +35,10 @@ export class HomeComponent implements OnInit {

runActions (data: BodyAction) {
if (data.code === ActionCode.NEXT) {
this.helperCborSelectableService.goNextStep$.next('go next');
this.selectableFormNextAction.next('go next');
this.actions = this.actions.filter((item) => item.code !== ActionCode.NEXT);
// Clear subscriptions to 'next step' observable
this.selectableFormNextAction.clear();
} else if(data.code === ActionCode.BACK) {
this.navigateService.goBack();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { RouterModule } from '@angular/router';
import { SharedModule } from '@app/shared/shared.module';
import { SelectablePresentationFormComponent } from './selectable-presentation-form.component';
import { HttpClientModule } from '@angular/common/http';
import { HelperCborSelectableService } from '../../services/helper-cbor-selectable.service';
import { SelectableFormNextAction } from '../../services/selectable-form-next-action.service';
import { MatExpansionModule } from '@angular/material/expansion';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatCheckboxModule } from '@angular/material/checkbox';
Expand All @@ -28,7 +28,7 @@ describe('CBOR CreateAScenarioComponent', () => {
],
declarations: [ SelectablePresentationFormComponent ],
providers: [
HelperCborSelectableService
SelectableFormNextAction
]
})
.compileComponents();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,137 +1,136 @@
import { Component, OnInit, ChangeDetectorRef, Injector } from '@angular/core';
import { catchError } from 'rxjs';
import { PresentationDefinitionResponse } from '@core/models/presentation-definition-response';
import { PresentationDefinitionService } from '@app/core/services/presentation-definition.service';
import { FieldConstraint } from '../../models/FieldConstraint';
import { DataService } from '@app/core/services/data.service';
import { NavigateService } from '@app/core/services/navigate.service';
import { FormSelectableField } from '@features/selectable-presentation/models/FormSelectableField';
import { HelperCborSelectableService } from '../../services/helper-cbor-selectable.service';
import { LocalStorageService } from '@app/core/services/local-storage.service';
import {ChangeDetectorRef, Component, Injector, OnInit} from '@angular/core';
import {catchError} from 'rxjs';
import {PresentationDefinitionResponse} from '@core/models/presentation-definition-response';
import {PresentationDefinitionService} from '@app/core/services/presentation-definition.service';
import {FieldConstraint} from '../../models/FieldConstraint';
import {DataService} from '@app/core/services/data.service';
import {NavigateService} from '@app/core/services/navigate.service';
import {FormSelectableField} from '@features/selectable-presentation/models/FormSelectableField';
import {SelectableFormNextAction} from '../../services/selectable-form-next-action.service';
import {LocalStorageService} from '@app/core/services/local-storage.service';
import * as constants from '@core/constants/constants';
import { Modification } from '@app/shared/elements/body-actions/models/modification';
import { BodyActionsService } from '@app/shared/elements/body-actions/body-actions.service';
import { Presentation } from '../../models/Presentation';
import { AttestationSelectableModelService } from "@app/core/services/attestation-selectable-model.service";
import { MsoMdocPresentationService } from "@app/core/services/mso-mdoc-presentation.service";
import { MsoMdoc } from "@core/models/msoMdoc";
import {Modification} from '@app/shared/elements/body-actions/models/modification';
import {BodyActionsService} from '@app/shared/elements/body-actions/body-actions.service';
import {Presentation} from '../../models/Presentation';
import {AttestationSelectableModelService} from "@app/core/services/attestation-selectable-model.service";
import {MsoMdocPresentationService} from "@app/core/services/mso-mdoc-presentation.service";
import {MsoMdoc} from "@core/models/msoMdoc";

@Component({
selector: 'vc-create-a-scenario',
templateUrl: './selectable-presentation-form.component.html',
styleUrls: ['./selectable-presentation-form.component.scss'],
providers: [PresentationDefinitionService]
selector: 'vc-create-a-scenario',
templateUrl: './selectable-presentation-form.component.html',
styleUrls: ['./selectable-presentation-form.component.scss'],
providers: [PresentationDefinitionService]
})
export class SelectablePresentationFormComponent implements OnInit {

formFields!: FormSelectableField[];
requestGenerate = false;
buttonMode = 'none';
formFields!: FormSelectableField[];
buttonMode = 'none';
attestationModel!: MsoMdoc;
draftPresentation!: Presentation;
presentationDefinitionText!: string;
selectedFields: FieldConstraint[] = [];
private readonly navigateService!: NavigateService;
private readonly helperCborSelectableService!: HelperCborSelectableService;
private readonly localStorageService!: LocalStorageService;
private readonly bodyActionsService!: BodyActionsService;
constructor (
draftPresentation!: Presentation;
presentationDefinitionText!: string;
selectedFields: FieldConstraint[] = [];
private readonly navigateService!: NavigateService;
private readonly localStorageService!: LocalStorageService;
private readonly bodyActionsService!: BodyActionsService;

constructor(
private readonly selectableFormNextAction: SelectableFormNextAction,
private readonly presentationDefinitionService: PresentationDefinitionService,
private readonly attestationSelectableModelService: AttestationSelectableModelService,
private readonly msoMdocPresentationService: MsoMdocPresentationService,
private readonly dataService: DataService,
private readonly changeDetectorRef: ChangeDetectorRef,
private readonly injector: Injector,
) {
this.navigateService = this.injector.get(NavigateService);
this.helperCborSelectableService = this.injector.get(HelperCborSelectableService);
this.localStorageService = this.injector.get(LocalStorageService);
this.bodyActionsService = this.injector.get(BodyActionsService);
) {
this.navigateService = this.injector.get(NavigateService);
this.localStorageService = this.injector.get(LocalStorageService);
this.bodyActionsService = this.injector.get(BodyActionsService);

this.enableNextButton();
}
}

ngOnInit (): void {
this.localStorageService.remove(constants.UI_PRESENTATION);
ngOnInit(): void {
this.localStorageService.remove(constants.UI_PRESENTATION);
this.initPresentationModel();
// Init form from model
this.formFields = this.extractFormFieldsFromModel()
this.helperCborSelectableService.goNextStep$.subscribe(_ => {
this.generateCode();
});
}
this.selectableFormNextAction.subscribe(_ => {
this.generateCode();
});
}

initPresentationModel() {
this.attestationModel = this.attestationSelectableModelService.getModel();
const presentationPurpose = this.attestationSelectableModelService.getPresentationPurpose();
this.draftPresentation = this.msoMdocPresentationService.presentationOf(this.attestationModel, presentationPurpose, [])
}

generateCode () {
this.requestGenerate = true;
if (this.convertJSONtoString(this.draftPresentation)) {
this.buttonMode = 'loading';
this.presentationDefinitionService.generateCode(this.convertJSONtoString(this.draftPresentation))
.pipe(
catchError((error) => {
return error;
})
)
.subscribe((data) => {
this.buttonMode = 'none';
this.requestGenerate = false;
this.dataService.setQRCode(data as PresentationDefinitionResponse);
this.navigateService.navigateTo('/cbor-selectable/verifiable');
this.changeDetectorRef.detectChanges();
});
} else {
console.log('invalid JSON');
}
}
handle (data: FormSelectableField) {
const value = data?.value;
if (!this.isExist(value.path[0])) {
this.selectedFields.push(value);
} else if (this.isExist(value.path[0])) {
this.selectedFields = this.selectedFields.filter((item: FieldConstraint) => {
return String(item.path) !== String(value.path[0]);
});
}
generateCode() {
if (this.convertJSONtoString(this.draftPresentation)) {
this.buttonMode = 'loading';
this.presentationDefinitionService.generateCode(this.convertJSONtoString(this.draftPresentation))
.pipe(
catchError((error) => {
return error;
})
)
.subscribe((data) => {
this.buttonMode = 'none';
this.dataService.setQRCode(data as PresentationDefinitionResponse);
this.navigateService.navigateTo('/cbor-selectable/verifiable');
this.changeDetectorRef.detectChanges();
});
} else {
console.log('invalid JSON');
}
}

handle(data: FormSelectableField) {
const value = data?.value;
if (!this.isExist(value.path[0])) {
this.selectedFields.push(value);
} else if (this.isExist(value.path[0])) {
this.selectedFields = this.selectedFields.filter((item: FieldConstraint) => {
return String(item.path) !== String(value.path[0]);
});
}
// Update draft presentation with selected fields
this.draftPresentation.presentation_definition.input_descriptors[0].constraints.fields = this.selectedFields;
this.draftPresentation.presentation_definition.input_descriptors[0].constraints.fields = this.selectedFields;
// refresh PD text from model
this.presentationDefinitionText = this.convertJSONtoString(this.draftPresentation.presentation_definition);
this.enableNextButton();
this.changeDetectorRef.detectChanges();
}
this.presentationDefinitionText = this.convertJSONtoString(this.draftPresentation.presentation_definition);
this.enableNextButton();
this.changeDetectorRef.detectChanges();
}

convertJSONtoString (obj: object) {
return JSON.stringify(obj, null, '\t');
}
convertJSONtoString(obj: object) {
return JSON.stringify(obj, null, '\t');
}

isExist (path: string) {
const exists = this.selectedFields.filter((item) => item.path.includes(path));
return exists.length > 0;
}
isExist(path: string) {
const exists = this.selectedFields.filter((item) => item.path.includes(path));
return exists.length > 0;
}

enableNextButton () {
const modifyData: Modification = {
id: 'next_button',
disabled: this.selectedFields == undefined || this.selectedFields.length === 0
};
this.bodyActionsService.handelButton$.next(modifyData);
}
enableNextButton() {
const modifyData: Modification = {
id: 'next_button',
disabled: this.selectedFields == undefined || this.selectedFields.length === 0
};
this.bodyActionsService.handelButton$.next(modifyData);
}

extractFormFieldsFromModel(): FormSelectableField[] {
return this.attestationModel.attributes.map( (attr, index) => {
return this.attestationModel.attributes.map((attr, index) => {
return {
id: index,
label: attr.text,
value: this.msoMdocPresentationService.fieldConstraint(this.attestationModel, attr.value)
}
})
}
trackByFn (_index: number, data: FormSelectableField) {
return data.id;
}

trackByFn(_index: number, data: FormSelectableField) {
return data.id;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { SelectablePresentationFormComponent } from '@features/selectable-presen
import { HomeComponent } from './components/home/home.component';
import { SharedModule } from '@app/shared/shared.module';
import { WalletLayoutComponent } from '@app/core/layout/wallet-layout/wallet-layout.component';
import { HelperCborSelectableService } from './services/helper-cbor-selectable.service';
import { SelectableFormNextAction } from './services/selectable-form-next-action.service';


@NgModule({
Expand All @@ -29,7 +29,7 @@ import { HelperCborSelectableService } from './services/helper-cbor-selectable.s
MatCheckboxModule,
],
providers: [
HelperCborSelectableService
SelectableFormNextAction
]
})
export class SelectablePresentationModule { }

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { TestBed } from '@angular/core/testing';

import { HelperCborSelectableService } from './helper-cbor-selectable.service';
import { SelectableFormNextAction } from './selectable-form-next-action.service';

describe('HelperCborSelectableService', () => {
let service: HelperCborSelectableService;
let service: SelectableFormNextAction;

beforeEach(() => {
TestBed.configureTestingModule({
providers: [HelperCborSelectableService]
providers: [SelectableFormNextAction]
});
service = TestBed.inject(HelperCborSelectableService);
service = TestBed.inject(SelectableFormNextAction);
});

it('should be created', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Injectable } from '@angular/core';
import {Subject, Subscription} from 'rxjs';

@Injectable()
export class SelectableFormNextAction {

/**
* Next button subject that holds the action to be executed when next button is clicked
*/
private goNextStep$: Subject<string> = new Subject();

/**
* An array to hold our subscriptions
*/
private subscriptions$: Array<Subscription> = new Array<Subscription>()

subscribe(observerOrNext: (value: string) => void) {
this.subscriptions$.push(
this.goNextStep$.subscribe(observerOrNext)
)
}

next(goNext: string) {
this.goNextStep$.next(goNext)
}

/**
* Unsubscribes all subscriptions of goNextStep$ Subject
*/
clear() {
this.subscriptions$.forEach(subscription => subscription.unsubscribe());
}

}

0 comments on commit 5674982

Please sign in to comment.