OpenSlides/client/src/app/site/motions/services/motion-repository.service.ts

152 lines
5.6 KiB
TypeScript
Raw Normal View History

import { Injectable } from '@angular/core';
import { DataSendService } from '../../../core/services/data-send.service';
import { Motion } from '../../../shared/models/motions/motion';
import { User } from '../../../shared/models/users/user';
import { Category } from '../../../shared/models/motions/category';
import { Workflow } from '../../../shared/models/motions/workflow';
import { WorkflowState } from '../../../shared/models/motions/workflow-state';
import { ViewMotion } from '../models/view-motion';
2018-09-10 15:53:11 +02:00
import { Observable } from 'rxjs';
import { BaseRepository } from '../../base/base-repository';
2018-09-13 14:40:04 +02:00
import { DataStoreService } from '../../../core/services/data-store.service';
2018-09-09 18:52:47 +02:00
import { LinenumberingService } from './linenumbering.service';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
/**
* Repository Services for motions (and potentially categories)
*
* The repository is meant to process domain objects (those found under
* shared/models), so components can display them and interact with them.
*
* Rather than manipulating models directly, the repository is meant to
* inform the {@link DataSendService} about changes which will send
* them to the Server.
*/
@Injectable({
providedIn: 'root'
})
2018-09-10 15:53:11 +02:00
export class MotionRepositoryService extends BaseRepository<ViewMotion, Motion> {
/**
* Creates a MotionRepository
*
* Converts existing and incoming motions to ViewMotions
* Handles CRUD using an observer to the DataStore
2018-09-09 18:52:47 +02:00
* @param DS
* @param dataSend
* @param lineNumbering
*/
2018-09-09 18:52:47 +02:00
public constructor(
DS: DataStoreService,
private dataSend: DataSendService,
private readonly lineNumbering: LinenumberingService,
private readonly sanitizer: DomSanitizer
) {
2018-09-13 14:40:04 +02:00
super(DS, Motion, [Category, User, Workflow]);
}
/**
* Converts a motion to a ViewMotion and adds it to the store.
*
* Foreign references of the motion will be resolved (e.g submitters to users)
* Expandable to all (server side) changes that might occur on the motion object.
*
* @param motion blank motion domain object
*/
2018-09-10 15:53:11 +02:00
protected createViewModel(motion: Motion): ViewMotion {
const category = this.DS.get(Category, motion.category_id);
const submitters = this.DS.getMany(User, motion.submitterIds);
const supporters = this.DS.getMany(User, motion.supporters_id);
const workflow = this.DS.get(Workflow, motion.workflow_id);
let state: WorkflowState = null;
if (workflow) {
state = workflow.getStateById(motion.state_id);
}
2018-09-10 15:53:11 +02:00
return new ViewMotion(motion, category, submitters, supporters, workflow, state);
}
/**
* Creates a motion
* Creates a (real) motion with patched data and delegate it
* to the {@link DataSendService}
*
* @param update the form data containing the update values
* @param viewMotion The View Motion. If not present, a new motion will be created
* TODO: Remove the viewMotion and make it actually distignuishable from save()
*/
public create(motion: Motion): Observable<any> {
2018-09-28 15:10:48 +02:00
if (!motion.supporters_id) {
delete motion.supporters_id;
}
2018-09-18 18:27:14 +02:00
return this.dataSend.createModel(motion);
}
/**
* updates a motion
*
* Creates a (real) motion with patched data and delegate it
* to the {@link DataSendService}
*
* @param update the form data containing the update values
* @param viewMotion The View Motion. If not present, a new motion will be created
*/
public update(update: Partial<Motion>, viewMotion: ViewMotion): Observable<any> {
const motion = viewMotion.motion;
motion.patchValues(update);
2018-09-18 18:27:14 +02:00
return this.dataSend.updateModel(motion, 'patch');
}
/**
* Deleting a motion.
*
* Extract the motion out of the motionView and delegate
* to {@link DataSendService}
* @param viewMotion
*/
public delete(viewMotion: ViewMotion): Observable<any> {
return this.dataSend.delete(viewMotion.motion);
}
2018-09-28 15:10:48 +02:00
/**
* Format the motion text using the line numbering and change
* reco algorithm.
*
2018-09-09 18:52:47 +02:00
* TODO: Call DiffView Service here.
2018-09-28 15:10:48 +02:00
*
* Can be called from detail view and exporter
* @param id Motion ID - will be pulled from the repository
* @param crMode indicator for the change reco mode
2018-09-09 18:52:47 +02:00
* @param lineLength the current line
* @param highlightLine the currently highlighted line (default: none)
2018-09-28 15:10:48 +02:00
*/
2018-09-09 18:52:47 +02:00
public formatMotion(id: number, crMode: number, lineLength: number, highlightLine?: number): SafeHtml {
2018-09-28 15:10:48 +02:00
const targetMotion = this.getViewModel(id);
if (targetMotion && targetMotion.text) {
let motionText = targetMotion.text;
2018-09-09 18:52:47 +02:00
motionText = this.lineNumbering.insertLineNumbers(motionText, lineLength, highlightLine);
2018-09-28 15:10:48 +02:00
// TODO : Use Diff Service here.
// this will(currently) append the previous changes.
// update
switch (crMode) {
case 0: // Original
break;
case 1: // Changed Version
motionText += ' and get changed version';
break;
case 2: // Diff Version
motionText += ' and get diff version';
break;
case 3: // Final Version
motionText += ' and final version';
break;
}
2018-09-09 18:52:47 +02:00
return this.sanitizer.bypassSecurityTrustHtml(motionText);
2018-09-28 15:10:48 +02:00
} else {
return null;
}
}
}