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

Fix issue with next button observable used in selectable attributes form #75

Merged
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
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());
}

}
Loading