Editing state and recommendation in motion-list
- In the info-dialog opening in the motion-list the user can update the current state and the recommendation for one motion.
This commit is contained in:
parent
2f01e46415
commit
1354fc74ef
@ -357,7 +357,7 @@
|
|||||||
<div class="os-form-card-mobile" mat-dialog-content>
|
<div class="os-form-card-mobile" mat-dialog-content>
|
||||||
<!-- Category -->
|
<!-- Category -->
|
||||||
<mat-form-field *ngIf="isCategoryAvailable()">
|
<mat-form-field *ngIf="isCategoryAvailable()">
|
||||||
<mat-select placeholder="{{ 'Category' | translate }}" [(ngModel)]="infoDialog.category">
|
<mat-select placeholder="{{ 'Category' | translate }}" [(ngModel)]="infoDialog.category_id">
|
||||||
<mat-option [value]="null">-</mat-option>
|
<mat-option [value]="null">-</mat-option>
|
||||||
<mat-option *ngFor="let category of categories" [value]="category.id">
|
<mat-option *ngFor="let category of categories" [value]="category.id">
|
||||||
{{ category.getTitle() | translate }}
|
{{ category.getTitle() | translate }}
|
||||||
@ -366,7 +366,7 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<!-- Motion block -->
|
<!-- Motion block -->
|
||||||
<mat-form-field *ngIf="isMotionBlockAvailable()">
|
<mat-form-field *ngIf="isMotionBlockAvailable()">
|
||||||
<mat-select placeholder="{{ 'Motion block' | translate }}" [(ngModel)]="infoDialog.motionBlock">
|
<mat-select placeholder="{{ 'Motion block' | translate }}" [(ngModel)]="infoDialog.motion_block_id">
|
||||||
<mat-option [value]="null">-</mat-option>
|
<mat-option [value]="null">-</mat-option>
|
||||||
<mat-option *ngFor="let block of motionBlocks" [value]="block.id">
|
<mat-option *ngFor="let block of motionBlocks" [value]="block.id">
|
||||||
{{ block.getTitle() | translate }}
|
{{ block.getTitle() | translate }}
|
||||||
@ -375,12 +375,30 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<!-- Tag -->
|
<!-- Tag -->
|
||||||
<mat-form-field *ngIf="isTagAvailable()">
|
<mat-form-field *ngIf="isTagAvailable()">
|
||||||
<mat-select multiple placeholder="{{ 'Tags' | translate }}" [(ngModel)]="infoDialog.tags">
|
<mat-select multiple placeholder="{{ 'Tags' | translate }}" [(ngModel)]="infoDialog.tags_id">
|
||||||
<mat-option *ngFor="let tag of tags" [value]="tag.id">
|
<mat-option *ngFor="let tag of tags" [value]="tag.id">
|
||||||
{{ tag.getTitle() | translate }}
|
{{ tag.getTitle() | translate }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
|
<!-- State -->
|
||||||
|
<mat-form-field *ngIf="perms.isAllowed('change_state', selectedMotion)">
|
||||||
|
<mat-select placeholder="{{ 'State' | translate }}" [(ngModel)]="infoDialog.state_id">
|
||||||
|
<mat-option *ngFor="let state of selectedMotion.state.next_states" [value]="state.id">
|
||||||
|
{{ state.getTitle() | translate }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<!-- Recommendation -->
|
||||||
|
<mat-form-field *ngIf="perms.isAllowed('change_state', selectedMotion)">
|
||||||
|
<mat-select placeholder="{{ 'Recommendation' | translate }}" [(ngModel)]="infoDialog.recommendation_id">
|
||||||
|
<mat-option *ngFor="let state of selectedMotion.possibleRecommendations" [value]="state.id">
|
||||||
|
{{ state.recommendation_label | translate }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div mat-dialog-actions>
|
<div mat-dialog-actions>
|
||||||
|
@ -60,17 +60,27 @@ interface InfoDialog {
|
|||||||
/**
|
/**
|
||||||
* The motion block id
|
* The motion block id
|
||||||
*/
|
*/
|
||||||
motionBlock: number;
|
motion_block_id: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The category id
|
* The category id
|
||||||
*/
|
*/
|
||||||
category: number;
|
category_id: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The motions tag ids
|
* The motions tag ids
|
||||||
*/
|
*/
|
||||||
tags: number[];
|
tags_id: number[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The id of the state
|
||||||
|
*/
|
||||||
|
state_id: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The id of the recommendation
|
||||||
|
*/
|
||||||
|
recommendation_id: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,6 +108,11 @@ export class MotionListComponent extends BaseListViewComponent<ViewMotion> imple
|
|||||||
*/
|
*/
|
||||||
public selectedView: MotionListviewType;
|
public selectedView: MotionListviewType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The motion, the user has currently selected in the quick-edit-dialog.
|
||||||
|
*/
|
||||||
|
public selectedMotion: ViewMotion = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Columns to display in table when desktop view is available
|
* Columns to display in table when desktop view is available
|
||||||
* Define the columns to show
|
* Define the columns to show
|
||||||
@ -394,46 +409,48 @@ export class MotionListComponent extends BaseListViewComponent<ViewMotion> imple
|
|||||||
* Opens a dialog to edit some meta information about a motion.
|
* Opens a dialog to edit some meta information about a motion.
|
||||||
*
|
*
|
||||||
* @param motion the ViewMotion whose content is edited.
|
* @param motion the ViewMotion whose content is edited.
|
||||||
* @param ev a MouseEvent.
|
|
||||||
*/
|
*/
|
||||||
public async openEditInfo(motion: ViewMotion): Promise<void> {
|
public async openEditInfo(motion: ViewMotion): Promise<void> {
|
||||||
if (!this.isMultiSelect && this.perms.isAllowed('change_metadata')) {
|
if (this.isMultiSelect || !this.perms.isAllowed('change_metadata')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectedMotion = motion;
|
||||||
// The interface holding the current information from motion.
|
// The interface holding the current information from motion.
|
||||||
this.infoDialog = {
|
this.infoDialog = {
|
||||||
title: motion.title,
|
title: motion.title,
|
||||||
motionBlock: motion.motion_block_id,
|
motion_block_id: motion.motion_block_id,
|
||||||
category: motion.category_id,
|
category_id: motion.category_id,
|
||||||
tags: motion.tags_id
|
tags_id: motion.tags_id,
|
||||||
|
state_id: motion.state_id,
|
||||||
|
recommendation_id: motion.recommendation_id
|
||||||
};
|
};
|
||||||
|
|
||||||
// Copies the interface to check, if changes were made.
|
|
||||||
const copyDialog = { ...this.infoDialog };
|
|
||||||
|
|
||||||
const dialogRef = this.dialog.open(this.motionInfoDialog, infoDialogSettings);
|
const dialogRef = this.dialog.open(this.motionInfoDialog, infoDialogSettings);
|
||||||
|
|
||||||
dialogRef.keydownEvents().subscribe((event: KeyboardEvent) => {
|
dialogRef.keydownEvents().subscribe((event: KeyboardEvent) => {
|
||||||
if (event.key === 'Enter' && event.shiftKey) {
|
if (event.key === 'Enter' && event.shiftKey) {
|
||||||
dialogRef.close(this.infoDialog);
|
dialogRef.close(this.infoDialog);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// After closing the dialog: Goes through the fields and check if they are changed
|
const result: InfoDialog = await dialogRef.afterClosed().toPromise();
|
||||||
// TODO: Logic like this should be handled in a service
|
|
||||||
dialogRef.afterClosed().subscribe(async (result: InfoDialog) => {
|
|
||||||
if (result) {
|
if (result) {
|
||||||
const partialUpdate = {
|
delete result.title; // Do not update the title!
|
||||||
category_id: result.category !== copyDialog.category ? result.category : undefined,
|
|
||||||
motion_block_id: result.motionBlock !== copyDialog.motionBlock ? result.motionBlock : undefined,
|
try {
|
||||||
tags_id:
|
await this.motionRepo.patch(result, motion);
|
||||||
JSON.stringify(result.tags) !== JSON.stringify(copyDialog.tags) ? result.tags : undefined
|
if (result.state_id !== motion.state_id) {
|
||||||
};
|
await this.motionRepo.setState(motion, result.state_id);
|
||||||
// TODO: "only update if different" was another repo-todo
|
}
|
||||||
if (!Object.keys(partialUpdate).every(key => partialUpdate[key] === undefined)) {
|
if (result.recommendation_id !== motion.recommendation_id) {
|
||||||
await this.motionRepo.update(partialUpdate, motion).catch(this.raiseError);
|
await this.motionRepo.setRecommendation(motion, result.recommendation_id);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.raiseError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
this.selectedMotion = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -425,7 +425,9 @@ class MotionSerializer(ModelSerializer):
|
|||||||
text = CharField(allow_blank=True, required=False) # This will be checked
|
text = CharField(allow_blank=True, required=False) # This will be checked
|
||||||
# during validation
|
# during validation
|
||||||
title = CharField(max_length=255)
|
title = CharField(max_length=255)
|
||||||
amendment_paragraphs = AmendmentParagraphsJSONSerializerField(required=False)
|
amendment_paragraphs = AmendmentParagraphsJSONSerializerField(
|
||||||
|
required=False, allow_null=True
|
||||||
|
)
|
||||||
workflow_id = IntegerField(
|
workflow_id = IntegerField(
|
||||||
min_value=1, required=False, validators=[validate_workflow_field]
|
min_value=1, required=False, validators=[validate_workflow_field]
|
||||||
)
|
)
|
||||||
@ -496,7 +498,7 @@ class MotionSerializer(ModelSerializer):
|
|||||||
data["reason"] = validate_html(data["reason"])
|
data["reason"] = validate_html(data["reason"])
|
||||||
|
|
||||||
# The motion text is only needed, if it is not a paragraph based amendment.
|
# The motion text is only needed, if it is not a paragraph based amendment.
|
||||||
if "amendment_paragraphs" in data:
|
if data.get("amendment_paragraphs") is not None:
|
||||||
data["amendment_paragraphs"] = list(
|
data["amendment_paragraphs"] = list(
|
||||||
map(
|
map(
|
||||||
lambda entry: validate_html(entry)
|
lambda entry: validate_html(entry)
|
||||||
|
Loading…
Reference in New Issue
Block a user