Merge pull request #3809 from tsiegleauq/MotionStates

Read the Workflow by state_id in Motion
This commit is contained in:
Finn Stutzenstein 2018-08-23 15:11:03 +02:00 committed by GitHub
commit 95c6628732
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 83 additions and 35 deletions

View File

@ -37,9 +37,7 @@ export class Motion extends BaseModel {
agenda_item_id: number;
log_messages: MotionLog[];
// read from config
workflow_id: number;
// by the config above
// dynamic values
workflow: Workflow;
// for request
@ -100,31 +98,31 @@ export class Motion extends BaseModel {
}
/**
* sets the workflow_id and the workflow
* sets the and the workflow from either dataStore or WebSocket
*/
initDataStoreValues() {
const motionsWorkflowConfig = this.DS.filter(Config, config => config.key === 'motions_workflow')[0] as Config;
if (motionsWorkflowConfig) {
this.workflow_id = +motionsWorkflowConfig.value;
} else {
this.DS.getObservable().subscribe(newConfig => {
if (newConfig instanceof Config && newConfig.key === 'motions_workflow') {
this.workflow_id = +newConfig.value;
// check the containing Workflows in DataStore
const allWorkflows = this.DS.get(Workflow) as Workflow[];
allWorkflows.forEach(localWorkflow => {
if (localWorkflow.isStateContained(this.state_id)) {
this.workflow = localWorkflow as Workflow;
}
});
}
this.workflow = this.DS.get(Workflow, this.workflow_id) as Workflow;
if (!this.workflow.id) {
// observe for new models
this.DS.getObservable().subscribe(newModel => {
if (newModel instanceof Workflow && newModel.id === this.workflow_id) {
this.workflow = newModel;
if (newModel instanceof Workflow) {
if (newModel.isStateContained(this.state_id)) {
this.workflow = newModel as Workflow;
}
}
});
}
}
/** add a new motionSubmitter from user-object */
/**
* add a new motionSubmitter from user-object
* @param user the user
*/
addSubmitter(user: User) {
const newSubmitter = new MotionSubmitter(null, user.id);
this.submitters.push(newSubmitter);
@ -142,6 +140,11 @@ export class Motion extends BaseModel {
}
}
/**
* Patch the current version
*
* TODO: Altering the current version should be avoided.
*/
set currentTitle(newTitle: string) {
if (this.versions[0]) {
this.versions[0].title = newTitle;
@ -221,9 +224,8 @@ export class Motion extends BaseModel {
* return the workflow state
*/
get state(): any {
if (this.state_id && this.workflow && this.workflow.id) {
const state = this.workflow.state_by_id(this.state_id);
return state;
if (this.workflow) {
return this.workflow.state_by_id(this.state_id);
} else {
return '';
}
@ -232,8 +234,12 @@ export class Motion extends BaseModel {
/**
* returns possible states for the motion
*/
get possible_states(): WorkflowState[] {
return this.workflow.states;
get nextStates(): WorkflowState[] {
if (this.workflow && this.state) {
return this.state.getNextStates(this.workflow);
} else {
return null;
}
}
/**

View File

@ -1,4 +1,6 @@
import { Deserializable } from '../deserializable.model';
import { Workflow } from './workflow';
import { MotionLog } from './motion-log';
/**
* Representation of a workflow state
@ -79,6 +81,20 @@ export class WorkflowState implements Deserializable {
this.workflow_id = workflow_id;
}
/**
* return a list of the next possible states.
* Also adds the current state.
*/
getNextStates(workflow: Workflow): WorkflowState[] {
const nextStates = [];
workflow.states.forEach(state => {
if (this.next_states_id.includes(state.id)) {
nextStates.push(state as WorkflowState);
}
});
return nextStates;
}
deserialize(input: any): this {
Object.assign(this, input);
return this;

View File

@ -21,6 +21,25 @@ export class Workflow extends BaseModel {
this.first_state = first_state;
}
/**
* Check if the containing @link{WorkflowState}s contain a given ID
* @param id The State ID
*/
isStateContained(obj: number | WorkflowState): boolean {
let id: number;
if (obj instanceof WorkflowState) {
id = obj.id;
} else {
id = obj;
}
return this.states.some(state => {
if (state.id === id) {
return true;
}
});
}
state_by_id(id: number): WorkflowState {
let targetState;
this.states.forEach(state => {

View File

@ -73,18 +73,19 @@
</div>
<!-- State -->
<div *ngIf='motion && motion.state_id || editMotion'>
<div *ngIf='!newMotion && motion && motion.workflow && motion.state_id || editMotion'>
<div *ngIf='!editMotion'>
<h3 translate>State</h3>
{{motion.state.name}}
{{motion.state}}
</div>
<mat-form-field *ngIf="editMotion">
<mat-form-field *ngIf="editMotion && !newMotion">
<mat-select placeholder='State' formControlName='state_id'>
<mat-option *ngFor="let state of motion.possible_states" [value]="state.id">{{state}}</mat-option>
<mat-option [value]="motion.state.id">{{motion.state}}</mat-option>
<mat-divider></mat-divider>
<mat-option *ngFor="let state of motion.nextStates" [value]="state.id">{{state}}</mat-option>
<mat-divider></mat-divider>
<mat-option>
<fa-icon icon='exclamation-triangle'></fa-icon>
<span translate>Reset State</span>
<fa-icon icon='exclamation-triangle'></fa-icon> <span translate>Reset State</span>
</mat-option>
</mat-select>
</mat-form-field>
@ -99,7 +100,7 @@
</div>
<mat-form-field *ngIf="motion && editMotion">
<mat-select placeholder='Recommendation' formControlName='recommendation_id'>
<mat-option *ngFor="let state of motion.possible_states" [value]="state.id">{{state}}</mat-option>
<mat-option *ngFor="let state of motion.nextStates" [value]="state.id">{{state}}</mat-option>
<mat-divider></mat-divider>
<mat-option>
<fa-icon icon='exclamation-triangle'></fa-icon>

View File

@ -133,6 +133,8 @@ export class MotionDetailComponent extends BaseComponent implements OnInit {
* http:post the motion to the server.
* The AutoUpdate-Service should see a change once it arrives and show it
* in the list view automatically
*
* TODO: state is not yet saved. Need a special "put" command
*/
saveMotion() {
const newMotionValues = { ...this.metaInfoForm.value, ...this.contentForm.value };

View File

@ -53,7 +53,7 @@
<ng-container matColumnDef="state">
<mat-header-cell *matHeaderCellDef mat-sort-header> State </mat-header-cell>
<mat-cell *matCellDef="let motion">
<div *ngIf='motion.state && motion.state.name !== "submitted"' class='innerTable'>
<div *ngIf='isDisplayIcon(motion.state) && motion.state' class='innerTable'>
<fa-icon icon={{getStateIcon(motion.state)}}></fa-icon>
</div>
</mat-cell>

View File

@ -121,6 +121,10 @@ export class MotionListComponent extends BaseComponent implements OnInit {
}
}
isDisplayIcon(state): boolean {
return state.name === 'accepted' || state.name === 'rejected' || state.name === 'not decided';
}
/**
* Download all motions As PDF and DocX
*