Merge pull request #4487 from CatoTH/OS3-Bugfix-Amendment-Status-Handling

Bugfix: Amendment statuses
This commit is contained in:
Emanuel Schütze 2019-03-09 23:14:29 +01:00 committed by GitHub
commit 0419ea629f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 160 additions and 75 deletions

View File

@ -485,32 +485,36 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
return this.diff.getTextWithChanges(targetMotion.text, changes, lineLength, highlightLine); return this.diff.getTextWithChanges(targetMotion.text, changes, lineLength, highlightLine);
case ChangeRecoMode.Diff: case ChangeRecoMode.Diff:
let text = ''; let text = '';
changes.forEach((change: ViewUnifiedChange, idx: number) => { changes
if (idx === 0) { .filter(change => {
text += this.extractMotionLineRange( return change.showInDiffView();
id, })
{ .forEach((change: ViewUnifiedChange, idx: number) => {
from: 1, if (idx === 0) {
to: change.getLineFrom() text += this.extractMotionLineRange(
}, id,
true, {
lineLength, from: 1,
highlightLine to: change.getLineFrom()
); },
} else if (changes[idx - 1].getLineTo() < change.getLineFrom()) { true,
text += this.extractMotionLineRange( lineLength,
id, highlightLine
{ );
from: changes[idx - 1].getLineTo(), } else if (changes[idx - 1].getLineTo() < change.getLineFrom()) {
to: change.getLineFrom() text += this.extractMotionLineRange(
}, id,
true, {
lineLength, from: changes[idx - 1].getLineTo(),
highlightLine to: change.getLineFrom()
); },
} true,
text += this.diff.getChangeDiff(targetMotion.text, change, lineLength, highlightLine); lineLength,
}); highlightLine
);
}
text += this.diff.getChangeDiff(targetMotion.text, change, lineLength, highlightLine);
});
text += this.diff.getTextRemainderAfterLastChange( text += this.diff.getTextRemainderAfterLastChange(
targetMotion.text, targetMotion.text,
changes, changes,
@ -519,7 +523,7 @@ export class MotionRepositoryService extends BaseAgendaContentObjectRepository<V
); );
return text; return text;
case ChangeRecoMode.Final: case ChangeRecoMode.Final:
const appliedChanges: ViewUnifiedChange[] = changes.filter(change => change.isAccepted()); const appliedChanges: ViewUnifiedChange[] = changes.filter(change => change.showInFinalView());
return this.diff.getTextWithChanges(targetMotion.text, appliedChanges, lineLength, highlightLine); return this.diff.getTextWithChanges(targetMotion.text, appliedChanges, lineLength, highlightLine);
case ChangeRecoMode.ModifiedFinal: case ChangeRecoMode.ModifiedFinal:
if (targetMotion.modified_final_version) { if (targetMotion.modified_final_version) {

View File

@ -43,4 +43,19 @@ export interface ViewUnifiedChange {
* True, if rejected. False, if accepted or undecided. * True, if rejected. False, if accepted or undecided.
*/ */
isRejected(): boolean; isRejected(): boolean;
/**
* If this object is to be shown in the Diff view.
*/
showInDiffView(): boolean;
/**
* If this object is to be shown in the Diff view.
*/
showInDiffView(): boolean;
/**
* If this object is to be shown in the Final view.
*/
showInFinalView(): boolean;
} }

View File

@ -105,4 +105,12 @@ export class ViewMotionChangeRecommendation extends BaseViewModel implements Vie
public isRejected(): boolean { public isRejected(): boolean {
return this.rejected; return this.rejected;
} }
public showInDiffView(): boolean {
return true;
}
public showInFinalView(): boolean {
return !this.rejected;
}
} }

View File

@ -79,4 +79,32 @@ export class ViewMotionAmendedParagraph implements ViewUnifiedChange {
public getIdentifier(): string { public getIdentifier(): string {
return this.amendment.identifier; return this.amendment.identifier;
} }
public showInDiffView(): boolean {
const mergeState = this.amendment.state
? this.amendment.state.merge_amendment_into_final
: MergeAmendment.UNDEFINED;
switch (mergeState) {
case MergeAmendment.YES:
return true;
case MergeAmendment.NO:
return false;
default:
const mergeRecommendation = this.amendment.recommendation
? this.amendment.recommendation.merge_amendment_into_final
: MergeAmendment.UNDEFINED;
switch (mergeRecommendation) {
case MergeAmendment.YES:
return true;
case MergeAmendment.NO:
return false;
default:
return false;
}
}
}
public showInFinalView(): boolean {
return this.amendment.state && this.amendment.state.merge_amendment_into_final === MergeAmendment.YES;
}
} }

View File

@ -28,8 +28,8 @@
--> -->
</span> </span>
<span class="status"> <span class="status">
<ng-container *ngIf="change.isRejected()"><span translate>Rejected</span></ng-container> <ng-container *ngIf="change.isRejected()"> <span translate>Rejected</span></ng-container>
<ng-container *ngIf="change.isAccepted() && isAmendment(change)"><span translate>Accepted</span></ng-container> <ng-container *ngIf="change.isAccepted() && isAmendment(change)"> {{ change.amendment.state.name | translate }}</ng-container>
</span> </span>
</a> </a>
</li> </li>

View File

@ -93,14 +93,6 @@
.status { .status {
color: gray; color: gray;
font-style: italic; font-style: italic;
& > *:before {
content: '(';
}
& > *:after {
content: ')';
}
} }
.no-changes { .no-changes {

View File

@ -201,21 +201,6 @@ export class MotionDetailDiffComponent extends BaseViewComponent implements Afte
return this.lineNumberingMode === LineNumberingMode.Outside; return this.lineNumberingMode === LineNumberingMode.Outside;
} }
/**
* Returns accepted, rejected or an empty string depending on the state of this change.
*
* @param change
*/
public getAcceptanceValue(change: ViewUnifiedChange): string {
if (change.isAccepted()) {
return 'accepted';
}
if (change.isRejected()) {
return 'rejected';
}
return '';
}
/** /**
* Returns true if the change is an Amendment * Returns true if the change is an Amendment
* *

View File

@ -608,7 +608,7 @@
<os-motion-detail-diff <os-motion-detail-diff
*ngIf="isRecoMode(ChangeRecoMode.Diff)" *ngIf="isRecoMode(ChangeRecoMode.Diff)"
[motion]="motion" [motion]="motion"
[changes]="allChangingObjects" [changes]="getChangesForDiffMode()"
[scrollToChange]="scrollToChange" [scrollToChange]="scrollToChange"
[highlightedLine]="highlightedLine" [highlightedLine]="highlightedLine"
[lineNumberingMode]="lnMode" [lineNumberingMode]="lnMode"

View File

@ -838,6 +838,18 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
return this.sanitizer.bypassSecurityTrustHtml(diffHtml); return this.sanitizer.bypassSecurityTrustHtml(diffHtml);
} }
public getChangesForDiffMode(): ViewUnifiedChange[] {
return this.allChangingObjects.filter(change => {
return change.showInDiffView();
});
}
public getChangesForFinalMode(): ViewUnifiedChange[] {
return this.allChangingObjects.filter(change => {
return change.showInFinalView();
});
}
/** /**
* Trigger to delete the motion. * Trigger to delete the motion.
*/ */
@ -975,7 +987,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit,
*/ */
public async createModifiedFinalVersion(): Promise<void> { public async createModifiedFinalVersion(): Promise<void> {
// Get the final version and remove line numbers // Get the final version and remove line numbers
const changes: ViewUnifiedChange[] = Object.assign([], this.allChangingObjects); const changes: ViewUnifiedChange[] = Object.assign([], this.getChangesForFinalMode());
let finalVersion = this.repo.formatMotion( let finalVersion = this.repo.formatMotion(
this.motion.id, this.motion.id,
ChangeRecoMode.Final, ChangeRecoMode.Final,

View File

@ -1,5 +1,4 @@
import { ChangeRecoMode, LineNumberingMode } from '../../../site/motions/models/view-motion'; import { ChangeRecoMode, LineNumberingMode } from '../../../site/motions/models/view-motion';
import { MergeAmendment } from '../../../shared/models/motions/workflow-state';
import { ReferencedMotions } from '../base/base-motion-slide'; import { ReferencedMotions } from '../base/base-motion-slide';
/** /**
@ -10,7 +9,8 @@ export interface MotionSlideDataAmendment {
id: number; id: number;
title: string; title: string;
amendment_paragraphs: string[]; amendment_paragraphs: string[];
merge_amendment_into_final: MergeAmendment; merge_amendment_into_final: number;
merge_amendment_into_diff: number;
} }
/** /**

View File

@ -1,6 +1,5 @@
import { ViewUnifiedChange, ViewUnifiedChangeType } from '../../../shared/models/motions/view-unified-change'; import { ViewUnifiedChange, ViewUnifiedChangeType } from '../../../shared/models/motions/view-unified-change';
import { MotionSlideDataAmendment } from './motion-slide-data'; import { MotionSlideDataAmendment } from './motion-slide-data';
import { MergeAmendment } from '../../../shared/models/motions/workflow-state';
import { LineRange } from '../../../core/ui-services/diff.service'; import { LineRange } from '../../../core/ui-services/diff.service';
/** /**
@ -10,7 +9,8 @@ import { LineRange } from '../../../core/ui-services/diff.service';
export class MotionSlideObjAmendmentParagraph implements ViewUnifiedChange { export class MotionSlideObjAmendmentParagraph implements ViewUnifiedChange {
public id: number; public id: number;
public type: number; public type: number;
public merge_amendment_into_final: MergeAmendment; public merge_amendment_into_final: number;
public merge_amendment_into_diff: number;
public constructor( public constructor(
data: MotionSlideDataAmendment, data: MotionSlideDataAmendment,
@ -20,6 +20,7 @@ export class MotionSlideObjAmendmentParagraph implements ViewUnifiedChange {
) { ) {
this.id = data.id; this.id = data.id;
this.merge_amendment_into_final = data.merge_amendment_into_final; this.merge_amendment_into_final = data.merge_amendment_into_final;
this.merge_amendment_into_diff = data.merge_amendment_into_diff;
} }
public getChangeId(): string { public getChangeId(): string {
@ -43,10 +44,18 @@ export class MotionSlideObjAmendmentParagraph implements ViewUnifiedChange {
} }
public isAccepted(): boolean { public isAccepted(): boolean {
return this.merge_amendment_into_final === MergeAmendment.YES; return this.merge_amendment_into_final === 1;
} }
public isRejected(): boolean { public isRejected(): boolean {
return this.merge_amendment_into_final === MergeAmendment.NO; return this.merge_amendment_into_final === 0;
}
public showInDiffView(): boolean {
return this.merge_amendment_into_diff === 1;
}
public showInFinalView(): boolean {
return this.merge_amendment_into_final === 1;
} }
} }

View File

@ -48,4 +48,12 @@ export class MotionSlideObjChangeReco implements MotionSlideDataChangeReco, View
public isRejected(): boolean { public isRejected(): boolean {
return this.rejected; return this.rejected;
} }
public showInDiffView(): boolean {
return true;
}
public showInFinalView(): boolean {
return !this.rejected;
}
} }

View File

@ -275,13 +275,16 @@ export class MotionSlideComponent extends BaseMotionSlideComponent<MotionSlideDa
); );
case ChangeRecoMode.Diff: case ChangeRecoMode.Diff:
let text = ''; let text = '';
this.allChangingObjects.forEach((change: ViewUnifiedChange, idx: number) => { const changes = this.allChangingObjects.filter(change => {
return change.showInDiffView();
});
changes.forEach((change: ViewUnifiedChange, idx: number) => {
if (idx === 0) { if (idx === 0) {
const lineRange = { from: 1, to: change.getLineFrom() }; const lineRange = { from: 1, to: change.getLineFrom() };
text += this.extractMotionLineRange(motion.text, lineRange, true, this.lineLength); text += this.extractMotionLineRange(motion.text, lineRange, true, this.lineLength);
} else if (this.allChangingObjects[idx - 1].getLineTo() < change.getLineFrom()) { } else if (changes[idx - 1].getLineTo() < change.getLineFrom()) {
const lineRange = { const lineRange = {
from: this.allChangingObjects[idx - 1].getLineTo(), from: changes[idx - 1].getLineTo(),
to: change.getLineFrom() to: change.getLineFrom()
}; };
text += this.extractMotionLineRange(motion.text, lineRange, true, this.lineLength); text += this.extractMotionLineRange(motion.text, lineRange, true, this.lineLength);
@ -290,14 +293,14 @@ export class MotionSlideComponent extends BaseMotionSlideComponent<MotionSlideDa
}); });
text += this.diff.getTextRemainderAfterLastChange( text += this.diff.getTextRemainderAfterLastChange(
motion.text, motion.text,
this.allChangingObjects, changes,
this.lineLength, this.lineLength,
this.highlightedLine this.highlightedLine
); );
return text; return text;
case ChangeRecoMode.Final: case ChangeRecoMode.Final:
const appliedChanges: ViewUnifiedChange[] = this.allChangingObjects.filter(change => const appliedChanges: ViewUnifiedChange[] = this.allChangingObjects.filter(change =>
change.isAccepted() change.showInFinalView()
); );
return this.diff.getTextWithChanges(motion.text, appliedChanges, this.lineLength, this.highlightedLine); return this.diff.getTextWithChanges(motion.text, appliedChanges, this.lineLength, this.highlightedLine);
case ChangeRecoMode.ModifiedFinal: case ChangeRecoMode.ModifiedFinal:
@ -312,7 +315,7 @@ export class MotionSlideComponent extends BaseMotionSlideComponent<MotionSlideDa
} else { } else {
// Use the final version as fallback, if the modified does not exist. // Use the final version as fallback, if the modified does not exist.
const appliedChangeObjects: ViewUnifiedChange[] = this.allChangingObjects.filter(change => const appliedChangeObjects: ViewUnifiedChange[] = this.allChangingObjects.filter(change =>
change.isAccepted() change.showInFinalView()
); );
return this.diff.getTextWithChanges( return this.diff.getTextWithChanges(
motion.text, motion.text,

View File

@ -35,31 +35,50 @@ def get_state(
) )
def get_amendment_merge_into_motion(all_data, motion, amendment): def get_amendment_merge_into_motion_diff(all_data, motion, amendment):
""" """
HINT: This implementation should be consistent to isAccepted() in ViewMotionAmendedParagraph.ts HINT: This implementation should be consistent to showInDiffView() in ViewMotionAmendedParagraph.ts
""" """
if amendment["state_id"] is None: if amendment["state_id"] is None:
return 0 return 0
state = get_state(all_data, motion, amendment["state_id"]) state = get_state(all_data, motion, amendment["state_id"])
if ( if state["merge_amendment_into_final"] == -1:
state["merge_amendment_into_final"] == -1 return 0
or state["merge_amendment_into_final"] == 1 if state["merge_amendment_into_final"] == 1:
): return 1
return state["merge_amendment_into_final"]
if amendment["recommendation_id"] is None: if amendment["recommendation_id"] is None:
return 0 return 0
recommendation = get_state(all_data, motion, amendment["recommendation_id"]) recommendation = get_state(all_data, motion, amendment["recommendation_id"])
return recommendation["merge_amendment_into_final"] if recommendation["merge_amendment_into_final"] == 1:
return 1
return 0
def get_amendment_merge_into_motion_final(all_data, motion, amendment):
"""
HINT: This implementation should be consistent to showInFinalView() in ViewMotionAmendedParagraph.ts
"""
if amendment["state_id"] is None:
return 0
state = get_state(all_data, motion, amendment["state_id"])
if state["merge_amendment_into_final"] == 1:
return 1
return 0
def get_amendments_for_motion(motion, all_data): def get_amendments_for_motion(motion, all_data):
amendment_data = [] amendment_data = []
for amendment_id, amendment in all_data["motions/motion"].items(): for amendment_id, amendment in all_data["motions/motion"].items():
if amendment["parent_id"] == motion["id"]: if amendment["parent_id"] == motion["id"]:
merge_amendment_into_final = get_amendment_merge_into_motion( merge_amendment_into_final = get_amendment_merge_into_motion_final(
all_data, motion, amendment
)
merge_amendment_into_diff = get_amendment_merge_into_motion_diff(
all_data, motion, amendment all_data, motion, amendment
) )
amendment_data.append( amendment_data.append(
@ -68,6 +87,7 @@ def get_amendments_for_motion(motion, all_data):
"identifier": amendment["identifier"], "identifier": amendment["identifier"],
"title": amendment["title"], "title": amendment["title"],
"amendment_paragraphs": amendment["amendment_paragraphs"], "amendment_paragraphs": amendment["amendment_paragraphs"],
"merge_amendment_into_diff": merge_amendment_into_diff,
"merge_amendment_into_final": merge_amendment_into_final, "merge_amendment_into_final": merge_amendment_into_final,
} }
) )

View File

@ -269,6 +269,7 @@ def test_motion_slide(all_data):
"amendment_paragraphs": ["New motion text"], "amendment_paragraphs": ["New motion text"],
"identifier": "Ä1", "identifier": "Ä1",
"merge_amendment_into_final": 0, "merge_amendment_into_final": 0,
"merge_amendment_into_diff": 0,
} }
], ],
"amendment_paragraphs": None, "amendment_paragraphs": None,