Skip to content

Commit

Permalink
Merge pull request #504 from adessoSE/CUC-533-given-then-in-central-b…
Browse files Browse the repository at this point in the history
…lock

Given&Then has been added to ZB.
  • Loading branch information
Alice-cla authored Dec 28, 2023
2 parents ea08fc7 + f76f40c commit 3aea89b
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 52 deletions.
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
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
? 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 @@ -463,38 +463,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 @@ -215,11 +215,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 @@ -541,6 +540,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 @@ -1840,9 +1840,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

0 comments on commit 3aea89b

Please sign in to comment.