Merge pull request #4279 from FinnStutzenstein/previousState

Allow motions to go a state back
This commit is contained in:
Sean 2019-02-08 12:23:08 +01:00 committed by GitHub
commit 268403cc92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 27 additions and 8 deletions

View File

@ -45,13 +45,15 @@ export class WorkflowState extends Deserializer {
* Also adds the current state. * Also adds the current state.
*/ */
public getNextStates(workflow: Workflow): WorkflowState[] { public getNextStates(workflow: Workflow): WorkflowState[] {
const nextStates = []; return workflow.states.filter(state => {
workflow.states.forEach(state => { return this.next_states_id.includes(state.id);
if (this.next_states_id.includes(state.id)) { });
nextStates.push(state as WorkflowState); }
}
public getPreviousStates(workflow: Workflow): WorkflowState[] {
return workflow.states.filter(state => {
return state.next_states_id.includes(this.id);
}); });
return nextStates;
} }
public toString = (): string => { public toString = (): string => {

View File

@ -223,6 +223,9 @@
</button> </button>
<div *ngIf="perms.isAllowed('change_metadata', motion)"> <div *ngIf="perms.isAllowed('change_metadata', motion)">
<mat-divider *ngIf="motion.nextStates.length > 0"></mat-divider> <mat-divider *ngIf="motion.nextStates.length > 0"></mat-divider>
<button *ngFor="let state of motion.previousStates" mat-menu-item (click)="setState(state.id)">
<mat-icon>arrow_back</mat-icon> {{ state.name | translate }} <span *ngIf="state.show_state_extension_field">&nbsp;...</span>
</button>
<button mat-menu-item (click)="setState(null)"> <button mat-menu-item (click)="setState(null)">
<mat-icon>replay</mat-icon> {{ 'Reset state' | translate }} <mat-icon>replay</mat-icon> {{ 'Reset state' | translate }}
</button> </button>

View File

@ -1035,7 +1035,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
* @param id Motion state id * @param id Motion state id
*/ */
public setState(id: number): void { public setState(id: number): void {
this.repo.setState(this.motion, id); this.repo.setState(this.motion, id).then(null, this.raiseError);
} }
/** /**

View File

@ -194,6 +194,10 @@ export class ViewMotion extends BaseAgendaViewModel implements Searchable {
return this.state && this.workflow ? this.state.getNextStates(this.workflow.workflow) : []; return this.state && this.workflow ? this.state.getNextStates(this.workflow.workflow) : [];
} }
public get previousStates(): WorkflowState[] {
return this.state && this.workflow ? this.state.getPreviousStates(this.workflow.workflow) : [];
}
public get item(): ViewItem { public get item(): ViewItem {
return this._item; return this._item;
} }

View File

@ -1176,6 +1176,14 @@ class State(RESTModelMixin, models.Model):
f"{state} can not be next state of {self} because it does not belong to the same workflow." f"{state} can not be next state of {self} because it does not belong to the same workflow."
) )
def is_next_or_previous_state_id(self, state_id):
""" Returns true, if the given state id is a valid next or previous state """
next_state_ids = [item.id for item in self.next_states.all()]
previous_state_ids = [
item.id for item in State.objects.filter(next_states__in=[self.id])
]
return state_id in next_state_ids or state_id in previous_state_ids
def get_root_rest_element(self): def get_root_rest_element(self):
""" """
Returns the workflow to this instance which is the root REST element. Returns the workflow to this instance which is the root REST element.

View File

@ -552,6 +552,8 @@ class MotionViewSet(ModelViewSet):
Send PUT {'state': <state_id>} to set and just PUT {} to reset the Send PUT {'state': <state_id>} to set and just PUT {} to reset the
state. Only managers can use this view. state. Only managers can use this view.
If a state is given, it must be a next or previous state.
""" """
# Retrieve motion and state. # Retrieve motion and state.
motion = self.get_object() motion = self.get_object()
@ -570,7 +572,7 @@ class MotionViewSet(ModelViewSet):
raise ValidationError( raise ValidationError(
{"detail": "Invalid data. State must be an integer."} {"detail": "Invalid data. State must be an integer."}
) )
if state_id not in [item.id for item in motion.state.next_states.all()]: if not motion.state.is_next_or_previous_state_id(state_id):
raise ValidationError( raise ValidationError(
{"detail": f"You can not set the state to {state_id}."} {"detail": f"You can not set the state to {state_id}."}
) )