Commit 2e8160bf authored by Alexander Philipp Nowosad's avatar Alexander Philipp Nowosad
Browse files

Add domain selection for expert knowledge

parent 109dd4ed
Pipeline #136390 failed with stages
in 10 minutes and 33 seconds
......@@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
import { PouchdbService } from '../database/pouchdb.service';
import { CompanyModel } from './company-model';
import PouchDB from 'pouchdb-browser';
import { CanvasDefinition } from './canvas-definition';
@Injectable({
providedIn: 'root'
......@@ -13,6 +14,14 @@ export class CompanyModelService {
) {
}
async createCompanyModel(model: Partial<CompanyModel>, definition: CanvasDefinition) {
const {id} = await this.add(model);
const companyModel = await this.get(id);
companyModel.definition = definition;
await this.save(companyModel);
return this.get(id);
}
add(companyModel: Partial<CompanyModel>) {
return this.pouchdbService.post(new CompanyModel(companyModel));
}
......
......@@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
import { PouchdbService } from '../database/pouchdb.service';
import PouchDB from 'pouchdb-browser';
import { ExpertModel } from './expert-model';
import { CanvasDefinition } from './canvas-definition';
@Injectable({
providedIn: 'root'
......@@ -13,6 +14,14 @@ export class ExpertModelService {
) {
}
async createExpertModel(model: Partial<ExpertModel>, definition: CanvasDefinition) {
const {id} = await this.add(model);
const expertModel = await this.get(id);
expertModel.definition = definition;
await this.save(expertModel);
return this.get(id);
}
add(expertModel: Partial<ExpertModel>) {
return this.pouchdbService.post(new ExpertModel(expertModel));
}
......
<ng-template #createModal let-d="dismiss">
<div class="modal-header">
<h4 class="modal-title" id="modal-basic-title">Create Company Model</h4>
<button type="button" class="close" aria-label="Close" (click)="d()">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="text-muted pt-3">
<form [formGroup]="createForm" (ngSubmit)="createCompanyModel()">
<app-feature-model-subform formGroupName="featureModel"></app-feature-model-subform>
<div class="form-group row">
<div class="col-sm-12">
<button type="submit" class="btn btn-sm btn-dark btn-block" [disabled]="!createForm.valid">
Create Company Model
</button>
</div>
</div>
</form>
</div>
</div>
</ng-template>
<ng-container [formGroup]="formGroup">
<div class="form-group form-row">
<label for="companyModelSelector" class="col-sm-6 col-form-label">Company Model</label>
<div class="col-sm-6">
<div class="col-sm-6 input-group">
<select id="companyModelSelector" formControlName="companyModelId" class="form-control">
<option *ngFor="let model of companyModels" [value]="model._id">{{ model.name }}</option>
</select>
{{predefinedInput.automaticCreation}}
<div class="input-group-append"
*ngIf="stepDecision.automaticCreation && stepDecision.companyModelId === companyModelIdControl.value">
<button class="btn btn-outline-warning" type="button" (click)="navigateSelectExpertKnowledge()">Edit</button>
</div>
</div>
</div>
<div class="d-flex">
<button type="button" class="btn btn-primary ml-auto" (click)="openCreateCompanyModelModal()">
Create new Company Model
</button>
</div>
</ng-container>
import { Component, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { Component, EventEmitter, OnInit, ViewChild } from '@angular/core';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { CompanyModel } from '../../../canvas-meta-model/company-model';
import { CompanyModelService } from '../../../canvas-meta-model/company-model.service';
import { DecisionConfigurationFormComponent } from '../../../development-process-registry/module-api/decision-configuration-form-component';
import { Domain } from '../../../development-process-registry/knowledge/domain';
import { FeatureModelFormService } from '../../form-services/feature-model-form.service';
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { CanvasDefinitionService } from '../../../canvas-meta-model/canvas-definition.service';
import { BmProcess } from '../../../development-process-registry/bm-process/bm-process';
import { Router } from '@angular/router';
@Component({
selector: 'app-create-canvas-configuration',
......@@ -13,22 +18,69 @@ import { Domain } from '../../../development-process-registry/knowledge/domain';
export class CreateCanvasConfigurationComponent implements OnInit, DecisionConfigurationFormComponent {
formGroup: FormGroup;
bmProcess: BmProcess;
predefinedInput: any;
contextDomains: Domain[];
stepDecision: any;
forceUpdate: EventEmitter<any>;
createForm: FormGroup;
companyModels: CompanyModel[];
private modalReference: NgbModalRef;
@ViewChild('createModal', {static: true}) createModal: any;
constructor(
private canvasDefinitionService: CanvasDefinitionService,
private companyModelService: CompanyModelService,
private fb: FormBuilder,
private featureModelFormService: FeatureModelFormService,
private modalService: NgbModal,
private router: Router,
) {
}
ngOnInit() {
this.loadCompanyModels().then();
this.createForm = this.fb.group({
featureModel: this.featureModelFormService.createForm(),
});
}
openCreateCompanyModelModal() {
this.modalReference = this.modalService.open(this.createModal, {size: 'lg'});
}
async createCompanyModel() {
const model: Partial<CompanyModel> = this.featureModelFormService.get(this.createForm.get('featureModel').value);
const canvasDefinition = await this.canvasDefinitionService.get(this.predefinedInput.definitionId);
const companyModel = await this.companyModelService.createCompanyModel(model, canvasDefinition);
this.forceUpdate.emit({companyModelId: companyModel._id, automaticCreation: true});
this.modalService.dismissAll();
this.router.navigate(['companyModels', companyModel._id, 'select'], {
queryParams: {
bmProcessId: this.bmProcess._id,
}
}).then();
}
navigateSelectExpertKnowledge() {
this.modalService.dismissAll();
this.router.navigate(['companyModels', this.stepDecision.companyModelId, 'select'], {
queryParams: {
bmProcessId: this.bmProcess._id,
}
}).then();
}
private async loadCompanyModels() {
this.companyModels = (await this.companyModelService.getList(this.predefinedInput.definitionId)).docs;
}
get companyModelIdControl() {
return this.formGroup.get('companyModelId') as FormControl;
}
}
......@@ -14,6 +14,9 @@ import { CreateCanvasComponent } from './api/create-canvas/create-canvas.compone
import { EditCanvasComponent } from './api/edit-canvas/edit-canvas.component';
import { CanvasDefinitionsComponent } from './canvas-definition/canvas-definitions/canvas-definitions.component';
import { CanvasDefinitionComponent } from './canvas-definition/canvas-definition/canvas-definition.component';
import {
CompanyModelSelectExpertKnowledgeComponent
} from './company-model/company-model-select-expert-knowledge/company-model-select-expert-knowledge.component';
const routes: Routes = [
......@@ -24,6 +27,7 @@ const routes: Routes = [
{path: 'companyModels', component: CompanyModelsComponent},
{path: 'companyModels/:id', component: CompanyModelComponent},
{path: 'companyModels/:id/edit', component: CompanyModelEditComponent},
{path: 'companyModels/:id/select', component: CompanyModelSelectExpertKnowledgeComponent},
{path: 'expertModels', component: ExpertModelsComponent},
{path: 'expertModels/:id', component: ExpertModelComponent},
{path: 'expertModels/:id/edit', component: ExpertModelEditComponent},
......
......@@ -46,6 +46,9 @@ import { CanvasComponent } from './instances/canvas/canvas.component';
import {
SelectCanvasDefinitionConfigurationComponent
} from './api/select-canvas-definition-configuration/select-canvas-definition-configuration.component';
import {
CompanyModelSelectExpertKnowledgeComponent
} from './company-model/company-model-select-expert-knowledge/company-model-select-expert-knowledge.component';
@NgModule({
......@@ -75,6 +78,7 @@ import {
// company-model
CompanyModelComponent,
CompanyModelEditComponent,
CompanyModelSelectExpertKnowledgeComponent,
CompanyModelsComponent,
// expert-model
......
......@@ -3,9 +3,7 @@ import { ModuleService } from '../development-process-registry/module-api/module
import { Module } from '../development-process-registry/module-api/module';
import { CompanyModel } from '../canvas-meta-model/company-model';
import { CompanyModelService } from '../canvas-meta-model/company-model.service';
import { CanvasDefinition } from '../canvas-meta-model/canvas-definition';
import { CanvasApiService } from './canvas-api.service';
import { ExpertModel } from '../canvas-meta-model/expert-model';
import { ExpertModelService } from '../canvas-meta-model/expert-model.service';
import { CreateCanvasConfigurationComponent } from './api/create-canvas-configuration/create-canvas-configuration.component';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
......@@ -68,20 +66,4 @@ export class CanvasService {
output: [{name: 'Canvas', metaModelType: CompanyModel.typeName}],
});
}
async createExpertModel(model: Partial<ExpertModel>, definition: CanvasDefinition) {
const {id} = await this.expertModelService.add(model);
const expertModel = await this.expertModelService.get(id);
expertModel.definition = definition;
await this.expertModelService.save(expertModel);
return this.expertModelService.get(id);
}
async createCompanyModel(model: Partial<CompanyModel>, definition: CanvasDefinition) {
const {id} = await this.companyModelService.add(model);
const companyModel = await this.companyModelService.get(id);
companyModel.definition = definition;
await this.companyModelService.save(companyModel);
return this.companyModelService.get(id);
}
}
<div class="nav-scroller bg-white shadow-sm">
<nav class="nav nav-underline" *ngIf="bmProcess && companyModel">
<a class="nav-link" [routerLink]="['/', 'bmprocess', 'bmprocessview', bmProcess._id]">{{bmProcess.name}}</a>
<a class="nav-link active"
[routerLink]="[]"
[queryParams]="{bmProcessId: this.bmProcess._id}">{{companyModel.name}}</a>
</nav>
</div>
<main *ngIf="companyModel && bmProcess" role="main" class="container">
<app-model-info-box [featureModel]="companyModel"></app-model-info-box>
<div class="my-3 p-3 bg-white rounded shadow-sm">
<h6 class="border-bottom border-gray pb-2">Domains</h6>
<ul class="list-group">
<li class="list-group-item" *ngFor="let domain of bmProcess.domains">{{domain.name}}</li>
</ul>
</div>
<div class="my-3 p-3 bg-white rounded shadow-sm">
<h6 class="border-bottom border-gray pb-2 mb-0">Select Expert Business Knowledge Model</h6>
<div class="text-muted pt-3">
<form [formGroup]="selectedExpertModelForm" (ngSubmit)="selectExpertModel()">
<div class="form-group row">
<label for="expertModelSelector" class="col-sm-4 col-form-label">Expert Business Knowledge Model</label>
<div class="col-sm-8">
<select id="expertModelSelector" formControlName="expertModelId" class="form-control">
<option *ngFor="let em of unselectedExpertModelList" [value]="em._id">{{ em.name }}</option>
</select>
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
<button type="submit" class="btn btn-sm btn-dark btn-block" [disabled]="!selectedExpertModelForm.valid">
Add Expert Model
</button>
</div>
</div>
</form>
</div>
</div>
<div class="my-3 p-3 bg-white rounded shadow-sm">
<h6 class="border-bottom border-gray pb-2 mb-0">Selected Expert Business Knowledge Models</h6>
<ul *ngIf="selectedExpertModelList" class="list-group inner" style="margin:5px;">
<li *ngFor="let em of selectedExpertModelList"
class="d-flex list-group-item justify-content-between align-items-center">
<span>{{ em.name }}</span>
<span>
<button type="button" (click)="mergeExpertModel(em._id)"
class="btn btn-warning btn-xs mr-1">Merge</button>
<button (click)="unselectExpertModel(em._id)" type="button"
class="btn btn-danger btn-xs">Unselect</button>
</span>
</li>
</ul>
</div>
</main>
import { Component, OnDestroy, OnInit } from '@angular/core';
import { CompanyModel } from '../../../canvas-meta-model/company-model';
import { Subscription } from 'rxjs';
import { ActivatedRoute, Router } from '@angular/router';
import { CompanyModelService } from '../../../canvas-meta-model/company-model.service';
import { BmProcess } from '../../../development-process-registry/bm-process/bm-process';
import { BmProcessService } from '../../../development-process-registry/bm-process/bm-process.service';
import { MergeService } from '../../merge/merge.service';
import { FormBuilder, Validators } from '@angular/forms';
import { ExpertModel } from '../../../canvas-meta-model/expert-model';
@Component({
selector: 'app-company-model-select-expert-knowledge',
templateUrl: './company-model-select-expert-knowledge.component.html',
styleUrls: ['./company-model-select-expert-knowledge.component.css']
})
export class CompanyModelSelectExpertKnowledgeComponent implements OnInit, OnDestroy {
companyModel: CompanyModel;
bmProcess: BmProcess;
selectedExpertModelForm = this.fb.group({expertModelId: [null, Validators.required]});
selectedExpertModelList: ExpertModel[];
unselectedExpertModelList: ExpertModel[];
private querySubscription: Subscription;
private routeSubscription: Subscription;
constructor(
private bmProcessService: BmProcessService,
private companyModelService: CompanyModelService,
private fb: FormBuilder,
private mergeService: MergeService,
private route: ActivatedRoute,
private router: Router,
) {
}
ngOnInit() {
this.querySubscription = this.route.queryParamMap.subscribe((paramMap) => {
this.loadBmProcess(paramMap.get('bmProcessId')).then();
});
this.routeSubscription = this.route.paramMap.subscribe((paramMap) => {
this.loadCompanyModel(paramMap.get('id')).then();
});
}
ngOnDestroy() {
if (this.querySubscription) {
this.querySubscription.unsubscribe();
}
if (this.routeSubscription) {
this.routeSubscription.unsubscribe();
}
}
async loadCompanyModel(companyModelId: string) {
this.companyModel = await this.companyModelService.get(companyModelId);
await this.loadExpertModels(companyModelId);
}
async loadBmProcess(bmProcessId: string) {
this.bmProcess = await this.bmProcessService.getBmProcess(bmProcessId);
}
mergeExpertModel(expertModelId: string): void {
this.router.navigate(['/merge', this.companyModel._id, expertModelId]).then();
}
async selectExpertModel() {
await this.mergeService.selectExpertModel(this.companyModel._id, this.selectedExpertModelForm.value.expertModelId);
this.selectedExpertModelForm.reset();
await this.loadExpertModels(this.companyModel._id);
}
async unselectExpertModel(expertModelId: string) {
await this.mergeService.unselectExpertModel(this.companyModel._id, expertModelId);
await this.loadExpertModels(this.companyModel._id);
}
private async loadExpertModels(companyModelId: string) {
await this.loadSelectedExpertModels(companyModelId);
await this.loadUnselectedExpertModels(companyModelId);
}
private async loadSelectedExpertModels(companyModelId: string) {
const result = await this.mergeService.getSelectedExpertModels(companyModelId);
this.selectedExpertModelList = result.docs;
}
private async loadUnselectedExpertModels(companyModelId: string) {
const result = await this.mergeService.getUnselectedExpertModels(companyModelId);
this.unselectedExpertModelList = result.docs.filter(
(model) => model.domains.some((domain) => this.bmProcess.domains.includes(domain))
);
}
}
import { Component, OnInit } from '@angular/core';
import { CanvasService } from '../../canvas.service';
import { Router } from '@angular/router';
import { CompanyModel } from '../../../canvas-meta-model/company-model';
import { CompanyModelService } from '../../../canvas-meta-model/company-model.service';
......@@ -15,7 +14,6 @@ export class CompanyModelsComponent implements OnInit {
companyModelList: CompanyModel[];
constructor(
private canvasService: CanvasService,
private companyModelService: CompanyModelService,
private router: Router,
) {
......@@ -26,7 +24,7 @@ export class CompanyModelsComponent implements OnInit {
}
async addCompanyModel(definition: CanvasDefinition, name: string, description: string) {
await this.canvasService.createCompanyModel({name, description}, definition);
await this.companyModelService.createCompanyModel({name, description}, definition);
this.loadCompanyModelList().then();
}
......
......@@ -2,7 +2,6 @@ import { Component, OnInit } from '@angular/core';
import { ExpertModelService } from '../../../canvas-meta-model/expert-model.service';
import { ExpertModel } from '../../../canvas-meta-model/expert-model';
import { Router } from '@angular/router';
import { CanvasService } from '../../canvas.service';
import { CanvasDefinition } from '../../../canvas-meta-model/canvas-definition';
@Component({
......@@ -15,7 +14,6 @@ export class ExpertModelsComponent implements OnInit {
expertModelList: ExpertModel[];
constructor(
private canvasService: CanvasService,
private expertModelService: ExpertModelService,
private router: Router,
) {
......@@ -26,7 +24,7 @@ export class ExpertModelsComponent implements OnInit {
}
async addExpertModel(definition: CanvasDefinition, name: string, description: string) {
await this.canvasService.createExpertModel({name, description}, definition);
await this.expertModelService.createExpertModel({name, description}, definition);
this.loadExpertModelList();
}
......
import { ConfigurationFormComponent } from './configuration-form-component';
import { Domain } from '../knowledge/domain';
import { EventEmitter } from '@angular/core';
import { BmProcess } from '../bm-process/bm-process';
export interface DecisionConfigurationFormComponent extends ConfigurationFormComponent {
bmProcess: BmProcess;
predefinedInput: any;
contextDomains: Domain[];
stepDecision: any;
forceUpdate: EventEmitter<any>;
}
......@@ -104,7 +104,8 @@
</button>
</div>
<div class="modal-body">
<app-method-info [contextDomains]="bmProcess.domains" [contextSituationalFactors]="bmProcess.situationalFactors"
<app-method-info [bmProcess]="bmProcess" [contextDomains]="bmProcess.domains"
[contextSituationalFactors]="bmProcess.situationalFactors"
[developmentMethod]="modalDevelopmentMethod" [decision]="bmProcess.decisions[modalElement.id]"
(updateDecisions)="updateDecisions($event)"></app-method-info>
</div>
......
import { Component, ComponentFactoryResolver, Input, OnChanges, SimpleChanges, ViewChild } from '@angular/core';
import { Component, ComponentFactoryResolver, EventEmitter, Input, OnChanges, Output, SimpleChanges, ViewChild } from '@angular/core';
import { ExecutionStep } from '../../development-process-registry/development-method/execution-step';
import { ModuleService } from '../../development-process-registry/module-api/module.service';
import { ConfigurationFormPlaceholderDirective } from '../configuration-form-placeholder.directive';
import { ControlContainer, FormGroup } from '@angular/forms';
import { Domain } from '../../development-process-registry/knowledge/domain';
import { BmProcess } from '../../development-process-registry/bm-process/bm-process';
@Component({
selector: 'app-method-info-step',
......@@ -12,8 +13,12 @@ import { Domain } from '../../development-process-registry/knowledge/domain';
})
export class MethodInfoStepComponent implements OnChanges {
@Input() bmProcess: BmProcess;
@Input() contextDomains: Domain[];
@Input() step: ExecutionStep;
@Input() stepDecision: any;
@Output() forceUpdate = new EventEmitter<any>();
@ViewChild(ConfigurationFormPlaceholderDirective, {static: true}) configurationFormHost: ConfigurationFormPlaceholderDirective;
......@@ -39,8 +44,11 @@ export class MethodInfoStepComponent implements OnChanges {
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(configurationFormComponentFactory);
componentRef.instance.formGroup = this.formGroup;
componentRef.instance.bmProcess = this.bmProcess;
componentRef.instance.predefinedInput = this.step.predefinedInput;
componentRef.instance.contextDomains = this.contextDomains;
componentRef.instance.forceUpdate = this.forceUpdate;
componentRef.instance.stepDecision = this.stepDecision;
}
}
......
<form [formGroup]="form" (ngSubmit)="submitForm()">
<ul formArrayName="steps" class="list-group">
<li *ngFor="let step of steps; let index = index" class="list-group-item">
<app-method-info-step [formGroupName]="index.toString()"
[contextDomains]="contextDomains"
[step]="step"></app-method-info-step>
<app-method-info-step
[formGroupName]="index.toString()"
[bmProcess]="bmProcess"
[contextDomains]="contextDomains"
[step]="step"
[stepDecision]="stepDecisions[index]"
(forceUpdate)="forceUpdate.emit({step: index, stepDecision: $event})"></app-method-info-step>
</li>
</ul>
<div *ngIf="steps.length > 0" class="form-group row mt-3">
......
......@@ -3,6 +3,7 @@ import { FormArray, FormBuilder, FormGroup } from '@angular/forms';
import { ExecutionStep } from '../../development-process-registry/development-method/execution-step';
import { MethodInfoStepsFormService } from '../shared/method-info-steps-form.service';
import { Domain } from '../../development-process-registry/knowledge/domain';
import { BmProcess } from '../../development-process-registry/bm-process/bm-process';
@Component({
selector: 'app-method-info-steps',
......@@ -11,11 +12,13 @@ import { Domain } from '../../development-process-registry/knowledge/domain';
})
export class MethodInfoStepsComponent implements OnChanges {
@Input() bmProcess: BmProcess;
@Input() contextDomains: Domain[];
@Input() steps: ExecutionStep[];
@Input() stepDecisions: any[];
@Output() submitStepsForm = new EventEmitter<any[]>();