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

Given&Then has been added to ZB. #504

Merged
merged 5 commits into from
Dec 28, 2023
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
79 changes: 68 additions & 11 deletions frontend/src/app/Services/block.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { EventEmitter, Injectable } from '@angular/core';
import { Block } from '../model/Block';
import { Observable } from 'rxjs';
import { BehaviorSubject, Observable} from 'rxjs';
import { ApiService } from '../Services/api.service';
import { HttpClient } from '@angular/common/http';
import { ToastrService } from 'ngx-toastr';
Expand Down Expand Up @@ -63,14 +63,19 @@ export class BlockService {
referenceStories: Story[];
referenceScenarios: Scenario[];
block: Block;
private toastDataSubject = new BehaviorSubject<any>(null);
toastData$ = this.toastDataSubject.asObservable();

updateToastData(data: any) {
this.toastDataSubject.next(data);
}
/**
* Emits the add block to scenario event
* @param block
* @param correspondingComponent
*/
addBlockToScenario(block: Block, correspondingComponent: string, addAsReference: boolean) {
this.addBlockToScenarioEvent.emit([correspondingComponent, block, addAsReference]);
addBlockToScenario(block: Block, correspondingComponent: string, addAsReference: boolean, addBlockAs?: string) {
this.addBlockToScenarioEvent.emit([correspondingComponent, block, addAsReference, addBlockAs]);
}
/**
* Emits the update block in blocks
Expand Down Expand Up @@ -278,26 +283,78 @@ export class BlockService {
}
}
/**
* Unpack steps from block. Wenn delete block unpack all reference in repository
* Unpack steps from a block. When deleting a block, unpack all references in the repository.
* @param block
* @param scenario
*/
unpackScenarioWithBlock(block, scenario) {
unpackScenarioWithBlock(block: Block, scenario: Scenario, stepReference?: StepType) {
delete block.usedAsReference;

if (stepReference) {
this.unpackStepsFromBlock(block, scenario, stepReference);
}else {
// Unpack steps from the block for all reference blocks in the scenario
const arrayRefBlocks = this.findReferenceBlocks(scenario, block);
arrayRefBlocks.forEach(_ => {
this.unpackStepsFromBlock(block, scenario);
});
}
}

/**
* Unpack steps from the block and remove the block reference among the steps.
* @param block
* @param scenario
* @param stepReference
*/
unpackStepsFromBlock(block: Block, scenario: Scenario, stepReference?: StepType) {
if (block && block.stepDefinitions) {
for (const s in block.stepDefinitions) {
block.stepDefinitions[s].forEach((step: StepType, j) => {
block.stepDefinitions[s].forEach((step: StepType) => {
step.checked = false;
scenario.stepDefinitions[s].push(JSON.parse(JSON.stringify(step)));
});
//remove the block reference among the steps
const index = scenario.stepDefinitions[s].findIndex((element) => element._blockReferenceId == block._id);
if (index > -1) {
scenario.stepDefinitions[s].splice(index, 1);
}
// Remove the block reference among the steps
nkarmazina marked this conversation as resolved.
Show resolved Hide resolved
this.removeBlocksAmongSteps(scenario.stepDefinitions[s], block, stepReference);

}
}
}
/**
* Find reference blocks in the given scenario for a specific block.
* @param scenario
* @param block
* @returns Array of reference blocks
*/
findReferenceBlocks(scenario: Scenario, block: Block): StepType[] {
const arrayRefBlocks: StepType[] = [];

for (const type in scenario.stepDefinitions) {
scenario.stepDefinitions[type].forEach((step) => {
if (step._blockReferenceId === block._id) {
arrayRefBlocks.push(step);
}
});
}
return arrayRefBlocks;
}

/**
* Remove blocks among steps based on a block reference or step reference.
* @param stepToSplice
* @param block
* @param stepReference
*/
removeBlocksAmongSteps(stepToSplice, block, stepReference? : StepType) {
const index = stepReference !== undefined
nkarmazina marked this conversation as resolved.
Show resolved Hide resolved
? stepToSplice.findIndex((element) => element.stepType === stepReference.stepType && element.id === stepReference.id )
: stepToSplice.findIndex((element) => element._blockReferenceId === block._id);

if (index > -1) {
stepToSplice.splice(index, 1);
}
}

/**
* Update the reference name in scenarios after changing the block name
* @param block
Expand Down
18 changes: 9 additions & 9 deletions frontend/src/app/base-editor/base-editor.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -457,38 +457,38 @@
</ng-container>
</div>
</div>
<ng-template #stepBlockReference let-block>
<mat-expansion-panel class="stepBlockContainer" (opened)="selectBlock(block)" (closed)="unselectBlock()">
<ng-template #stepBlockReference let-blockStep>
<mat-expansion-panel class="stepBlockContainer" (opened)="selectBlock(blockStep)" (closed)="unselectBlock()">
<mat-expansion-panel-header class="stepBlockHeader">
<mat-panel-title class="stepBlockTitle">
<!-- <div class="dragIconContainer" cdkDragHandle >
<em class="material-icons dragIcon">drag_indicator</em>
</div>
<div *ngIf="(block.selectionValue === undefined || block.selectionValue === null)">
<input type="checkbox" class="checkbox" id="{{'block' + block.id + 'Checkbox'}}" (change)="this.checkStep($event, block, null)" [checked]="block.checked">
<div *ngIf="(blockStep.selectionValue === undefined || blockStep.selectionValue === null)">
<input type="checkbox" class="checkbox" id="{{'blockStep' + blockStep.id + 'Checkbox'}}" (change)="this.checkStep($event, blockStep, null)" [checked]="blockStep.checked">
</div> -->
<div class="SmallHeadline5">
{{block.type}}
{{blockStep.type}}
</div>
</mat-panel-title>
<span class="mat-expansion-indicator" matTooltip="Expand Block to view its Steps"
style="mix-blend-mode: color; width: 15px; transform: translate(9px, 0px);"></span>
</mat-expansion-panel-header>
<!--Block Content-->
<div *ngIf="this.selectedBlock" id="blockContent"
[class.scrollable]="getStepsListBlockPreview(block.stepDefinitions, j).length > 7">
<div *ngFor="let currentStep of getStepsListBlockPreview(block.stepDefinitions); let j = index;">
[class.scrollable]="getStepsListBlockPreview(blockStep.stepDefinitions, j).length > 7">
<div *ngFor="let currentStep of getStepsListBlockPreview(blockStep.stepDefinitions); let j = index;">
<ng-template *ngTemplateOutlet="blockstep;
context: {$implicit: currentStep , index:j}">
</ng-template>
</div>
</div>
<mat-action-row class="blockButtonGroup">
<button id="editBlock" uk-tooltip title="Edit Block" class="blockButton" (click)="editBlock(block);">
<button id="editBlock" uk-tooltip title="Edit Block" class="blockButton" (click)="editBlock(blockStep);">
<em class="material-icons">edit</em>
</button>
<button id="block_RemoveReference" uk-tooltip title="Remove Reference and Unpack Block" class="blockButton"
(click)="showUnpackBlockToast(this.selectedBlock);">
(click)="showUnpackBlockToast(this.selectedBlock, blockStep);">
<em class="material-icons">link_off</em>
</button>
</mat-action-row>
Expand Down
15 changes: 8 additions & 7 deletions frontend/src/app/base-editor/base-editor.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,10 @@ export class BaseEditorComponent {
}
if (this.templateName == 'scenario' && block[0] == 'scenario') {
if (block[2]) {
const blockReference: StepType = {
_blockReferenceId: block[1]._id, id: 0, type: block[1].name, stepType: 'when',
pre: '', mid: '', post: '', values: []
};
this.selectedScenario.stepDefinitions.when.push(JSON.parse(JSON.stringify(blockReference)));
let blockReference: StepType;
blockReference = { _blockReferenceId: block[1]._id, id: 0, type: block[1].name,
stepType: block[3].toLowerCase(), pre: '', mid: '', post: '', values: []};
this.addStep(blockReference, this.selectedScenario, 'scenario');
} else {
block = block[1];
this.insertStepsWithExamples(block);
Expand Down Expand Up @@ -519,6 +518,7 @@ export class BaseEditorComponent {
const obj = JSON.parse(JSON.stringify(step));
const newId = this.getLastIDinStep(stepDefinitions, obj.stepType) + 1;
const newStep: StepType = {
_blockReferenceId: step._blockReferenceId,
id: newId,
mid: obj.mid,
pre: obj.pre,
Expand Down Expand Up @@ -1815,9 +1815,10 @@ export class BaseEditorComponent {
this.expandStepBlock = false;
}

showUnpackBlockToast(block) {
showUnpackBlockToast(block, stepReference) {
const toastData = { block: block, stepReference: stepReference };
this.blockService.updateToastData(toastData);
this.apiService.nameOfComponent('unpackBlock');
this.blockService.block = block;
this.toastr.warning(
'Unpacking the Block will remove its reference to the original Block! Do you want to unpack the block?', 'Unpack Block', {
toastComponent: DeleteToast
Expand Down
18 changes: 11 additions & 7 deletions frontend/src/app/delete-toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
transition,
trigger
} from '@angular/animations';
import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { Toast, ToastrService, ToastPackage } from 'ngx-toastr';
import { ApiService } from './Services/api.service';
import { BlockService } from './Services/block.service';
Expand Down Expand Up @@ -100,7 +100,7 @@ import { StoryService } from './Services/story.service';
],
preserveWhitespaces: false,
})
export class DeleteToast extends Toast {
export class DeleteToast extends Toast implements OnInit {
/**
* Name of the delete button
*/
Expand All @@ -113,6 +113,8 @@ import { StoryService } from './Services/story.service';
* Name of the component that the user wants to delete
*/
nameComponent: string;
toastData: any;

/**
* Constructor
* @param toastrService
Expand All @@ -139,7 +141,12 @@ import { StoryService } from './Services/story.service';
this.deleteString = 'Delete';
}
}


ngOnInit() {
this.blockService.toastData$.subscribe((data) => {
this.toastData = data;
});
}
/**
* Creates a toast and delete the selected component
* @param event
Expand All @@ -157,10 +164,7 @@ import { StoryService } from './Services/story.service';
break;
case 'block': this.blockService.deleteBlockEmitter();
break;
case 'unpackBlock':{
const blockToUnpack = this.blockService.block;
this.blockService.unpackBlockEmitter(blockToUnpack);
}
case 'unpackBlock': this.blockService.unpackBlockEmitter(this.toastData);
break;
}
this.remove();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,27 @@ td.mat-mdc-cell:first-of-type, td.mat-mdc-footer-cell:first-of-type{
}


#addAsReferenceLabel{
#addAsReferenceLabel, #blockAddAslabel{
margin-right: 5px;
margin-top: 3px
}

.addReferenceBlockToStepType{
margin-left: 10px;
display: flex;
align-items: center;
}
#addAsReferenceCheckbox{
margin-left: 5px;
margin-right: 10px;
margin-top: 3px
}

.addAsReference{
display: flex;
align-items: center;
}
.addBlockDropDownDiv{
margin-bottom: 15px;
}
.mat-table{
font-family: Klavika, sans-serif;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,38 @@
</div>
<div id="addBlockFooter" class="modal-footer" [class.forBackground]="this.selectedTemplate == 'background'">
<form *ngIf="blocks.length !== 0 && this.selectedTemplate !== 'background'" class="addAsReference">
<label id="addAsReferenceLabel">Add Block as Reference: </label>
<input id="addAsReferenceCheckbox "type="checkbox" [checked]="this.addAsReference" (change)="checkAddAsReference()">
<dfn class="def">
<span class="infoIcon uk-icon" uk-icon="info" style="color:#999999"></span>
<span rel="def">
Add the saved Block as a Reference to adopt changes, when steps in the original Block get changed.
</span>
</dfn>
<div class="addRefCheckbox">
<label id="addAsReferenceLabel">Add Block as Reference: </label>
<input id="addAsReferenceCheckbox "type="checkbox" [checked]="this.addAsReference" (change)="checkAddAsReference()" [disabled]="this.selectedBlock == undefined">
<dfn class="def">
<span class="infoIcon uk-icon" uk-icon="info" style="color:#999999"></span>
<span rel="def">
Add the saved Block as a Reference to adopt changes, when steps in the original Block get changed.
</span>
</dfn>
</div>
<div *ngIf="this.addAsReference" class="addReferenceBlockToStepType">
<div>
<label id="blockAddAslabel">Block will be added as: </label>
</div>
<div class="addBlockDropDownDiv">
<mat-form-field appearance="standard" class="addBlockDropDown">
<mat-select [formControl]="currentStepType">
<mat-option *ngFor="let addBlockOption of this.addBlockToStepType" [value]="addBlockOption">
{{addBlockOption}}
</mat-option>
</mat-select>
</mat-form-field>
<dfn class="def">
<span class="infoIcon uk-icon" uk-icon="info" style="color:#999999"></span>
<span rel="def">
Add the saved Block as a Reference to a selected type of steps.
</span>
</dfn>
</div>
</div>
</form>
<button *ngIf="blocks.length !== 0" type="button" class="normalButton" (click)="onClickSubmit()">Add Block</button>
<button *ngIf="blocks.length !== 0" type="button" class="normalButton" (click)="onClickSubmit()" [disabled]="this.selectedBlock == undefined" [class.disable]="this.selectedBlock == undefined">Add Block</button>
</div>
</div>
</ng-template>
13 changes: 10 additions & 3 deletions frontend/src/app/modals/add-block-form/add-block-form.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Subscription } from 'rxjs';
import { ToastrService } from 'ngx-toastr';
import { DeleteToast } from 'src/app/delete-toast';
import { ApiService } from 'src/app/Services/api.service';
import { FormControl } from '@angular/forms';

@Component({
selector: 'app-add-block-form',
Expand All @@ -18,7 +19,7 @@ export class AddBlockFormComponent implements OnInit,OnDestroy {
@ViewChild('addBlockFormModal') addBlockFormModal: any;
@ViewChild('newTitle') newTitleLabel: HTMLElement;


currentStepType = new FormControl('When');
/**
* Saved blocks
*/
Expand Down Expand Up @@ -59,6 +60,10 @@ export class AddBlockFormComponent implements OnInit,OnDestroy {
*/
selectedBlockList: Block[];

/**
*The type of step to which to add the block
*/
addBlockToStepType: string[] = ['Given', 'When', 'Then'];
/**
* Currently selected block
*/
Expand Down Expand Up @@ -250,13 +255,14 @@ export class AddBlockFormComponent implements OnInit,OnDestroy {
}

/**
* Adds a block to saved blocks
* Add a block to a scenario
*/
addBlockFormSubmit() {
this.blockService.addBlockToScenario(this.selectedBlock, this.correspondingComponent, this.addAsReference);
this.blockService.addBlockToScenario(this.selectedBlock, this.correspondingComponent, this.addAsReference, this.currentStepType.value);
delete this.addAsReference;
delete this.selectedBlock;
this.stepList = [];
this.currentStepType = new FormControl('When');
this.modalReference.close();
}

Expand Down Expand Up @@ -304,6 +310,7 @@ export class AddBlockFormComponent implements OnInit,OnDestroy {
closeModal(){
delete this.addAsReference;
delete this.selectedBlock;
this.currentStepType = new FormControl('When');
this.stepList = [];
this.modalReference.close();
}
Expand Down
Loading
Loading