Skip to content

Commit

Permalink
[CYB - 195][UI] Parser job configuration. (#89)
Browse files Browse the repository at this point in the history
  • Loading branch information
vpavlenko-cv authored Dec 21, 2024
1 parent b973766 commit 77f4b83
Show file tree
Hide file tree
Showing 16 changed files with 555 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {ClusterPageComponent} from "./cluster/cluster-page/cluster-page.componen
import {PipelinesComponent} from 'src/app/cluster/pipelines/pipelines.component';
import {PipelineCreateComponent} from 'src/app/cluster/pipelines/pipeline-create/pipeline-create.component';
import {PipelineSubmitComponent} from 'src/app/cluster/pipelines/pipeline-submit/pipeline-submit.component';
import {PipelineStepperComponent} from 'src/app/cluster/pipelines/pipeline-stepper/pipeline-stepper.component';

export const routes: Routes = [
{ path: '404', component: PageNotFoundComponent },
Expand All @@ -37,6 +38,7 @@ export const routes: Routes = [
{ path: 'clusters', component: ClusterListPageComponent },
{ path: 'clusters/pipelines', component: PipelinesComponent },
{ path: 'clusters/pipelines/create', component: PipelineCreateComponent },
{ path: 'clusters/pipelines/stepper', component: PipelineStepperComponent },
{ path: 'clusters/pipelines/submit', component: PipelineSubmitComponent },
{ path: 'clusters/:clusterId', component: ClusterPageComponent},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ const mockChains: ChainModel[] = [{id: '1', name: 'test1'}, {id: '2', name: 'tes
describe('PipelinesComponent', () => {
let component: ChainListPageComponent;
let fixture: ComponentFixture<ChainListPageComponent>;
let pipelineService: jasmine.SpyObj<PipelineService>
let chainListPageService: jasmine.SpyObj<ChainListPageService>
let pipelineService: jasmine.SpyObj<PipelineService>;
let chainListPageService: jasmine.SpyObj<ChainListPageService>;

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,16 @@

<div *ngIf="mode !== 'Empty'">
<div class="flex-row-jsb-ac horizontal-wrapper" [style.min-height.px]="70">
<mat-slide-toggle color="primary" [checked]="jobs.indexOf(jobsEnum.PARSER.value) !== -1"
<mat-slide-toggle [disabled]="slideToggleDisabled(jobsEnum.PARSER)" color="primary" [checked]="jobs.indexOf(jobsEnum.PARSER.value) !== -1"
(change)="toggleValueInArray( jobs , jobsEnum.PARSER.value)">{{ jobsEnum.PARSER.label }}
</mat-slide-toggle>
<mat-slide-toggle color="primary" [checked]="jobs.indexOf(jobsEnum.TRIAGE.value) !== -1"
<mat-slide-toggle [disabled]="slideToggleDisabled(jobsEnum.TRIAGE)" color="primary" [checked]="jobs.indexOf(jobsEnum.TRIAGE.value) !== -1"
(change)="toggleValueInArray( jobs , jobsEnum.TRIAGE.value)">{{ jobsEnum.TRIAGE.label }}
</mat-slide-toggle>
<mat-slide-toggle color="primary" [checked]="jobs.indexOf(jobsEnum.PROFILE.value) !== -1"
<mat-slide-toggle [disabled]="slideToggleDisabled(jobsEnum.PROFILE)" color="primary" [checked]="jobs.indexOf(jobsEnum.PROFILE.value) !== -1"
(change)="toggleValueInArray( jobs , jobsEnum.PROFILE.value)">{{ jobsEnum.PROFILE.label }}
</mat-slide-toggle>
<mat-slide-toggle color="primary" [checked]="jobs.indexOf(jobsEnum.INDEX.value) !== -1"
<mat-slide-toggle [disabled]="slideToggleDisabled(jobsEnum.INDEX)" color="primary" [checked]="jobs.indexOf(jobsEnum.INDEX.value) !== -1"
(change)="toggleValueInArray( jobs , jobsEnum.INDEX.value)">{{ jobsEnum.INDEX.label }}
</mat-slide-toggle>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const BUTTONS_CONST = [
{label: 'Archive', value: 'Archive', disabled: false},
{label: 'Git', value: 'Git', disabled: false},
{label: 'Empty', value: 'Empty', disabled: false},
{label: 'Manual', value: 'Manual', disabled: true}
{label: 'Manual', value: 'Manual', disabled: false}
] as const;

const BUTTON_LABELS = BUTTONS_CONST.map(b => b.value);
Expand Down Expand Up @@ -107,6 +107,8 @@ export class PipelineCreateComponent {
this.fileControl.clearValidators();
break
case 'Manual':
this.jobs = [JOBS_ENUM.PARSER.value];
break;
default:
}
this.fileControl.updateValueAndValidity();
Expand All @@ -128,7 +130,13 @@ export class PipelineCreateComponent {
jobs: this.jobs,
sourceMap: this.sourceMap,
}
this._router.navigate(['clusters/pipelines/submit'], {state: {data}});
if (this.mode === 'Manual') {
this._router.navigate(['clusters/pipelines/stepper'], {state: {data}});

} else {
this._router.navigate(['clusters/pipelines/submit'], {state: {data}});

}
}

onFileDropped(fileList: FileList) {
Expand Down Expand Up @@ -182,4 +190,9 @@ export class PipelineCreateComponent {
}))
);
}

slideToggleDisabled(value) {
return this.mode === 'Manual' && value !== JOBS_ENUM.PARSER;

}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,188 @@
<p>pipeline-stepper works!</p>
<mat-stepper #stepper>
<mat-step [stepControl]="parserFormGroup">
<form [formGroup]="parserFormGroup">
<ng-template matStepLabel>Parser config</ng-template>
<mat-tab-group color="primary" class="parser-chain-step">
<mat-tab label="General Config">
<div class="general-section">
<h1>Kafka Topic config: </h1>
<span>Configuration of Kafka topic for parser job</span>
<div style="display: flex; flex-direction: column">
<div style="display: flex; flex-direction: row">
<mat-form-field class="input-form" color="primary" appearance="outline">
<mat-label>Topic output</mat-label>
<input matInput
type="text"
formControlName="topicOutput"
id="topicOutput"
label="topic Output"
placeholder="topic Output"
>
</mat-form-field>
<mat-form-field class="input-form" color="primary" appearance="outline" [style.margin-left.px]="15">
<mat-label>Error Topic</mat-label>
<input matInput
type="text"
formControlName="errorTopic"
id="errorTopic"
label="error topic name"
placeholder="error topic">
</mat-form-field>
</div>
<mat-slide-toggle color="primary" formControlName="sourceFlag" [style.margin-bottom.px]="15">Enable source
</mat-slide-toggle>
<div *ngIf="parserFormGroup.controls.sourceFlag.value" class="general-section">
<mat-form-field class="input-form" color="primary"
appearance="outline">
<mat-label>Original base path</mat-label>
<input matInput
type="text"
formControlName="origBasePath"
id="origBasePath"
label="original base path"
placeholder="orig Base Path name">
</mat-form-field>
</div>
</div>
</div>

</mat-tab>

<div formArrayName="chains">
<mat-tab *ngFor="let chain of chains.controls; let index = index" formGroupName="{{index}}">
<ng-template mat-tab-label>
<ng-container *ngIf="!chain.getRawValue().editMode">
<div (dblclick)="dbClick(chain)">{{ chain.getRawValue().chainName }}</div>
</ng-container>

<ng-container *ngIf="chain.getRawValue().editMode">
<input style="max-width: 100px" formControlName="chainName"/>
<mat-icon class="save-tab-icon" (click)="dbClick(chain)">save</mat-icon>
<mat-icon *ngIf="chains.length > 1" class="delete-tab-icon" (click)="deleteChain(index)">delete
</mat-icon>
</ng-container>
</ng-template>
<mat-form-field *ngIf="vm$ | async as vm" class="source-list" appearance="outline">
<mat-label>Source</mat-label>
<mat-chip-list #chipList aria-label="Source selection" selectable="false">
<mat-chip
*ngFor="let selectedPipeline of getSelectedSource(index)"
(removed)="remove(selectedPipeline, index)"
>
{{ selectedPipeline }}
<button matChipRemove>
<mat-icon>cancel</mat-icon>
</button>
</mat-chip>
<input
placeholder="Select source..."
#sourceInput
formControlName="source"
[style.width.%]="85"
[matAutocomplete]="auto"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
(matChipInputTokenEnd)="add($event, index)">
<mat-autocomplete #auto="matAutocomplete"
(optionSelected)="selected($event, index)">
<mat-option
*ngFor="let searchedPipeline of vm.pipelines | filter:getSelectedSource(index) | contains:getSource(index)"
[value]="searchedPipeline">
{{ searchedPipeline }}
</mat-option>
</mat-autocomplete>
</mat-chip-list>

</mat-form-field>

<!-- Chains list -->

<div *ngIf="vm$ | async as vm">
<app-custom-list *ngIf="vm.currentChains.length > 0">
<app-custom-list-line *ngFor="let chain of vm.currentChains">
<mat-icon customListIcon>link</mat-icon>
<div customListLine>{{ chain.name }}</div>
<app-styled-chips-list customListChips
[chips]="topicMap.get(index)?.get(chain.id) ? [topicMap.get(index).get(chain.id)] : [] "
[forceStyleDisplay]="true"></app-styled-chips-list>
<button
customListAction
mat-button
color="primary"
class="flex-row-jc-ac"
data-qe-id="view-fields-button"
matTooltip="Add topic to the chain"
matTooltipPosition="above"
(click)="assignTopic(assignTopicDialog, chain.id, index)">
<mat-chip selected>ASSIGN TOPIC
<mat-icon [style.color]="'white'">add</mat-icon>
</mat-chip>
</button>
<button
customListAction
mat-button
color="primary"
class="flex-row-jc-ac"
data-qe-id="view-fields-button"
matTooltip="Edit"
matTooltipPosition="below"
[routerLink]="['/parserconfig', 'chains', chain.id]"
[queryParams]="{pipeline: chain.pipeline}"

>
<mat-icon class="edit-action-color">edit</mat-icon>
</button>
<button
customListAction
mat-button
color="primary"
class="flex-row-jc-ac"
data-qe-id="delete-field-type-btn"
matTooltip="Delete"
matTooltipPosition="below"
(click)="deleteItem(chain.id)">
<mat-icon class="delete-action-color">delete</mat-icon>
</button>
</app-custom-list-line>
</app-custom-list>
<button [style.margin.px]="10" mat-raised-button routerLink="/parserconfig"
color="primary">ADD CHAIN
</button>
</div>
</mat-tab>
</div>
<mat-tab disabled>
<ng-template mat-tab-label>
<button mat-icon-button (click)="addTab()">
<mat-icon>add_circle</mat-icon>
</button>
</ng-template>
</mat-tab>
</mat-tab-group>
<div>
<button mat-raised-button color="primary" (click)="navigateToReceiver()" matStepperNext>Next
</button>
</div>
</form>
</mat-step>
</mat-stepper>


<ng-template #assignTopicDialog let-data>
<h2 mat-dialog-title>Assign Topic</h2>
<div mat-dialog-content [style.display]="'inline'">
<div class="inner-assign-wrapper">
<span class="inner-assign-wrapper-span">
Topic or Topic pattern that would associated with this chain.
</span>
<mat-form-field appearance="outline">
<mat-label>Topic Name</mat-label>
<input matInput [(ngModel)]="data.name">
</mat-form-field>
</div>
</div>
<div mat-dialog-actions align="end">
<button mat-raised-button color="accent" [mat-dialog-close]="false">Cancel</button>
<button mat-raised-button color="primary" [mat-dialog-close]="data">Assign</button>
</div>
</ng-template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
@use '@angular/material' as mat;
@import "./styles.scss";

.save-tab-icon {
color: mat.get-color-from-palette($theme-primary);
}

.delete-tab-icon {
color: mat.get-color-from-palette(mat.$red-palette, 300);
}

.source-list {
min-width: 300px;
width: 70%;
margin-top: 10px;
margin-bottom: 10px;
}

.inner-assign-wrapper {
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-content: flex-start;
justify-content: space-around;
align-items: flex-start;
}

.inner-assign-wrapper-span {
font-size: 20px;
margin-bottom: 15px;
}

.general-section {
display: flex;
flex-direction: column
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {ComponentFixture, TestBed} from '@angular/core/testing';

import {PipelineStepperComponent} from './pipeline-stepper.component';
import {FormsModule} from '@angular/forms';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {SharedModule} from 'src/app/shared/share.module';
import {MatCardModule} from '@angular/material/card';
import {MatDividerModule} from '@angular/material/divider';
Expand All @@ -16,10 +16,26 @@ import {AsyncPipe, NgComponentOutlet, NgForOf, NgIf, NgTemplateOutlet} from '@an
import {MatSelectModule} from '@angular/material/select';
import {MatStepperModule} from '@angular/material/stepper';
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
import {PipelineService} from 'src/app/services/pipeline.service';
import {of} from 'rxjs';
import {ChainListPageService} from 'src/app/services/chain-list-page.service';
import {ChainModel} from 'src/app/chain-list-page/chain.model';
import {Router} from '@angular/router';
import {RouterTestingModule} from '@angular/router/testing';
import {MatTabsModule} from '@angular/material/tabs';
import {MatSlideToggleModule} from '@angular/material/slide-toggle';
import {MatChipsModule} from '@angular/material/chips';
import {MatAutocompleteModule} from '@angular/material/autocomplete';

const mockPipeline = ['foo-pipeline1', 'foo-pipeline2'];
const mockChains: ChainModel[] = [{id: '1', name: 'test1'}, {id: '2', name: 'test2'}];

describe('PipelineStepperComponent', () => {
let component: PipelineStepperComponent;
let fixture: ComponentFixture<PipelineStepperComponent>;
let pipelineService: jasmine.SpyObj<PipelineService>;
let chainListPageService: jasmine.SpyObj<ChainListPageService>;
let router: Router;

beforeEach(async () => {
await TestBed.configureTestingModule({ imports: [
Expand All @@ -41,13 +57,43 @@ describe('PipelineStepperComponent', () => {
FormsModule,
NgForOf,
MatStepperModule,
RouterTestingModule.withRoutes([]),
MatTabsModule,
ReactiveFormsModule,
MatSlideToggleModule,
MatChipsModule,
MatAutocompleteModule,
NoopAnimationsModule
],
providers: [
{
provide: PipelineService,
useValue: jasmine.createSpyObj('PipelineService', ['getPipelines', 'createPipeline', 'renamePipeline', 'deletePipeline'])
},
{
provide: ChainListPageService,
useValue: jasmine.createSpyObj('ChainListPageService', ['createChain', 'getChains', 'deleteChain', 'getPipelines'])
},
],

declarations: [ PipelineStepperComponent ]
})
.compileComponents();

pipelineService = TestBed.inject(PipelineService) as jasmine.SpyObj<PipelineService>;
pipelineService.getPipelines.and.returnValue(of(mockPipeline));
chainListPageService = TestBed.inject(ChainListPageService) as jasmine.SpyObj<ChainListPageService>;
chainListPageService.getChains.and.returnValue(of(mockChains));

router = TestBed.inject(Router);
spyOn(router, 'getCurrentNavigation').and.returnValue({
extras: {state: {data: {clusterId: 'test1', pipelineName: 'foo-pipe', branch: 'testbranch'}}},
id: 0,
initialUrl: null,
extractedUrl: null,
trigger: null,
previousNavigation: null
})
fixture = TestBed.createComponent(PipelineStepperComponent);
component = fixture.componentInstance;
fixture.detectChanges();
Expand Down
Loading

0 comments on commit 77f4b83

Please sign in to comment.