Skip to content

Commit

Permalink
Added navigation over stages of SetPollingSource editing wizard (#110)
Browse files Browse the repository at this point in the history
* Add navigator.
* Remove material warning.
* Add descriptions for steps.
* Added validation when the user moves to the next step.
* Increase unit tests coverage
  • Loading branch information
dmitriy-borzenko authored Jul 24, 2023
1 parent 3a6d937 commit b18816f
Show file tree
Hide file tree
Showing 16 changed files with 246 additions and 90 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The ability to edit SetPollingSource event
- Editing SetWaterMark event
- Editing SetTransform event
- Support defining initial polling source information for the root datasets interactively (SetPollingSource event):
- Prepare step(optional)
- Preprocess step(optional)
- Create a navigator to display the state of the interactive input for the SetPollingSource event

## [0.6.0] - 2023-02-27

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,93 +2,139 @@
<div class="mt-4">
<div class="border border-1 mt-4 px-2 py-4 rounded-3">
<form [formGroup]="pollingSourceForm">
<ng-container *ngIf="currentStep === steps.FETCH">
<app-base-step
[sectionStepRadioData]="FETCH_STEP_RADIO_DATA"
[sectionFormData]="FETCH_FORM_DATA"
[defaultKind]="FETCH_DEFAULT_KIND"
[sectionName]="steps.FETCH"
[eventYamlByHash]="eventYamlByHash"
eventHistory
></app-base-step>
<app-stepper-navigation
[prevStep]="null"
[nextStep]="steps.PREPARE"
[validStep]="fetchForm.valid"
(changeStepEmitter)="changeStep($event)"
></app-stepper-navigation>
</ng-container>
<ng-container *ngIf="currentStep === steps.PREPARE">
<app-prepare-step
[eventYamlByHash]="eventYamlByHash"
[sectionName]="steps.PREPARE"
></app-prepare-step>
<app-stepper-navigation
[prevStep]="steps.FETCH"
[nextStep]="steps.READ"
[validStep]="prepareForm.valid"
(changeStepEmitter)="changeStep($event)"
></app-stepper-navigation>
</ng-container>

<ng-container *ngIf="currentStep === steps.READ">
<app-base-step
[sectionStepRadioData]="READ_STEP_RADIO_DATA"
[sectionFormData]="READ_FORM_DATA"
[defaultKind]="READ_DEFAULT_KIND"
[sectionName]="steps.READ"
[eventYamlByHash]="eventYamlByHash"
></app-base-step>
<app-stepper-navigation
[prevStep]="steps.PREPARE"
[nextStep]="steps.PREPROCESS"
[validStep]="readForm.valid"
(changeStepEmitter)="changeStep($event)"
></app-stepper-navigation>
</ng-container>
<ng-container *ngIf="currentStep === steps.PREPROCESS">
<app-preprocess-step
[eventYamlByHash]="eventYamlByHash"
[preprocessValue]="preprocessStepValue"
[showPreprocessStep]="showPreprocessStep"
(showPreprocessStepEmitter)="
onShowPreprcessStep($event)
"
></app-preprocess-step>
<app-stepper-navigation
[prevStep]="steps.READ"
[nextStep]="steps.MERGE"
[validStep]="fetchForm.valid"
(changeStepEmitter)="changeStep($event)"
></app-stepper-navigation>
</ng-container>
<ng-container *ngIf="currentStep === steps.MERGE">
<app-base-step
[sectionStepRadioData]="MERGE_STEP_RADIO_DATA"
[sectionFormData]="MERGE_FORM_DATA"
[defaultKind]="MERGE_DEFAULT_KIND"
[sectionName]="steps.MERGE"
[eventYamlByHash]="eventYamlByHash"
<mat-stepper #stepper>
<mat-step
[stepControl]="fetchForm"
errorMessage="Field is required"
>
<div
*ngIf="errorMessage"
class="alert alert-danger mt-2"
role="alert"
<ng-template matStepLabel>
<div
class="stepper-header-overlay"
(click)="onShowErrors()"
></div>
Fetch</ng-template
>
<p class="text-danger fs-6">
Error:<br />{{ errorMessage }}
</p>
</div></app-base-step
<div class="container-step">
<app-base-step
[sectionStepRadioData]="FETCH_STEP_RADIO_DATA"
[sectionFormData]="FETCH_FORM_DATA"
[defaultKind]="FETCH_DEFAULT_KIND"
[sectionName]="steps.FETCH"
[eventYamlByHash]="eventYamlByHash"
[description]="
'Determines where data is sourced from'
"
></app-base-step>
<app-stepper-navigation
[prevStep]="null"
[nextStep]="steps.PREPARE"
[validStep]="fetchForm.valid"
(changeStepEmitter)="changeStep($event)"
></app-stepper-navigation>
</div>
</mat-step>
<mat-step
[stepControl]="prepareForm"
errorMessage="Field is required"
>
<app-stepper-navigation
[prevStep]="steps.PREPROCESS"
[nextStep]="null"
[validStep]="mergeForm.valid"
(changeStepEmitter)="changeStep($event)"
(saveEventEmitter)="onSubmit()"
(editYamlEmitter)="onEditYaml()"
></app-stepper-navigation>
</ng-container>
<ng-template matStepLabel> Prepare </ng-template>
<div class="container-step">
<app-prepare-step
[eventYamlByHash]="eventYamlByHash"
[sectionName]="steps.PREPARE"
></app-prepare-step>
<app-stepper-navigation
[prevStep]="steps.FETCH"
[nextStep]="steps.READ"
[validStep]="prepareForm.valid"
(changeStepEmitter)="changeStep($event)"
></app-stepper-navigation>
</div>
</mat-step>
<mat-step
[stepControl]="readForm"
errorMessage="Field is required"
>
<ng-template matStepLabel>
<div
class="stepper-header-overlay"
(click)="onShowErrors()"
></div>
Read</ng-template
>
<div class="container-step">
<app-base-step
[sectionStepRadioData]="READ_STEP_RADIO_DATA"
[sectionFormData]="READ_FORM_DATA"
[defaultKind]="READ_DEFAULT_KIND"
[sectionName]="steps.READ"
[eventYamlByHash]="eventYamlByHash"
[description]="
'Defines how data is read into structured format'
"
></app-base-step>
<app-stepper-navigation
[prevStep]="steps.PREPARE"
[nextStep]="steps.PREPROCESS"
[validStep]="readForm.valid"
(changeStepEmitter)="changeStep($event)"
></app-stepper-navigation>
</div>
</mat-step>
<mat-step [stepControl]="readForm">
<ng-template matStepLabel>Preprocess</ng-template>
<div class="container-step">
<app-preprocess-step
[eventYamlByHash]="eventYamlByHash"
[preprocessValue]="preprocessStepValue"
[showPreprocessStep]="showPreprocessStep"
(showPreprocessStepEmitter)="
onShowPreprcessStep($event)
"
></app-preprocess-step>
<app-stepper-navigation
[prevStep]="steps.READ"
[nextStep]="steps.MERGE"
[validStep]="fetchForm.valid"
(changeStepEmitter)="changeStep($event)"
></app-stepper-navigation>
</div>
</mat-step>
<mat-step [stepControl]="mergeForm">
<ng-template matStepLabel>Merge</ng-template>
<div class="container-step">
<app-base-step
[sectionStepRadioData]="MERGE_STEP_RADIO_DATA"
[sectionFormData]="MERGE_FORM_DATA"
[defaultKind]="MERGE_DEFAULT_KIND"
[sectionName]="steps.MERGE"
[eventYamlByHash]="eventYamlByHash"
[description]="
'Determines how newly-ingested data should be merged with existing history'
"
>
<div
*ngIf="errorMessage"
class="alert alert-danger mt-2"
role="alert"
>
<p class="text-danger fs-6">
Error:<br />{{ errorMessage }}
</p>
</div></app-base-step
>
<app-stepper-navigation
[prevStep]="steps.PREPROCESS"
[nextStep]="null"
[validStep]="mergeForm.valid"
[validAllSteps]="pollingSourceForm.valid"
(changeStepEmitter)="changeStep($event)"
(saveEventEmitter)="onSubmit()"
(editYamlEmitter)="onEditYaml()"
></app-stepper-navigation>
</div>
</mat-step>
</mat-stepper>
</form>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@

.container-step
margin-top: 40px

.layout
max-width: 1200px
width: 100%
margin-right: auto
margin-left: auto
padding: 0 30px 100px
position: relative

.stepper-header-overlay
position: absolute
top: 0
left: 0
width: 100%
height: 100%
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { PollingSourceFormComponentsModule } from "../form-components/polling-so
import { of } from "rxjs";
import { mockDatasetHistoryResponse } from "src/app/search/mock.data";
import {
DatasetKind,
DatasetPageInfoFragment,
MetadataBlockFragment,
} from "src/app/api/kamu.graphql.interface";
Expand Down Expand Up @@ -66,6 +67,7 @@ describe("AddPollingSourceComponent", () => {
createDatasetService = TestBed.inject(AppDatasetCreateService);
modalRef = modalService.open(FinalYamlModalComponent);
component = fixture.componentInstance;
component.showPreprocessStep = false;
component.currentStep = SetPollingSourceSection.FETCH;
component.history = {
history: mockDatasetHistoryResponse.datasets.byOwnerAndName
Expand All @@ -76,6 +78,7 @@ describe("AddPollingSourceComponent", () => {
component.pollingSourceForm = new FormGroup({
fetch: new FormGroup({
kind: new FormControl("url"),
url: new FormControl(""),
order: new FormControl("NONE"),
eventTime: new FormGroup({
kind: new FormControl("fromMetadata"),
Expand Down Expand Up @@ -149,4 +152,18 @@ describe("AddPollingSourceComponent", () => {
createDatasetService.errorCommitEventChanges(errorMessage);
expect(component.errorMessage).toBe(errorMessage);
});

it("should check init dataset kind", () => {
expect(component.datasetKind).toBeUndefined();
editService.changeKindChanges(DatasetKind.Root);
editService.onKindChanges.subscribe(() => {
expect(component.datasetKind).toEqual(DatasetKind.Root);
});
});

it("should check change showPreprocessStep property", () => {
expect(component.showPreprocessStep).toEqual(false);
component.onShowPreprcessStep(true);
expect(component.showPreprocessStep).toEqual(true);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,19 @@ import { DatasetHistoryUpdate } from "src/app/dataset-view/dataset.subscriptions
import { EditPollingSourceService } from "./edit-polling-source.service";
import { MaybeNull } from "src/app/common/app.types";
import { SupportedEvents } from "src/app/dataset-block/metadata-block/components/event-details/supported.events";
import { STEPPER_GLOBAL_OPTIONS } from "@angular/cdk/stepper";

@Component({
selector: "app-add-polling-source",
templateUrl: "./add-polling-source.component.html",
styleUrls: ["./add-polling-source.component.sass"],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
{
provide: STEPPER_GLOBAL_OPTIONS,
useValue: { showError: true },
},
],
})
export class AddPollingSourceComponent extends BaseComponent implements OnInit {
public currentStep: SetPollingSourceSection = SetPollingSourceSection.FETCH;
Expand Down Expand Up @@ -171,17 +178,17 @@ export class AddPollingSourceComponent extends BaseComponent implements OnInit {
FinalYamlModalComponent,
{ size: "lg" },
);
const instance = modalRef.componentInstance as FinalYamlModalComponent;
this.processFormService.transformForm(this.pollingSourceForm);
(modalRef.componentInstance as FinalYamlModalComponent).yamlTemplate =
instance.yamlTemplate =
this.yamlEventService.buildYamlSetPollingSourceEvent(
this.pollingSourceForm.value as Omit<
SetPollingSource,
"__typename"
>,
this.showPreprocessStep ? this.preprocessStepValue : null,
);
(modalRef.componentInstance as FinalYamlModalComponent).datasetInfo =
this.getDatasetInfoFromUrl();
instance.datasetInfo = this.getDatasetInfoFromUrl();
}

public onShowPreprcessStep(showPreprocessStep: boolean): void {
Expand All @@ -195,4 +202,15 @@ export class AddPollingSourceComponent extends BaseComponent implements OnInit {
}),
);
}

public onShowErrors(): void {
const elems =
document.querySelectorAll<HTMLInputElement>("input.ng-invalid");
elems.forEach((element: HTMLInputElement) => {
setTimeout(() => {
element.focus();
element.blur();
});
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<h2 class="text-center">
{{ title }}
</h2>
<p class="text-center mb-4">{{ description }}</p>
<app-select-kind-field
[form]="sectionForm"
[data]="sectionStepRadioData"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export class BaseStepComponent extends BaseComponent implements OnInit {
@Input() public sectionStepRadioData: RadioControlType[];
@Input() public sectionFormData: JsonFormData;
@Input() public defaultKind: string;
@Input() public description: string;
@Input() public sectionName: SetPollingSourceSection;
@Input() public eventYamlByHash: MaybeNull<string> = null;
private editFormValue: EditFormType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,16 @@ <h2 class="text-center">Prepare</h2>
>
<h3 class="text-center">Pipe</h3>
<div>
<label class="form-label"> Command </label>
<label class="form-label">
Command <span class="text-danger">*</span>
</label>
</div>
<input class="form-control" formControlName="command" />
<input
class="form-control"
formControlName="command"
required
/>

<div
*ngIf="
sectionForm.controls[i].get('command')?.errors
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<h2 class="text-center">Preprocess</h2>
<p class="text-center mb-4">Pre-processing query that shapes the data.</p>
<div class="d-flex justify-content-center flex-column align-items-center mt-4">
<div class="form-check">
<input
Expand Down
Loading

0 comments on commit b18816f

Please sign in to comment.