Merge pull request #4062 from FinnStutzenstein/modified-final-version

Modified final version
This commit is contained in:
Sean 2019-01-29 18:31:38 +01:00 committed by GitHub
commit 00b15228f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 155 additions and 51 deletions

View File

@ -76,11 +76,7 @@
<span translate>Project</span> <span translate>Project</span>
</button> </button>
<!-- New amendment --> <!-- New amendment -->
<button <button mat-menu-item (click)="createAmendment()" *ngIf="perms.isAllowed('can_create_amendments', motion)">
mat-menu-item
(click)="createAmendment()"
*ngIf="perms.isAllowed('can_create_amendments', motion)"
>
<mat-icon>add</mat-icon> <mat-icon>add</mat-icon>
<span translate>New amendment</span> <span translate>New amendment</span>
</button> </button>
@ -128,7 +124,9 @@
<mat-divider *ngIf="!editMotion" class="spacer-top-10 spacer-bottom-20"></mat-divider> <mat-divider *ngIf="!editMotion" class="spacer-top-10 spacer-bottom-20"></mat-divider>
<!-- Content --> <!-- Content -->
<div class="hspacing" [ngClass]="editMotion ? 'os-form-card-mobile' : 'os-card-mobile'"><ng-container *ngTemplateOutlet="contentTemplate"></ng-container></div> <div class="hspacing" [ngClass]="editMotion ? 'os-form-card-mobile' : 'os-card-mobile'">
<ng-container *ngTemplateOutlet="contentTemplate"></ng-container>
</div>
<mat-divider *ngIf="!editMotion" class="spacer-top-10 spacer-bottom-20"></mat-divider> <mat-divider *ngIf="!editMotion" class="spacer-top-10 spacer-bottom-20"></mat-divider>
@ -209,8 +207,7 @@
<h4 translate>State</h4> <h4 translate>State</h4>
<mat-menu #stateMenu="matMenu"> <mat-menu #stateMenu="matMenu">
<button *ngFor="let state of motion.nextStates" mat-menu-item (click)="setState(state.id)"> <button *ngFor="let state of motion.nextStates" mat-menu-item (click)="setState(state.id)">
{{ state.name | translate }} {{ state.name | translate }} <span *ngIf="state.show_state_extension_field">&nbsp;...</span>
<span *ngIf="state.show_state_extension_field">&nbsp;...</span>
</button> </button>
<mat-divider></mat-divider> <mat-divider></mat-divider>
<button mat-menu-item (click)="setState(null)" *ngIf="perms.isAllowed('change_metadata', motion)"> <button mat-menu-item (click)="setState(null)" *ngIf="perms.isAllowed('change_metadata', motion)">
@ -223,18 +220,13 @@
</mat-basic-chip> </mat-basic-chip>
<div *ngIf="motion.state.show_state_extension_field" class="spacer-top-10"> <div *ngIf="motion.state.show_state_extension_field" class="spacer-top-10">
<mat-form-field> <mat-form-field>
<input matInput placeholder="{{ 'Extension' | translate }}" <input matInput placeholder="{{ 'Extension' | translate }}" [(ngModel)]="newStateExtension" />
[(ngModel)]="newStateExtension"/>
</mat-form-field> </mat-form-field>
<button mat-icon-button (click)="setStateExtension()"> <button mat-icon-button (click)="setStateExtension()"><mat-icon>check</mat-icon></button>
<mat-icon>check</mat-icon>
</button>
</div> </div>
</div> </div>
<div *ngIf="!perms.isAllowed('change_metadata', motion)"> <div *ngIf="!perms.isAllowed('change_metadata', motion)">
<mat-basic-chip [ngClass]="getStateCssColor()" > <mat-basic-chip [ngClass]="getStateCssColor()"> {{ stateLabel }} </mat-basic-chip>
{{ stateLabel }}
</mat-basic-chip>
</div> </div>
</div> </div>
@ -251,8 +243,11 @@
<span *ngIf="recommendation.show_recommendation_extension_field">&nbsp;...</span> <span *ngIf="recommendation.show_recommendation_extension_field">&nbsp;...</span>
</button> </button>
<mat-divider></mat-divider> <mat-divider></mat-divider>
<button mat-menu-item *ngIf="perms.isAllowed('change_metadata', motion)" <button
(click)="setRecommendation(null)"> mat-menu-item
*ngIf="perms.isAllowed('change_metadata', motion)"
(click)="setRecommendation(null)"
>
<mat-icon>replay</mat-icon> {{ 'Reset recommendation' | translate }} <mat-icon>replay</mat-icon> {{ 'Reset recommendation' | translate }}
</button> </button>
</mat-menu> </mat-menu>
@ -260,21 +255,22 @@
<mat-basic-chip [matMenuTriggerFor]="recommendationMenu" class="bluegrey"> <mat-basic-chip [matMenuTriggerFor]="recommendationMenu" class="bluegrey">
{{ recommendationLabel }} {{ recommendationLabel }}
</mat-basic-chip> </mat-basic-chip>
<div *ngIf="motion.recommendation && motion.recommendation.show_recommendation_extension_field" <div
class="spacer-top-10"> *ngIf="motion.recommendation && motion.recommendation.show_recommendation_extension_field"
class="spacer-top-10"
>
<mat-form-field> <mat-form-field>
<input matInput placeholder="{{ 'Extension' | translate }}" <input
[(ngModel)]="newRecommendationExtension"/> matInput
placeholder="{{ 'Extension' | translate }}"
[(ngModel)]="newRecommendationExtension"
/>
</mat-form-field> </mat-form-field>
<button mat-icon-button (click)="setRecommendationExtension()"> <button mat-icon-button (click)="setRecommendationExtension()"><mat-icon>check</mat-icon></button>
<mat-icon>check</mat-icon>
</button>
</div> </div>
</div> </div>
<div *ngIf="!perms.isAllowed('change_metadata', motion)"> <div *ngIf="!perms.isAllowed('change_metadata', motion)">
<mat-basic-chip class="bluegrey"> <mat-basic-chip class="bluegrey"> {{ recommendationLabel }} </mat-basic-chip>
{{ recommendationLabel }}
</mat-basic-chip>
</div> </div>
<button mat-button *ngIf="canFollowRecommendation()" (click)="onFollowRecButton()"> <button mat-button *ngIf="canFollowRecommendation()" (click)="onFollowRecButton()">
<span translate>Follow recommendation</span> <span translate>Follow recommendation</span>
@ -295,7 +291,11 @@
{{ category }} {{ category }}
</button> </button>
</mat-menu> </mat-menu>
<mat-basic-chip *ngIf="perms.isAllowed('change_metadata', motion)" [matMenuTriggerFor]="categoryMenu" class="grey"> <mat-basic-chip
*ngIf="perms.isAllowed('change_metadata', motion)"
[matMenuTriggerFor]="categoryMenu"
class="grey"
>
{{ motion.category ? motion.category : '' }} {{ motion.category ? motion.category : '' }}
</mat-basic-chip> </mat-basic-chip>
<mat-basic-chip *ngIf="!perms.isAllowed('change_metadata', motion)" class="grey"> <mat-basic-chip *ngIf="!perms.isAllowed('change_metadata', motion)" class="grey">
@ -312,7 +312,11 @@
{{ block }} {{ block }}
</button> </button>
</mat-menu> </mat-menu>
<mat-basic-chip *ngIf="perms.isAllowed('change_metadata', motion)" [matMenuTriggerFor]="blockMenu" class="grey"> <mat-basic-chip
*ngIf="perms.isAllowed('change_metadata', motion)"
[matMenuTriggerFor]="blockMenu"
class="grey"
>
{{ motion.motion_block ? motion.motion_block : '' }} {{ motion.motion_block ? motion.motion_block : '' }}
</mat-basic-chip> </mat-basic-chip>
<mat-basic-chip *ngIf="!perms.isAllowed('change_metadata', motion)" class="grey"> <mat-basic-chip *ngIf="!perms.isAllowed('change_metadata', motion)" class="grey">
@ -367,6 +371,26 @@
> >
<mat-icon>rate_review</mat-icon> <mat-icon>rate_review</mat-icon>
</button> </button>
<button
type="button"
mat-icon-button
matTooltip="{{ 'Create final print template' | translate }}"
*ngIf="isRecoMode(ChangeRecoMode.Final)"
(click)="createModifiedFinalVersion()"
>
<mat-icon>description</mat-icon>
</button>
<button
type="button"
class="red-warning-text"
mat-button
matTooltip="{{ 'Delete final print template' | translate }}"
*ngIf="isRecoMode(ChangeRecoMode.ModifiedFinal)"
(click)="deleteModifiedFinalVersion()"
>
<mat-icon>description</mat-icon>
</button>
</div> </div>
<!-- Selecting statute paragraphs for amendment --> <!-- Selecting statute paragraphs for amendment -->
@ -436,26 +460,26 @@
<!-- Regular motions or traditional amendments --> <!-- Regular motions or traditional amendments -->
<ng-container *ngIf="!editMotion && !motion.isStatuteAmendment() && !motion.isParagraphBasedAmendment()"> <ng-container *ngIf="!editMotion && !motion.isStatuteAmendment() && !motion.isParagraphBasedAmendment()">
<div <div
*ngIf="!isRecoModeDiff()" *ngIf="!isRecoMode(ChangeRecoMode.Diff)"
class="motion-text" class="motion-text"
[class.line-numbers-none]="isLineNumberingNone()" [class.line-numbers-none]="isLineNumberingNone()"
[class.line-numbers-inline]="isLineNumberingInline()" [class.line-numbers-inline]="isLineNumberingInline()"
[class.line-numbers-outside]="isLineNumberingOutside()" [class.line-numbers-outside]="isLineNumberingOutside()"
> >
<os-motion-detail-original-change-recommendations <os-motion-detail-original-change-recommendations
*ngIf="isLineNumberingOutside() && isRecoModeOriginal()" *ngIf="isLineNumberingOutside() && isRecoMode(ChangeRecoMode.Original)"
[html]="getFormattedTextPlain()" [html]="getFormattedTextPlain()"
[changeRecommendations]="changeRecommendations" [changeRecommendations]="changeRecommendations"
(createChangeRecommendation)="createChangeRecommendation($event)" (createChangeRecommendation)="createChangeRecommendation($event)"
(gotoChangeRecommendation)="gotoChangeRecommendation($event)" (gotoChangeRecommendation)="gotoChangeRecommendation($event)"
></os-motion-detail-original-change-recommendations> ></os-motion-detail-original-change-recommendations>
<div <div
*ngIf="!isLineNumberingOutside() || !isRecoModeOriginal()" *ngIf="!isLineNumberingOutside() || !isRecoMode(ChangeRecoMode.Original)"
[innerHTML]="sanitizedText(getFormattedTextPlain())" [innerHTML]="sanitizedText(getFormattedTextPlain())"
></div> ></div>
</div> </div>
<os-motion-detail-diff <os-motion-detail-diff
*ngIf="isRecoModeDiff()" *ngIf="isRecoMode(ChangeRecoMode.Diff)"
[motion]="motion" [motion]="motion"
[changes]="allChangingObjects" [changes]="allChangingObjects"
[scrollToChange]="scrollToChange" [scrollToChange]="scrollToChange"
@ -695,4 +719,13 @@
> >
Final version Final version
</button> </button>
<button
mat-menu-item
translate
*ngIf="motion?.modified_final_version"
(click)="setChangeRecoMode(ChangeRecoMode.ModifiedFinal)"
[ngClass]="{ selected: motion?.crMode === ChangeRecoMode.ModifiedFinal }"
>
Final print template
</button>
</mat-menu> </mat-menu>

View File

@ -38,6 +38,7 @@ import { ViewportService } from '../../../../core/services/viewport.service';
import { ViewUnifiedChange } from '../../models/view-unified-change'; import { ViewUnifiedChange } from '../../models/view-unified-change';
import { ViewStatuteParagraph } from '../../models/view-statute-paragraph'; import { ViewStatuteParagraph } from '../../models/view-statute-paragraph';
import { Workflow } from 'app/shared/models/motions/workflow'; import { Workflow } from 'app/shared/models/motions/workflow';
import { LinenumberingService } from '../../services/linenumbering.service';
/** /**
* Component for the motion detail view * Component for the motion detail view
@ -336,7 +337,8 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
private sanitizer: DomSanitizer, private sanitizer: DomSanitizer,
private promptService: PromptService, private promptService: PromptService,
private pdfExport: MotionPdfExportService, private pdfExport: MotionPdfExportService,
private personalNoteService: PersonalNoteService private personalNoteService: PersonalNoteService,
private linenumberingService: LinenumberingService
) { ) {
super(title, translate, matSnackBar); super(title, translate, matSnackBar);
@ -599,10 +601,14 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
/** /**
* Save a motion. Calls the "patchValues" function in the MotionObject * Save a motion. Calls the "patchValues" function in the MotionObject
*/ */
public async updateMotion(): Promise<void> { private updateMotionFromForm(): void {
const newMotionValues = { ...this.contentForm.value }; const newMotionValues = { ...this.contentForm.value };
const motion = this.prepareMotionForSave(newMotionValues, Motion); this.updateMotion(newMotionValues, this.motionCopy).then(() => (this.editMotion = false), this.raiseError);
this.repo.update(motion, this.motionCopy).then(() => (this.editMotion = false), this.raiseError); }
private async updateMotion(newMotionValues: Partial<Motion>, motion: ViewMotion): Promise<void> {
const updateMotion = this.prepareMotionForSave(newMotionValues, Motion);
await this.repo.update(updateMotion, motion);
} }
/** /**
@ -612,7 +618,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
if (this.newMotion) { if (this.newMotion) {
this.createMotion(); this.createMotion();
} else { } else {
this.updateMotion(); this.updateMotionFromForm();
} }
} }
@ -719,24 +725,20 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
/** /**
* Sets the motions change reco mode * Sets the motions change reco mode
* @param mode Needs to fot to the enum defined in ViewMotion * @param mode The mode
*/ */
public setChangeRecoMode(mode: ChangeRecoMode): void { public setChangeRecoMode(mode: ChangeRecoMode): void {
this.crMode = mode; this.crMode = mode;
} }
/** /**
* Returns true if the original version (including change recommendation annotation) is to be shown * Returns true if the given version is to be shown
*
* @param mode The mode to check
* @returns true, if the mode is shown
*/ */
public isRecoModeOriginal(): boolean { public isRecoMode(mode: ChangeRecoMode): boolean {
return this.crMode === ChangeRecoMode.Original || this.allChangingObjects.length === 0; return this.crMode === mode;
}
/**
* Returns true if the diff version is to be shown
*/
public isRecoModeDiff(): boolean {
return this.crMode === ChangeRecoMode.Diff && this.allChangingObjects.length > 0;
} }
/** /**
@ -779,6 +781,51 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
this.router.navigate(['./create-amendment'], { relativeTo: this.route }); this.router.navigate(['./create-amendment'], { relativeTo: this.route });
} }
/**
* Sets the modified final version to the final version.
*/
public async createModifiedFinalVersion(): Promise<void> {
// Get the final version and remove line numbers
const changes: ViewUnifiedChange[] = Object.assign([], this.allChangingObjects);
let finalVersion = this.repo.formatMotion(
this.motion.id,
ChangeRecoMode.Final,
changes,
this.lineLength,
this.highlightedLine
);
finalVersion = this.linenumberingService.stripLineNumbers(finalVersion);
// Update the motion
try {
// Just confirm this, if there is one modified final version the user would override.
if (this.motion.modified_final_version) {
const content = this.translate.instant('Are you sure to copy the final version to the print template?');
if (await this.promptService.open(this.motion.title, content)) {
await this.updateMotion({ modified_final_version: finalVersion }, this.motion);
}
} else {
await this.updateMotion({ modified_final_version: finalVersion }, this.motion);
}
} catch (e) {
this.raiseError(e);
}
this.setChangeRecoMode(ChangeRecoMode.ModifiedFinal);
}
/**
* Deletes the modified final version
*/
public async deleteModifiedFinalVersion(): Promise<void> {
const content = this.translate.instant('Are you sure to delete the print template?');
if (await this.promptService.open(this.motion.title, content)) {
this.updateMotion({ modified_final_version: '' }, this.motion).then(
() => this.setChangeRecoMode(ChangeRecoMode.Final),
this.raiseError
);
}
}
/** /**
* Comes from the head bar * Comes from the head bar
* *

View File

@ -30,7 +30,8 @@ export enum ChangeRecoMode {
Original = 'original', Original = 'original',
Changed = 'changed', Changed = 'changed',
Diff = 'diff', Diff = 'diff',
Final = 'agreed' Final = 'agreed',
ModifiedFinal = 'modified_final_version'
} }
/** /**
@ -89,6 +90,16 @@ export class ViewMotion extends BaseProjectableModel {
return this.motion ? this.motion.reason : null; return this.motion ? this.motion.reason : null;
} }
public get modified_final_version(): string {
return this.motion ? this.motion.modified_final_version : null;
}
public set modified_final_version(value: string) {
if (this.motion) {
this.motion.modified_final_version = value;
}
}
public get weight(): number { public get weight(): number {
return this.motion ? this.motion.weight : null; return this.motion ? this.motion.weight : null;
} }

View File

@ -343,6 +343,19 @@ export class MotionRepositoryService extends BaseRepository<ViewMotion, Motion>
case ChangeRecoMode.Final: case ChangeRecoMode.Final:
const appliedChanges: ViewUnifiedChange[] = changes.filter(change => change.isAccepted()); const appliedChanges: ViewUnifiedChange[] = changes.filter(change => change.isAccepted());
return this.diff.getTextWithChanges(targetMotion, appliedChanges, lineLength, highlightLine); return this.diff.getTextWithChanges(targetMotion, appliedChanges, lineLength, highlightLine);
case ChangeRecoMode.ModifiedFinal:
if (targetMotion.modified_final_version) {
return this.lineNumbering.insertLineNumbers(
targetMotion.modified_final_version,
lineLength,
highlightLine,
null,
1
);
} else {
// Use the final version as fallback, if the modified does not exist.
return this.formatMotion(id, ChangeRecoMode.Final, changes, lineLength, highlightLine);
}
default: default:
console.error('unrecognized ChangeRecoMode option (' + crMode + ')'); console.error('unrecognized ChangeRecoMode option (' + crMode + ')');
return null; return null;