Merge pull request #4052 from tsiegleauq/motion-attachments
Motion Attachments + Restructure
This commit is contained in:
commit
659f9f116a
@ -24,6 +24,15 @@ export class Mediafile extends ProjectableBaseModel {
|
||||
this.mediafile = new File(input.mediafile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the downloadURL
|
||||
*
|
||||
* @returns the download URL for the specific file as string
|
||||
*/
|
||||
public getDownloadUrl(): string {
|
||||
return `${this.media_url_prefix}${this.mediafile.name}`;
|
||||
}
|
||||
|
||||
public getTitle(): string {
|
||||
return this.title;
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { BaseRepository } from '../../base/base-repository';
|
||||
import { DataStoreService } from '../../../core/services/data-store.service';
|
||||
@ -12,6 +14,7 @@ import { ViewSpeaker } from '../models/view-speaker';
|
||||
import { Speaker } from 'app/shared/models/agenda/speaker';
|
||||
import { User } from 'app/shared/models/users/user';
|
||||
import { HttpService } from 'app/core/services/http.service';
|
||||
import { ConfigService } from 'app/core/services/config.service';
|
||||
|
||||
/**
|
||||
* Repository service for users
|
||||
@ -27,11 +30,13 @@ export class AgendaRepositoryService extends BaseRepository<ViewItem, Item> {
|
||||
* @param DS The DataStore
|
||||
* @param httpService OpenSlides own HttpService
|
||||
* @param mapperService OpenSlides mapping service for collection strings
|
||||
* @param config Read config variables
|
||||
*/
|
||||
public constructor(
|
||||
protected DS: DataStoreService,
|
||||
private httpService: HttpService,
|
||||
mapperService: CollectionStringModelMapperService
|
||||
mapperService: CollectionStringModelMapperService,
|
||||
private config: ConfigService
|
||||
) {
|
||||
super(DS, mapperService, Item);
|
||||
}
|
||||
@ -179,4 +184,13 @@ export class AgendaRepositoryService extends BaseRepository<ViewItem, Item> {
|
||||
const contentObject = this.getContentObject(item);
|
||||
return new ViewItem(item, contentObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get agenda visibility from the config
|
||||
*
|
||||
* @return An observable to the default agenda visibility
|
||||
*/
|
||||
public getDefaultAgendaVisibility(): Observable<number> {
|
||||
return this.config.get('agenda_new_items_default_visibility').pipe(map(key => +key));
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ export abstract class ListViewBaseComponent<V extends BaseViewModel> extends Bas
|
||||
this.singleSelectAction(row);
|
||||
} else {
|
||||
const idx = this.selectedRows.indexOf(row);
|
||||
if ( idx < 0){
|
||||
if (idx < 0) {
|
||||
this.selectedRows.push(row);
|
||||
} else {
|
||||
this.selectedRows.splice(idx, 1);
|
||||
@ -92,13 +92,12 @@ export abstract class ListViewBaseComponent<V extends BaseViewModel> extends Bas
|
||||
* Should be overridden by implementations. Currently there is no default action.
|
||||
* @param row a ViewModel
|
||||
*/
|
||||
public singleSelectAction(row: V) : void {
|
||||
}
|
||||
public singleSelectAction(row: V): void {}
|
||||
|
||||
/**
|
||||
* enables/disables the multiSelect Mode
|
||||
*/
|
||||
public toggleMultiSelect() : void {
|
||||
public toggleMultiSelect(): void {
|
||||
if (!this.canMultiSelect || this.isMultiSelect) {
|
||||
this._multiSelectModus = false;
|
||||
this.clearSelection();
|
||||
@ -107,6 +106,13 @@ export abstract class ListViewBaseComponent<V extends BaseViewModel> extends Bas
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select all files in the current data source
|
||||
*/
|
||||
public selectAll(): void {
|
||||
this.selectedRows = this.dataSource.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current state of the multiSelect modus
|
||||
*/
|
||||
|
@ -168,6 +168,10 @@
|
||||
<mat-icon>library_add</mat-icon>
|
||||
<span translate>Exit multiselect</span>
|
||||
</button>
|
||||
<button mat-menu-item (click)="selectAll()">
|
||||
<mat-icon>done_all</mat-icon>
|
||||
<span translate>Select all</span>
|
||||
</button>
|
||||
<mat-divider></mat-divider>
|
||||
<button mat-menu-item *osPerms="'mediafiles.can_manage'" (click)="deleteSelected()">
|
||||
<mat-icon>delete</mat-icon>
|
||||
|
@ -43,7 +43,7 @@ export class ViewMediafile extends BaseViewModel {
|
||||
}
|
||||
|
||||
public get downloadUrl(): string {
|
||||
return this.mediafile && this.mediafile.mediafile ? `${this.prefix}${this.fileName}` : null;
|
||||
return this.mediafile ? this.mediafile.getDownloadUrl() : null;
|
||||
}
|
||||
|
||||
public constructor(mediafile?: Mediafile, uploader?: User) {
|
||||
@ -100,7 +100,7 @@ export class ViewMediafile extends BaseViewModel {
|
||||
'video/3gpp',
|
||||
'video/x-msvideo',
|
||||
'video/x-ms-wmv',
|
||||
'video/x-matroska',
|
||||
'video/x-matroska'
|
||||
].includes(this.type);
|
||||
}
|
||||
|
||||
|
@ -3,14 +3,6 @@
|
||||
<button class="small-button" type="button" mat-icon-button disableRipple *ngIf="!isEditMode" (click)="onEdit()">
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button>
|
||||
<span *ngIf="isEditMode">
|
||||
<button class="small-button" type="button" mat-icon-button disableRipple (click)="onSave()">
|
||||
<mat-icon>save</mat-icon>
|
||||
</button>
|
||||
<button class="small-button" type="button" mat-icon-button disableRipple (click)="onCancel()">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
</span>
|
||||
</h4>
|
||||
|
||||
<div *ngIf="!isEditMode">
|
||||
@ -32,7 +24,13 @@
|
||||
></os-search-value-selector>
|
||||
</form>
|
||||
|
||||
<os-sorting-list class="testclass" [input]="editSubmitterObservable" [live]="true" [count]="true" (sortEvent)="onSortingChange($event)">
|
||||
<os-sorting-list
|
||||
class="testclass"
|
||||
[input]="editSubmitterObservable"
|
||||
[live]="true"
|
||||
[count]="true"
|
||||
(sortEvent)="onSortingChange($event)"
|
||||
>
|
||||
<!-- implicit user references into the component using ng-template slot -->
|
||||
<ng-template let-user>
|
||||
<button type="button" mat-icon-button matTooltip="{{ 'Remove' | translate }}" (click)="onRemove(user)">
|
||||
@ -40,6 +38,9 @@
|
||||
</button>
|
||||
</ng-template>
|
||||
</os-sorting-list>
|
||||
<mat-card-actions>
|
||||
<button type="button" mat-button (click)="onSave()"><span translate>Save</span></button>
|
||||
<button type="button" mat-button (click)="onCancel()"><span translate>Cancel</span></button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
</div>
|
||||
|
||||
|
@ -13,6 +13,7 @@ import { Item, itemVisibilityChoices } from 'app/shared/models/agenda/item';
|
||||
import { DataStoreService } from 'app/core/services/data-store.service';
|
||||
import { MotionBlockRepositoryService } from '../../services/motion-block-repository.service';
|
||||
import { ViewMotionBlock } from '../../models/view-motion-block';
|
||||
import { AgendaRepositoryService } from 'app/site/agenda/services/agenda-repository.service';
|
||||
|
||||
/**
|
||||
* Table for the motion blocks
|
||||
@ -57,6 +58,7 @@ export class MotionBlockListComponent extends ListViewBaseComponent<ViewMotionBl
|
||||
* @param router routing to children
|
||||
* @param route determine the local route
|
||||
* @param repo the motion block repository
|
||||
* @param agendaRepo the agenda repository service
|
||||
* @param DS the dataStore
|
||||
* @param formBuilder creates forms
|
||||
*/
|
||||
@ -67,6 +69,7 @@ export class MotionBlockListComponent extends ListViewBaseComponent<ViewMotionBl
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private repo: MotionBlockRepositoryService,
|
||||
private agendaRepo: AgendaRepositoryService,
|
||||
private DS: DataStoreService,
|
||||
private formBuilder: FormBuilder
|
||||
) {
|
||||
@ -98,7 +101,7 @@ export class MotionBlockListComponent extends ListViewBaseComponent<ViewMotionBl
|
||||
this.dataSource.data = newMotionblocks;
|
||||
});
|
||||
|
||||
this.repo.getDefaultAgendaVisibility().subscribe(visibility => (this.defaultVisibility = visibility));
|
||||
this.agendaRepo.getDefaultAgendaVisibility().subscribe(visibility => (this.defaultVisibility = visibility));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,7 +12,7 @@
|
||||
<span translate>Motion</span>
|
||||
<!-- Whitespace between "Motion" and identifier -->
|
||||
<span> </span> <span *ngIf="!editMotion">{{ motion.identifier }}</span>
|
||||
<span *ngIf="editMotion">{{ metaInfoForm.get('identifier').value }}</span>
|
||||
<span *ngIf="editMotion">{{ contentForm.get('identifier').value }}</span>
|
||||
</h2>
|
||||
<h2 *ngIf="newMotion" translate>New motion</h2>
|
||||
</div>
|
||||
@ -21,14 +21,32 @@
|
||||
<div *ngIf="!editMotion" class="extra-controls-slot on-transition-fade">
|
||||
<div *ngIf="previousMotion">
|
||||
<button mat-button (click)="navigateToMotion(previousMotion)">
|
||||
<mat-icon>navigate_before</mat-icon>
|
||||
<!-- possible icons:
|
||||
arrow_left
|
||||
chevron_left
|
||||
first_page
|
||||
arrow_back
|
||||
arrow_back_ios
|
||||
navigate_before
|
||||
fast_rewind
|
||||
-->
|
||||
<mat-icon>chevron_left</mat-icon>
|
||||
<span>{{ previousMotion.identifier }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="nextMotion">
|
||||
<button mat-button (click)="navigateToMotion(nextMotion)">
|
||||
<span>{{ nextMotion.identifier }}</span>
|
||||
<mat-icon>navigate_next</mat-icon>
|
||||
<!-- possible icons:
|
||||
arrow_right
|
||||
chevron_right
|
||||
last_page
|
||||
arrow_forward
|
||||
arrow_forward_ios
|
||||
navigate_next
|
||||
fast_forward
|
||||
-->
|
||||
<mat-icon>chevron_right</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -87,18 +105,16 @@
|
||||
</os-head-bar>
|
||||
|
||||
<!-- Title -->
|
||||
<div *ngIf="motion" class="motion-title on-transition-fade">
|
||||
<h2 *ngIf="!editMotion">{{ motion.title }}</h2>
|
||||
<h2 *ngIf="editMotion">{{ contentForm.get('title').value }}</h2>
|
||||
<div class="motion-title on-transition-fade" *ngIf="motion && !editMotion">
|
||||
<h2>{{ motion.title }}</h2>
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="vp.isMobile; then: mobileView; else: desktopView"></ng-container>
|
||||
<ng-container *ngIf="vp.isMobile; then mobileView; else desktopView"></ng-container>
|
||||
|
||||
<ng-template #mobileView>
|
||||
<mat-accordion multi='true' class='on-transition-fade'>
|
||||
|
||||
<mat-accordion multi="true" class="on-transition-fade">
|
||||
<!-- MetaInfo Panel-->
|
||||
<mat-expansion-panel #metaInfoPanel [expanded]="true" class='meta-info-block meta-info-panel'>
|
||||
<mat-expansion-panel #metaInfoPanel [expanded]="true" class="meta-info-block meta-info-panel">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
<mat-icon>info</mat-icon>
|
||||
@ -126,8 +142,8 @@
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<os-motion-comments *ngIf="!newMotion" [motion]="motion"></os-motion-comments>
|
||||
<os-personal-note *ngIf="!newMotion" [motion]="motion"></os-personal-note>
|
||||
<os-motion-comments *ngIf="!editMotion" [motion]="motion"></os-motion-comments>
|
||||
<os-personal-note *ngIf="!editMotion" [motion]="motion"></os-personal-note>
|
||||
</mat-accordion>
|
||||
</ng-template>
|
||||
|
||||
@ -139,8 +155,8 @@
|
||||
<ng-container *ngTemplateOutlet="metaInfoTemplate"></ng-container>
|
||||
</div>
|
||||
|
||||
<os-motion-comments *ngIf="!newMotion" [motion]="motion"></os-motion-comments>
|
||||
<os-personal-note *ngIf="!newMotion" [motion]="motion"></os-personal-note>
|
||||
<os-motion-comments *ngIf="!editMotion" [motion]="motion"></os-motion-comments>
|
||||
<os-personal-note *ngIf="!editMotion" [motion]="motion"></os-personal-note>
|
||||
</div>
|
||||
<div class="desktop-right ">
|
||||
<!-- Content -->
|
||||
@ -150,99 +166,72 @@
|
||||
</ng-template>
|
||||
|
||||
<ng-template #metaInfoTemplate>
|
||||
<form [formGroup]="metaInfoForm" (keydown)="onKeyDown($event)" (ngSubmit)="saveMotion()">
|
||||
<!-- Identifier -->
|
||||
<div *ngIf="editMotion && !newMotion">
|
||||
<!-- <div *ngIf="editMotion"> -->
|
||||
<div *ngIf="!editMotion">
|
||||
<h4 translate>Identifier</h4>
|
||||
{{ motion.identifier }}
|
||||
</div>
|
||||
<mat-form-field *ngIf="editMotion">
|
||||
<input
|
||||
matInput
|
||||
placeholder="{{ "Identifier" | translate }}"
|
||||
formControlName="identifier"
|
||||
[value]="motionCopy.identifier"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div *ngIf="motion">
|
||||
<!-- Submitters -->
|
||||
<div *ngIf="motion && motion.submitters || newMotion">
|
||||
<div *ngIf="newMotion">
|
||||
<div *osPerms="['motions.can_manage', 'motions.can_manage_metadata']">
|
||||
<os-search-value-selector
|
||||
ngDefaultControl
|
||||
[form]="metaInfoForm"
|
||||
[formControl]="metaInfoForm.get('submitters_id')"
|
||||
[multiple]="true"
|
||||
listname="{{ 'Submitters' | translate }}"
|
||||
[InputListValues]="submitterObserver"
|
||||
></os-search-value-selector>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="!editMotion && !newMotion">
|
||||
<os-manage-submitters [motion]="motion"></os-manage-submitters>
|
||||
</div>
|
||||
<div *ngIf="motion.submitters || newMotion">
|
||||
<div *ngIf="!editMotion"><os-manage-submitters [motion]="motion"></os-manage-submitters></div>
|
||||
</div>
|
||||
|
||||
<!-- Supporters -->
|
||||
<div *ngIf='motion && minSupporters'>
|
||||
<div *ngIf="editMotion">
|
||||
<div *osPerms="['motions.can_manage', 'motions.can_manage_metadata']">
|
||||
<os-search-value-selector
|
||||
ngDefaultControl
|
||||
[form]="metaInfoForm"
|
||||
[formControl]="metaInfoForm.get('supporters_id')"
|
||||
[multiple]="true"
|
||||
listname="{{ 'Supporters' | translate }}"
|
||||
[InputListValues]="supporterObserver"
|
||||
></os-search-value-selector>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="!editMotion">
|
||||
<h4 *ngIf="perms.isAllowed('support', motion) || motion.hasSupporters()" translate>Supporters</h4>
|
||||
<!-- support button -->
|
||||
<button type="button" *ngIf="perms.isAllowed('support', motion)" (click)=support() mat-raised-button color="primary">
|
||||
<mat-icon>thumb_up</mat-icon>
|
||||
{{ 'Support' | translate }}
|
||||
</button>
|
||||
<!-- unsupport button -->
|
||||
<button type="button" *ngIf="perms.isAllowed('unsupport', motion)" (click)=unsupport() mat-raised-button color="primary">
|
||||
<mat-icon>thumb_down</mat-icon>
|
||||
{{ 'Unsupport' | translate }}
|
||||
</button>
|
||||
<!-- show supporters (TODO: open in dialog) -->
|
||||
<button type="button" *ngIf="motion.hasSupporters()" (click)=openSupportersDialog() mat-button>
|
||||
{{ motion.supporters.length }} {{ 'supporters' | translate }}
|
||||
</button>
|
||||
<p *ngIf="showSupporters">
|
||||
<mat-chip-list *ngFor="let supporter of motion.supporters">
|
||||
<mat-chip>{{ supporter.full_name }}</mat-chip>
|
||||
</mat-chip-list>
|
||||
</p>
|
||||
</div>
|
||||
<!-- do Support -->
|
||||
<div *ngIf="minSupporters && !editMotion">
|
||||
<h4 *ngIf="perms.isAllowed('support', motion) || motion.hasSupporters()" translate>Supporters</h4>
|
||||
|
||||
<!-- support button -->
|
||||
<button
|
||||
type="button"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
(click)="support()"
|
||||
*ngIf="perms.isAllowed('support', motion)"
|
||||
>
|
||||
<mat-icon>thumb_up</mat-icon>
|
||||
{{ 'Support' | translate }}
|
||||
</button>
|
||||
|
||||
<!-- unsupport button -->
|
||||
<button
|
||||
type="button"
|
||||
*ngIf="perms.isAllowed('unsupport', motion)"
|
||||
(click)="unsupport()"
|
||||
mat-raised-button
|
||||
color="primary"
|
||||
>
|
||||
<mat-icon>thumb_down</mat-icon>
|
||||
{{ 'Unsupport' | translate }}
|
||||
</button>
|
||||
<!-- show supporters (TODO: open in dialog) -->
|
||||
<button type="button" *ngIf="motion.hasSupporters()" (click)="openSupportersDialog()" mat-button>
|
||||
{{ motion.supporters.length }} {{ 'supporters' | translate }}
|
||||
</button>
|
||||
<p *ngIf="showSupporters">
|
||||
<mat-chip-list *ngFor="let supporter of motion.supporters">
|
||||
<mat-chip>{{ supporter.full_name }}</mat-chip>
|
||||
</mat-chip-list>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- State -->
|
||||
<div *ngIf='motion && !editMotion'>
|
||||
<!-- Set State -->
|
||||
<div *ngIf="!editMotion">
|
||||
<h4 translate>State</h4>
|
||||
<mat-menu #stateMenu='matMenu'>
|
||||
<button *ngFor='let state of motion.nextStates' mat-menu-item
|
||||
(click)=setState(state.id)>{{ state.name | translate }}
|
||||
<mat-menu #stateMenu="matMenu">
|
||||
<button *ngFor="let state of motion.nextStates" mat-menu-item (click)="setState(state.id)">
|
||||
{{ state.name | translate }}
|
||||
</button>
|
||||
<mat-divider></mat-divider>
|
||||
<button mat-menu-item (click)=setState(null)>
|
||||
<button mat-menu-item (click)="setState(null)">
|
||||
<mat-icon>replay</mat-icon> {{ 'Reset state' | translate }}
|
||||
</button>
|
||||
</mat-menu>
|
||||
<mat-basic-chip [matMenuTriggerFor]='stateMenu' [ngClass]="{
|
||||
'green': motion.state.css_class === 'success',
|
||||
'red': motion.state.css_class === 'danger',
|
||||
'grey': motion.state.css_class === 'default',
|
||||
'lightblue': motion.state.css_class === 'primary' }">
|
||||
<mat-basic-chip
|
||||
*ngIf="motion.state"
|
||||
[matMenuTriggerFor]="stateMenu"
|
||||
[ngClass]="{
|
||||
green: motion.state.css_class === 'success',
|
||||
red: motion.state.css_class === 'danger',
|
||||
grey: motion.state.css_class === 'default',
|
||||
lightblue: motion.state.css_class === 'primary'
|
||||
}"
|
||||
>
|
||||
{{ motion.state.name | translate }}
|
||||
</mat-basic-chip>
|
||||
|
||||
@ -250,27 +239,35 @@
|
||||
</div>
|
||||
|
||||
<!-- Recommendation -->
|
||||
<div *ngIf='motion && recommender && !editMotion'>
|
||||
<div *ngIf="recommender && !editMotion">
|
||||
<h4>{{ recommender }}</h4>
|
||||
<mat-menu #recommendationMenu='matMenu'>
|
||||
<button *ngFor='let recommendation of motion.possibleRecommendations' mat-menu-item
|
||||
(click)=setRecommendation(recommendation.id)>{{ recommendation.recommendation_label | translate }}
|
||||
<mat-menu #recommendationMenu="matMenu">
|
||||
<button
|
||||
*ngFor="let recommendation of motion.possibleRecommendations"
|
||||
mat-menu-item
|
||||
(click)="setRecommendation(recommendation.id)"
|
||||
>
|
||||
{{ recommendation.recommendation_label | translate }}
|
||||
</button>
|
||||
<mat-divider></mat-divider>
|
||||
<button mat-menu-item (click)=setRecommendation(null)>
|
||||
<button mat-menu-item (click)="setRecommendation(null)">
|
||||
<mat-icon>replay</mat-icon> {{ 'Reset recommendation' | translate }}
|
||||
</button>
|
||||
</mat-menu>
|
||||
<mat-basic-chip [matMenuTriggerFor]='recommendationMenu' class="bluegrey">
|
||||
{{ motion.recommendation ? (motion.recommendation.recommendation_label | translate) : ('not set' | translate) }}
|
||||
<mat-basic-chip [matMenuTriggerFor]="recommendationMenu" class="bluegrey">
|
||||
{{
|
||||
motion.recommendation
|
||||
? (motion.recommendation.recommendation_label | translate)
|
||||
: ('not set' | translate)
|
||||
}}
|
||||
</mat-basic-chip>
|
||||
</div>
|
||||
|
||||
<!-- Category -->
|
||||
<!-- Disabled during "new motion" since changing has no effect -->
|
||||
<div *ngIf="motion && !editMotion">
|
||||
<div *ngIf="!editMotion">
|
||||
<h4 translate>Category</h4>
|
||||
<mat-menu #categoryMenu='matMenu'>
|
||||
<mat-menu #categoryMenu="matMenu">
|
||||
<button
|
||||
mat-menu-item
|
||||
*ngFor="let category of categoryObserver.value"
|
||||
@ -278,75 +275,34 @@
|
||||
>
|
||||
{{ category }}
|
||||
</button>
|
||||
<button mat-menu-item (click)=setCategory(null)>
|
||||
---
|
||||
</button>
|
||||
<button mat-menu-item (click)="setCategory(null)">---</button>
|
||||
</mat-menu>
|
||||
<mat-basic-chip [matMenuTriggerFor]='categoryMenu' class="grey">
|
||||
<mat-basic-chip [matMenuTriggerFor]="categoryMenu" class="grey">
|
||||
{{ motion.category ? motion.category : ('not set' | translate) }}
|
||||
</mat-basic-chip>
|
||||
</div>
|
||||
|
||||
<!-- Block -->
|
||||
<div *ngIf="motion && !editMotion">
|
||||
<div *ngIf="!editMotion">
|
||||
<h4 translate>Motion block</h4>
|
||||
|
||||
<mat-menu #blockMenu='matMenu'>
|
||||
<button
|
||||
mat-menu-item
|
||||
*ngFor="let block of blockObserver.value"
|
||||
(click)="setBlock(block.id)"
|
||||
>
|
||||
<mat-menu #blockMenu="matMenu">
|
||||
<button mat-menu-item *ngFor="let block of blockObserver.value" (click)="setBlock(block.id)">
|
||||
{{ block }}
|
||||
</button>
|
||||
<button mat-menu-item (click)="setBlock(null)">
|
||||
---
|
||||
</button>
|
||||
<button mat-menu-item (click)="setBlock(null)">---</button>
|
||||
</mat-menu>
|
||||
<mat-basic-chip [matMenuTriggerFor]='blockMenu' class="grey">
|
||||
{{ motion.motion_block ? motion.motion_block : ('not set' | translate) }}
|
||||
<mat-basic-chip [matMenuTriggerFor]="blockMenu" class="grey">
|
||||
{{ motion.motion_block ? motion.motion_block : ('not set' | translate) }}
|
||||
</mat-basic-chip>
|
||||
</div>
|
||||
|
||||
<!-- Workflow -->
|
||||
<div *ngIf="editMotion">
|
||||
<div *osPerms="['motions.can_manage', 'motions.can_manage_metadata']">
|
||||
<os-search-value-selector
|
||||
ngDefaultControl
|
||||
[form]="metaInfoForm"
|
||||
[formControl]="metaInfoForm.get('workflow_id')"
|
||||
[multiple]="false"
|
||||
listname="{{ 'Workflow' | translate }}"
|
||||
[InputListValues]="workflowObserver"
|
||||
></os-search-value-selector>
|
||||
</div>
|
||||
<!-- Origin - display only -->
|
||||
<div *ngIf="!editMotion && motion.origin">
|
||||
<h4 translate>Origin</h4>
|
||||
{{ motion.origin }}
|
||||
</div>
|
||||
|
||||
<!-- Origin -->
|
||||
<div *ngIf="(motion && motion.origin) || editMotion">
|
||||
<div *ngIf="!editMotion">
|
||||
<h4 translate>Origin</h4>
|
||||
{{ motion.origin }}
|
||||
</div>
|
||||
<div *osPerms="['motions.can_manage', 'motions.can_manage_metadata']">
|
||||
<mat-form-field *ngIf="editMotion">
|
||||
<input
|
||||
matInput
|
||||
placeholder="{{ 'Origin' | translate}}"
|
||||
formControlName="origin"
|
||||
[value]="motionCopy.origin"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Voting -->
|
||||
<!--
|
||||
<div *ngIf='motion.polls && motion.polls.length > 0 || editMotion'>
|
||||
<h4 translate>Voting</h4>
|
||||
</div>
|
||||
-->
|
||||
</form>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #contentTemplate>
|
||||
@ -356,9 +312,10 @@
|
||||
(clickdown)="onKeyDown($event)"
|
||||
(keydown)="onKeyDown($event)"
|
||||
(ngSubmit)="saveMotion()"
|
||||
*ngIf="motion"
|
||||
>
|
||||
<!-- Line Number and Diff buttons -->
|
||||
<div *ngIf="motion && !editMotion && !motion.isStatuteAmendment()" class="motion-text-controls">
|
||||
<div *ngIf="!editMotion && !motion.isStatuteAmendment()" class="motion-text-controls">
|
||||
<button
|
||||
type="button"
|
||||
mat-icon-button
|
||||
@ -397,31 +354,53 @@
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<!-- Title -->
|
||||
<div *ngIf="(motion && motion.title) || editMotion">
|
||||
<div *ngIf="!editMotion">
|
||||
<h4>{{ motion.title }}</h4>
|
||||
<!-- Submitter -->
|
||||
<div *ngIf="newMotion" class="content-field form100">
|
||||
<div *osPerms="['motions.can_manage', 'motions.can_manage_metadata']">
|
||||
<os-search-value-selector
|
||||
ngDefaultControl
|
||||
[form]="contentForm"
|
||||
[formControl]="contentForm.get('submitters_id')"
|
||||
[multiple]="true"
|
||||
listname="{{ 'Submitters' | translate }}"
|
||||
[InputListValues]="submitterObserver"
|
||||
></os-search-value-selector>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-id-title">
|
||||
<!-- Identifier -->
|
||||
<div *ngIf="editMotion && !newMotion" class="content-field form-identifier">
|
||||
<mat-form-field *ngIf="editMotion">
|
||||
<input
|
||||
matInput
|
||||
placeholder="{{ 'Identifier' | translate }}"
|
||||
formControlName="identifier"
|
||||
[value]="motionCopy.identifier"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<mat-form-field *ngIf="editMotion" class="wide-form">
|
||||
<input
|
||||
matInput
|
||||
osAutofocus
|
||||
placeholder="{{ 'Title' | translate }}"
|
||||
formControlName="title"
|
||||
[value]="motionCopy.title"
|
||||
required
|
||||
/>
|
||||
</mat-form-field>
|
||||
<!-- Title -->
|
||||
<div *ngIf="editMotion" class="content-field form-title">
|
||||
<mat-form-field *ngIf="editMotion">
|
||||
<input
|
||||
matInput
|
||||
osAutofocus
|
||||
placeholder="{{ 'Title' | translate }}"
|
||||
formControlName="title"
|
||||
[value]="motionCopy.title"
|
||||
required
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Text -->
|
||||
<span class="text-prefix-label">{{ preamble | translate }}</span>
|
||||
|
||||
<!-- Regular motions or traditional amendments -->
|
||||
<ng-container
|
||||
*ngIf="motion && !editMotion && !motion.isStatuteAmendment() && !motion.isParagraphBasedAmendment()"
|
||||
>
|
||||
<ng-container *ngIf="!editMotion && !motion.isStatuteAmendment() && !motion.isParagraphBasedAmendment()">
|
||||
<div
|
||||
*ngIf="!isRecoModeDiff()"
|
||||
class="motion-text"
|
||||
@ -451,7 +430,7 @@
|
||||
</ng-container>
|
||||
<div
|
||||
class="motion-text line-numbers-none"
|
||||
*ngIf="motion && !editMotion && motion.isStatuteAmendment()"
|
||||
*ngIf="!editMotion && motion.isStatuteAmendment()"
|
||||
[innerHTML]="getFormattedStatuteAmendment()"
|
||||
></div>
|
||||
|
||||
@ -459,21 +438,120 @@
|
||||
<editor formControlName="text" [init]="tinyMceSettings" *ngIf="motion && editMotion"></editor>
|
||||
|
||||
<!-- Paragraph-based amendments -->
|
||||
<ng-container *ngIf="motion && !editMotion && motion.isParagraphBasedAmendment()">
|
||||
<ng-container *ngIf="!editMotion && motion.isParagraphBasedAmendment()">
|
||||
<ng-container *ngTemplateOutlet="paragraphBasedAmendment"></ng-container>
|
||||
</ng-container>
|
||||
|
||||
<!-- Reason -->
|
||||
<div *ngIf="motion || editMotion">
|
||||
<h5 *ngIf="motion.reason || editMotion" translate>Reason</h5>
|
||||
<div *ngIf="motion.reason || editMotion">
|
||||
<h3 translate>Reason</h3>
|
||||
<div class="motion-text" *ngIf="!editMotion"><div [innerHtml]="motion.reason"></div></div>
|
||||
|
||||
<!-- The HTML Editor -->
|
||||
<editor
|
||||
formControlName='reason'
|
||||
[init]="tinyMceSettings"
|
||||
*ngIf="editMotion"
|
||||
></editor>
|
||||
<editor formControlName="reason" [init]="tinyMceSettings" *ngIf="editMotion"></editor>
|
||||
</div>
|
||||
|
||||
<div class="extra-data">
|
||||
<!-- Attachments -->
|
||||
<div *ngIf="motion.hasAttachments() || editMotion" class="content-field form100">
|
||||
<div *ngIf="!editMotion">
|
||||
<h4 translate>Attachments</h4>
|
||||
<mat-list dense>
|
||||
<mat-list-item *ngFor="let file of motion.attachments">
|
||||
<a [routerLink]="" (click)="onClickAttacment(file)">{{ file.title }}</a>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
</div>
|
||||
<div *ngIf="editMotion">
|
||||
<os-search-value-selector
|
||||
ngDefaultControl
|
||||
[form]="contentForm"
|
||||
[formControl]="contentForm.get('attachments_id')"
|
||||
[multiple]="true"
|
||||
listname="{{ 'Attachments' | translate }}"
|
||||
[InputListValues]="mediafilesObserver"
|
||||
></os-search-value-selector>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Category form -->
|
||||
<div class="content-field form100" *ngIf="newMotion && categoryObserver.value.length > 0">
|
||||
<os-search-value-selector
|
||||
ngDefaultControl
|
||||
[form]="contentForm"
|
||||
[formControl]="contentForm.get('category_id')"
|
||||
[multiple]="false"
|
||||
[includeNone]="true"
|
||||
listname="{{ 'Category' | translate }}"
|
||||
[InputListValues]="categoryObserver"
|
||||
></os-search-value-selector>
|
||||
</div>
|
||||
|
||||
<!-- Parent item -->
|
||||
<div class="content-field form100" *ngIf="newMotion && agendaItemObserver.value.length > 0">
|
||||
<os-search-value-selector
|
||||
ngDefaultControl
|
||||
[form]="contentForm"
|
||||
[formControl]="contentForm.get('parent_id')"
|
||||
[multiple]="false"
|
||||
[includeNone]="true"
|
||||
listname="{{ 'Parent Item' | translate }}"
|
||||
[InputListValues]="agendaItemObserver"
|
||||
></os-search-value-selector>
|
||||
</div>
|
||||
|
||||
<!-- Visibility -->
|
||||
<div class="content-field form100" *ngIf="newMotion">
|
||||
<mat-form-field>
|
||||
<mat-select formControlName="agenda_type" placeholder="{{ 'Agenda visibility' | translate }}">
|
||||
<mat-option *ngFor="let type of itemVisibility" [value]="type.key">
|
||||
<span>{{ type.name | translate }}</span>
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<!-- Supporter form -->
|
||||
<div class="content-field form100" *ngIf="editMotion && minSupporters">
|
||||
<div *osPerms="['motions.can_manage', 'motions.can_manage_metadata']">
|
||||
<os-search-value-selector
|
||||
ngDefaultControl
|
||||
[form]="contentForm"
|
||||
[formControl]="contentForm.get('supporters_id')"
|
||||
[multiple]="true"
|
||||
listname="{{ 'Supporters' | translate }}"
|
||||
[InputListValues]="supporterObserver"
|
||||
></os-search-value-selector>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Workflow -->
|
||||
<div class="content-field form100" *ngIf="editMotion && workflowObserver.value.length > 1">
|
||||
<div *osPerms="['motions.can_manage', 'motions.can_manage_metadata']">
|
||||
<os-search-value-selector
|
||||
ngDefaultControl
|
||||
[form]="contentForm"
|
||||
[formControl]="contentForm.get('workflow_id')"
|
||||
[multiple]="false"
|
||||
listname="{{ 'Workflow' | translate }}"
|
||||
[InputListValues]="workflowObserver"
|
||||
></os-search-value-selector>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Origin form -->
|
||||
<div class="content-field form100" *ngIf="editMotion">
|
||||
<div *osPerms="['motions.can_manage', 'motions.can_manage_metadata']">
|
||||
<mat-form-field>
|
||||
<input
|
||||
matInput
|
||||
placeholder="{{ 'Origin' | translate }}"
|
||||
formControlName="origin"
|
||||
[value]="motionCopy.origin"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</ng-template>
|
||||
@ -522,9 +600,15 @@
|
||||
<!-- Line number Menu -->
|
||||
<mat-menu #lineNumberingMenu="matMenu">
|
||||
<div *ngIf="motion">
|
||||
<button mat-menu-item translate (click)=setLineNumberingMode(0) [ngClass]="{ 'selected': motion.lnMode === 0 }">none</button>
|
||||
<button mat-menu-item translate (click)=setLineNumberingMode(1) [ngClass]="{ 'selected': motion.lnMode === 1 }">inline</button>
|
||||
<button mat-menu-item translate (click)=setLineNumberingMode(2) [ngClass]="{ 'selected': motion.lnMode === 2 }">outside</button>
|
||||
<button mat-menu-item translate (click)="setLineNumberingMode(0)" [ngClass]="{ selected: motion.lnMode === 0 }">
|
||||
none
|
||||
</button>
|
||||
<button mat-menu-item translate (click)="setLineNumberingMode(1)" [ngClass]="{ selected: motion.lnMode === 1 }">
|
||||
inline
|
||||
</button>
|
||||
<button mat-menu-item translate (click)="setLineNumberingMode(2)" [ngClass]="{ selected: motion.lnMode === 2 }">
|
||||
outside
|
||||
</button>
|
||||
</div>
|
||||
</mat-menu>
|
||||
|
||||
|
@ -23,7 +23,6 @@ span {
|
||||
line-height: 180%;
|
||||
font-size: 120%;
|
||||
color: #317796; // TODO: put in theme as $primary
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
@ -41,58 +40,6 @@ span {
|
||||
}
|
||||
}
|
||||
|
||||
.motion-submitter {
|
||||
display: inline;
|
||||
font-weight: bold;
|
||||
font-size: 70%;
|
||||
}
|
||||
|
||||
.meta-info-block {
|
||||
form {
|
||||
div + div {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
display: block;
|
||||
// padding-top: 0;
|
||||
margin-top: 0px; //distance between heading and text
|
||||
margin-bottom: 3px; //distance between heading and text
|
||||
font-size: 80%;
|
||||
color: gray;
|
||||
|
||||
mat-icon {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-form-field-label {
|
||||
font-size: 12pt;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.mat-form-field-label-wrapper {
|
||||
mat-icon {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wide-form {
|
||||
textarea {
|
||||
height: 25vh;
|
||||
}
|
||||
|
||||
::ng-deep {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.meta-info-panel {
|
||||
padding-top: 25px;
|
||||
|
||||
@ -143,6 +90,45 @@ span {
|
||||
display: block;
|
||||
margin: 0 10px 7px 0px;
|
||||
}
|
||||
|
||||
.extra-data {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.content-field {
|
||||
display: inline-block;
|
||||
::ng-deep {
|
||||
.mat-form-field {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form100 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form70 {
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.form30 {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.form-id-title {
|
||||
display: flex;
|
||||
|
||||
.form-identifier {
|
||||
flex: 0 0 95px;
|
||||
max-width: 95px;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.form-title {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.desktop-view {
|
||||
|
@ -1,7 +1,9 @@
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { MatDialog, MatExpansionPanel, MatSnackBar, MatCheckboxChange } from '@angular/material';
|
||||
import { take, takeWhile, multicast, skipWhile } from 'rxjs/operators';
|
||||
|
||||
import { Category } from '../../../../shared/models/motions/category';
|
||||
import { ViewportService } from '../../../../core/services/viewport.service';
|
||||
@ -19,7 +21,7 @@ import {
|
||||
} from '../motion-change-recommendation/motion-change-recommendation.component';
|
||||
import { ChangeRecommendationRepositoryService } from '../../services/change-recommendation-repository.service';
|
||||
import { ViewChangeReco } from '../../models/view-change-reco';
|
||||
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
|
||||
|
||||
import { ViewUnifiedChange } from '../../models/view-unified-change';
|
||||
import { OperatorService } from '../../../../core/services/operator.service';
|
||||
import { BaseViewComponent } from '../../../base/base-view';
|
||||
@ -27,11 +29,14 @@ import { ViewStatuteParagraph } from '../../models/view-statute-paragraph';
|
||||
import { StatuteParagraphRepositoryService } from '../../services/statute-paragraph-repository.service';
|
||||
import { ConfigService } from '../../../../core/services/config.service';
|
||||
import { Workflow } from 'app/shared/models/motions/workflow';
|
||||
import { take, takeWhile, multicast, skipWhile } from 'rxjs/operators';
|
||||
import { LocalPermissionsService } from '../../services/local-permissions.service';
|
||||
import { ViewCreateMotion } from '../../models/view-create-motion';
|
||||
import { CreateMotion } from '../../models/create-motion';
|
||||
import { MotionBlock } from 'app/shared/models/motions/motion-block';
|
||||
import { itemVisibilityChoices, Item } from 'app/shared/models/agenda/item';
|
||||
import { PromptService } from 'app/core/services/prompt.service';
|
||||
import { AgendaRepositoryService } from 'app/site/agenda/services/agenda-repository.service';
|
||||
import { Mediafile } from 'app/shared/models/mediafiles/mediafile';
|
||||
|
||||
/**
|
||||
* Component for the motion detail view
|
||||
@ -56,11 +61,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
@ViewChild('contentPanel')
|
||||
public contentPanel: MatExpansionPanel;
|
||||
|
||||
/**
|
||||
* Motions meta-info
|
||||
*/
|
||||
public metaInfoForm: FormGroup;
|
||||
|
||||
/**
|
||||
* Motion content. Can be a new version
|
||||
*/
|
||||
@ -184,6 +184,16 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
*/
|
||||
public blockObserver: BehaviorSubject<MotionBlock[]>;
|
||||
|
||||
/**
|
||||
* Subject for mediafiles
|
||||
*/
|
||||
public mediafilesObserver: BehaviorSubject<Mediafile[]>;
|
||||
|
||||
/**
|
||||
* Subject for agenda items
|
||||
*/
|
||||
public agendaItemObserver: BehaviorSubject<Item[]>;
|
||||
|
||||
/**
|
||||
* Determine if the name of supporters are visible
|
||||
*/
|
||||
@ -209,6 +219,16 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
*/
|
||||
public showAmendmentContext = false;
|
||||
|
||||
/**
|
||||
* Determines the default agenda item visibility
|
||||
*/
|
||||
public defaultVisibility: number;
|
||||
|
||||
/**
|
||||
* Determine visibility states for the agenda that will be created implicitly
|
||||
*/
|
||||
public itemVisibility = itemVisibilityChoices;
|
||||
|
||||
/**
|
||||
* Constuct the detail view.
|
||||
*
|
||||
@ -222,11 +242,13 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
* @param formBuilder For reactive forms. Form Group and Form Control
|
||||
* @param dialogService For opening dialogs
|
||||
* @param repo Motion Repository
|
||||
* @param agendaRepo Read out agenda variables
|
||||
* @param changeRecoRepo Change Recommendation Repository
|
||||
* @param statuteRepo: Statute Paragraph Repository
|
||||
* @param DS The DataStoreService
|
||||
* @param configService The configuration provider
|
||||
* @param sanitizer For making HTML SafeHTML
|
||||
* @param promptService ensure safe deletion
|
||||
*/
|
||||
public constructor(
|
||||
title: Title,
|
||||
@ -240,15 +262,15 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
private formBuilder: FormBuilder,
|
||||
private dialogService: MatDialog,
|
||||
private repo: MotionRepositoryService,
|
||||
private agendaRepo: AgendaRepositoryService,
|
||||
private changeRecoRepo: ChangeRecommendationRepositoryService,
|
||||
private statuteRepo: StatuteParagraphRepositoryService,
|
||||
private DS: DataStoreService,
|
||||
private configService: ConfigService,
|
||||
private sanitizer: DomSanitizer
|
||||
private sanitizer: DomSanitizer,
|
||||
private promptService: PromptService
|
||||
) {
|
||||
super(title, translate, matSnackBar);
|
||||
this.createForm();
|
||||
this.getMotionByUrl();
|
||||
|
||||
// Initial Filling of the Subjects
|
||||
this.submitterObserver = new BehaviorSubject(DS.getAll(User));
|
||||
@ -256,6 +278,8 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
this.categoryObserver = new BehaviorSubject(DS.getAll(Category));
|
||||
this.workflowObserver = new BehaviorSubject(DS.getAll(Workflow));
|
||||
this.blockObserver = new BehaviorSubject(DS.getAll(MotionBlock));
|
||||
this.mediafilesObserver = new BehaviorSubject(DS.getAll(Mediafile));
|
||||
this.agendaItemObserver = new BehaviorSubject(DS.getAll(Item));
|
||||
|
||||
// Make sure the subjects are updated, when a new Model for the type arrives
|
||||
this.DS.changeObservable.subscribe(newModel => {
|
||||
@ -268,8 +292,13 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
this.workflowObserver.next(DS.getAll(Workflow));
|
||||
} else if (newModel instanceof MotionBlock) {
|
||||
this.blockObserver.next(DS.getAll(MotionBlock));
|
||||
} else if (newModel instanceof Mediafile) {
|
||||
this.mediafilesObserver.next(DS.getAll(Mediafile));
|
||||
} else if (newModel instanceof Item) {
|
||||
this.agendaItemObserver.next(DS.getAll(Item));
|
||||
}
|
||||
});
|
||||
|
||||
// load config variables
|
||||
this.configService.get('motions_statutes_enabled').subscribe(enabled => (this.statutesEnabled = enabled));
|
||||
this.configService.get('motions_min_supporters').subscribe(supporters => (this.minSupporters = supporters));
|
||||
@ -277,6 +306,45 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
this.configService.get('motions_amendments_enabled').subscribe(enabled => (this.amendmentsEnabled = enabled));
|
||||
}
|
||||
|
||||
/**
|
||||
* Init.
|
||||
* Sets the surrounding motions to navigate back and forth
|
||||
*/
|
||||
public ngOnInit(): void {
|
||||
this.createForm();
|
||||
this.getMotionByUrl();
|
||||
|
||||
this.repo.getViewModelListObservable().subscribe(newMotionList => {
|
||||
if (newMotionList) {
|
||||
this.allMotions = newMotionList;
|
||||
this.setSurroundingMotions();
|
||||
}
|
||||
});
|
||||
|
||||
this.statuteRepo.getViewModelListObservable().subscribe(newViewStatuteParagraphs => {
|
||||
this.statuteParagraphs = newViewStatuteParagraphs;
|
||||
});
|
||||
|
||||
// Set the default visibility using observers
|
||||
this.agendaRepo.getDefaultAgendaVisibility().subscribe(visibility => {
|
||||
if (visibility && this.newMotion) {
|
||||
this.contentForm.get('agenda_type').setValue(visibility);
|
||||
}
|
||||
});
|
||||
|
||||
// disable the selector for attachments if there are none
|
||||
this.mediafilesObserver.subscribe(files => {
|
||||
if (this.createForm) {
|
||||
const attachmentsCtrl = this.contentForm.get('attachments_id');
|
||||
if (this.mediafilesObserver.value.length === 0) {
|
||||
attachmentsCtrl.disable();
|
||||
} else {
|
||||
attachmentsCtrl.enable();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges amendments and change recommendations and sorts them by the line numbers.
|
||||
* Called each time one of these arrays changes.
|
||||
@ -350,12 +418,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
* Async load the values of the motion in the Form.
|
||||
*/
|
||||
public patchForm(formMotion: ViewMotion): void {
|
||||
const metaInfoPatch = {};
|
||||
Object.keys(this.metaInfoForm.controls).forEach(ctrl => {
|
||||
metaInfoPatch[ctrl] = formMotion[ctrl];
|
||||
});
|
||||
this.metaInfoForm.patchValue(metaInfoPatch);
|
||||
|
||||
const contentPatch: { [key: string]: any } = {};
|
||||
Object.keys(this.contentForm.controls).forEach(ctrl => {
|
||||
contentPatch[ctrl] = formMotion[ctrl];
|
||||
@ -380,20 +442,19 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
* TODO: Build a custom form validator
|
||||
*/
|
||||
public createForm(): void {
|
||||
this.metaInfoForm = this.formBuilder.group({
|
||||
identifier: [''],
|
||||
category_id: [''],
|
||||
state_id: [''],
|
||||
recommendation_id: [''],
|
||||
submitters_id: [],
|
||||
supporters_id: [[]],
|
||||
workflow_id: [],
|
||||
origin: ['']
|
||||
});
|
||||
this.contentForm = this.formBuilder.group({
|
||||
identifier: [''],
|
||||
title: ['', Validators.required],
|
||||
text: ['', Validators.required],
|
||||
reason: [''],
|
||||
category_id: [''],
|
||||
attachments_id: [[]],
|
||||
parent_id: [],
|
||||
agenda_type: [''],
|
||||
submitters_id: [],
|
||||
supporters_id: [[]],
|
||||
workflow_id: [],
|
||||
origin: [''],
|
||||
statute_amendment: [''], // Internal value for the checkbox, not saved to the model
|
||||
statute_paragraph_id: ['']
|
||||
});
|
||||
@ -417,6 +478,8 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
*
|
||||
* @param motionValues valus for the new motion
|
||||
* @param ctor The motion constructor, so different motion types can be created.
|
||||
*
|
||||
* @returns the motion to save
|
||||
*/
|
||||
private prepareMotionForSave<T extends Motion>(motionValues: any, ctor: new (...args: any[]) => T): T {
|
||||
const motion = new ctor();
|
||||
@ -440,7 +503,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
* Creates a motion. Calls the "patchValues" function in the MotionObject
|
||||
*/
|
||||
public async createMotion(): Promise<void> {
|
||||
const newMotionValues = { ...this.metaInfoForm.value, ...this.contentForm.value };
|
||||
const newMotionValues = { ...this.contentForm.value };
|
||||
const motion = this.prepareMotionForSave(newMotionValues, CreateMotion);
|
||||
|
||||
try {
|
||||
@ -455,7 +518,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
* Save a motion. Calls the "patchValues" function in the MotionObject
|
||||
*/
|
||||
public async updateMotion(): Promise<void> {
|
||||
const newMotionValues = { ...this.metaInfoForm.value, ...this.contentForm.value };
|
||||
const newMotionValues = { ...this.contentForm.value };
|
||||
const motion = this.prepareMotionForSave(newMotionValues, Motion);
|
||||
this.repo.update(motion, this.motionCopy).then(() => (this.editMotion = false), this.raiseError);
|
||||
}
|
||||
@ -473,6 +536,8 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* get the formated motion text from the repository.
|
||||
*
|
||||
* @returns formated motion texts
|
||||
*/
|
||||
public getFormattedTextPlain(): string {
|
||||
// Prevent this.allChangingObjects to be reordered from within formatMotion
|
||||
@ -510,9 +575,9 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
* If `this.motion` is an amendment, this returns a specified line range from the parent motion
|
||||
* (e.g. to show the contect in which this amendment is happening)
|
||||
*
|
||||
* @param {number} from
|
||||
* @param {number} to
|
||||
* @returns {SafeHtml}
|
||||
* @param from the line number to start
|
||||
* @param to the line number to stop
|
||||
* @returns safe html strings
|
||||
*/
|
||||
public getParentMotionRange(from: number, to: number): SafeHtml {
|
||||
const str = this.repo.extractMotionLineRange(this.motion.parent_id, { from, to }, true);
|
||||
@ -521,7 +586,8 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* get the diff html from the statute amendment, as SafeHTML for [innerHTML]
|
||||
* @returns {SafeHtml}
|
||||
*
|
||||
* @returns safe html strings
|
||||
*/
|
||||
public getFormattedStatuteAmendment(): SafeHtml {
|
||||
const diffHtml = this.repo.formatStatuteAmendment(this.statuteParagraphs, this.motion, this.motion.lineLength);
|
||||
@ -530,17 +596,18 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* Trigger to delete the motion.
|
||||
* Sends a delete request over the repository and
|
||||
* shows a "are you sure" dialog
|
||||
*/
|
||||
public async deleteMotionButton(): Promise<void> {
|
||||
this.repo.delete(this.motion).then(() => {
|
||||
const content = this.translate.instant('Are you sure you want to delete this motion block?');
|
||||
if (await this.promptService.open(this.motion.title, content)) {
|
||||
await this.repo.delete(this.motion);
|
||||
this.router.navigate(['./motions/']);
|
||||
}, this.raiseError);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the motions line numbering mode
|
||||
*
|
||||
* @param mode Needs to got the enum defined in ViewMotion
|
||||
*/
|
||||
public setLineNumberingMode(mode: LineNumberingMode): void {
|
||||
@ -549,6 +616,8 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* Returns true if no line numbers are to be shown.
|
||||
*
|
||||
* @returns whether there are line numbers at all
|
||||
*/
|
||||
public isLineNumberingNone(): boolean {
|
||||
return this.motion.lnMode === LineNumberingMode.None;
|
||||
@ -556,6 +625,8 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* Returns true if the line numbers are to be shown within the text with no line breaks.
|
||||
*
|
||||
* @returns whether the line numberings are inside
|
||||
*/
|
||||
public isLineNumberingInline(): boolean {
|
||||
return this.motion.lnMode === LineNumberingMode.Inside;
|
||||
@ -563,6 +634,8 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* Returns true if the line numbers are to be shown to the left of the text.
|
||||
*
|
||||
* @returns whether the line numberings are outside
|
||||
*/
|
||||
public isLineNumberingOutside(): boolean {
|
||||
return this.motion.lnMode === LineNumberingMode.Outside;
|
||||
@ -627,6 +700,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* Comes from the head bar
|
||||
*
|
||||
* @param mode
|
||||
*/
|
||||
public setEditMode(mode: boolean): void {
|
||||
@ -644,6 +718,9 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default workflow ID during form creation
|
||||
*/
|
||||
public updateWorkflowIdForCreateForm(): void {
|
||||
const isStatuteAmendment = !!this.contentForm.get('statute_amendment').value;
|
||||
const configKey = isStatuteAmendment ? 'motions_statute_amendments_workflow' : 'motions_workflow';
|
||||
@ -663,7 +740,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
skipWhile(id => !id)
|
||||
)
|
||||
.subscribe(id => {
|
||||
this.metaInfoForm.patchValue({
|
||||
this.contentForm.patchValue({
|
||||
workflow_id: parseInt(id, 10)
|
||||
});
|
||||
});
|
||||
@ -671,6 +748,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* If the checkbox is deactivated, the statute_paragraph_id-field needs to be reset, as only that field is saved
|
||||
*
|
||||
* @param {MatCheckboxChange} $event
|
||||
*/
|
||||
public onStatuteAmendmentChange($event: MatCheckboxChange): void {
|
||||
@ -682,6 +760,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* The paragraph of the statute to amend was changed -> change the input fields below
|
||||
*
|
||||
* @param {number} newValue
|
||||
*/
|
||||
public onStatuteParagraphChange(newValue: number): void {
|
||||
@ -694,6 +773,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* Navigates the user to the given ViewMotion
|
||||
*
|
||||
* @param motion target
|
||||
*/
|
||||
public navigateToMotion(motion: ViewMotion): void {
|
||||
@ -749,6 +829,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* Sets the state
|
||||
*
|
||||
* @param id Motion state id
|
||||
*/
|
||||
public setState(id: number): void {
|
||||
@ -757,6 +838,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* Sets the recommendation
|
||||
*
|
||||
* @param id Motion recommendation id
|
||||
*/
|
||||
public setRecommendation(id: number): void {
|
||||
@ -765,6 +847,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* Sets the category for current motion
|
||||
*
|
||||
* @param id Motion category id
|
||||
*/
|
||||
public setCategory(id: number): void {
|
||||
@ -797,32 +880,29 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* Create the absolute path to the corresponding list of speakers
|
||||
*
|
||||
* @returns the link to the corresponding list of speakers as string
|
||||
*/
|
||||
public getSpeakerLink(): string {
|
||||
return `/agenda/${this.motion.agenda_item_id}/speakers`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Click handler for attachments
|
||||
*
|
||||
* @param attachment the selected file
|
||||
*/
|
||||
public onClickAttacment(attachment: Mediafile): void {
|
||||
window.open(attachment.getDownloadUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the user has the correct requirements to alter the motion
|
||||
* TODO: All views should probably have a "isAllowedTo" routine to simplify this process
|
||||
*
|
||||
* @returns whether or not the OP is allowed to edit the motion
|
||||
*/
|
||||
public opCanEdit(): boolean {
|
||||
return this.op.hasPerms('motions.can_manage', 'motions.can_manage_metadata');
|
||||
}
|
||||
|
||||
/**
|
||||
* Init.
|
||||
* Sets the surrounding motions to navigate back and forth
|
||||
*/
|
||||
public ngOnInit(): void {
|
||||
this.repo.getViewModelListObservable().subscribe(newMotionList => {
|
||||
if (newMotionList) {
|
||||
this.allMotions = newMotionList;
|
||||
this.setSurroundingMotions();
|
||||
}
|
||||
});
|
||||
this.statuteRepo.getViewModelListObservable().subscribe(newViewStatuteParagraphs => {
|
||||
this.statuteParagraphs = newViewStatuteParagraphs;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -41,13 +41,21 @@
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header>Title</mat-header-cell>
|
||||
<mat-cell *matCellDef="let motion">
|
||||
<div class="innerTable">
|
||||
<span class="motion-list-title">{{ motion.title }}</span> <br />
|
||||
<span class="motion-list-title">{{ motion.title }}</span>
|
||||
<!-- attachments -->
|
||||
<span class="attached-files" *ngIf="motion.hasAttachments()">
|
||||
<!-- <mat-basic-chip class="bluegrey"> <mat-icon>attach_file</mat-icon> </mat-basic-chip> -->
|
||||
<mat-icon>attach_file</mat-icon>
|
||||
</span>
|
||||
|
||||
<br />
|
||||
<span class="motion-list-from" *ngIf="motion.submitters.length">
|
||||
<span translate>by</span> {{ motion.submitters }}
|
||||
</span>
|
||||
<br *ngIf="motion.submitters.length" />
|
||||
<!-- state -->
|
||||
<mat-basic-chip
|
||||
*ngIf="motion.state"
|
||||
[ngClass]="{
|
||||
green: motion.state.css_class === 'success',
|
||||
red: motion.state.css_class === 'danger',
|
||||
|
@ -30,6 +30,17 @@
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.attached-files {
|
||||
.mat-icon {
|
||||
display: inline-flex;
|
||||
vertical-align: middle;
|
||||
$icon-size: 16px;
|
||||
font-size: $icon-size;
|
||||
height: $icon-size;
|
||||
width: $icon-size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** State */
|
||||
|
@ -9,6 +9,7 @@ import { ViewMotionCommentSection } from './view-motion-comment-section';
|
||||
import { MotionComment } from '../../../shared/models/motions/motion-comment';
|
||||
import { Item } from 'app/shared/models/agenda/item';
|
||||
import { MotionBlock } from 'app/shared/models/motions/motion-block';
|
||||
import { Mediafile } from 'app/shared/models/mediafiles/mediafile';
|
||||
|
||||
export enum LineNumberingMode {
|
||||
None,
|
||||
@ -39,6 +40,7 @@ export class ViewMotion extends BaseViewModel {
|
||||
protected _state: WorkflowState;
|
||||
protected _item: Item;
|
||||
protected _block: MotionBlock;
|
||||
protected _attachments: Mediafile[];
|
||||
|
||||
/**
|
||||
* Indicates the LineNumberingMode Mode.
|
||||
@ -79,7 +81,7 @@ export class ViewMotion extends BaseViewModel {
|
||||
}
|
||||
|
||||
public get identifier(): string {
|
||||
return this.motion ? this.motion.identifier : null;
|
||||
return this.motion && this.motion.identifier ? this.motion.identifier : null;
|
||||
}
|
||||
|
||||
public get title(): string {
|
||||
@ -188,6 +190,10 @@ export class ViewMotion extends BaseViewModel {
|
||||
return this._item;
|
||||
}
|
||||
|
||||
public get agenda_type(): number {
|
||||
return this.item ? this.item.type : null;
|
||||
}
|
||||
|
||||
public get motion_block_id(): number {
|
||||
return this.motion ? this.motion.motion_block_id : null;
|
||||
}
|
||||
@ -209,7 +215,15 @@ export class ViewMotion extends BaseViewModel {
|
||||
}
|
||||
|
||||
public get tags_id(): number[] {
|
||||
return this._motion ? this._motion.tags_id : null;
|
||||
return this.motion ? this.motion.tags_id : null;
|
||||
}
|
||||
|
||||
public get attachments_id(): number[] {
|
||||
return this.motion ? this.motion.attachments_id : null
|
||||
}
|
||||
|
||||
public get attachments(): Mediafile[] {
|
||||
return this._attachments ? this._attachments : null;
|
||||
}
|
||||
|
||||
public constructor(
|
||||
@ -220,10 +234,10 @@ export class ViewMotion extends BaseViewModel {
|
||||
workflow?: Workflow,
|
||||
state?: WorkflowState,
|
||||
item?: Item,
|
||||
block?: MotionBlock
|
||||
block?: MotionBlock,
|
||||
attachments?: Mediafile[],
|
||||
) {
|
||||
super();
|
||||
|
||||
this._motion = motion;
|
||||
this._category = category;
|
||||
this._submitters = submitters;
|
||||
@ -232,6 +246,7 @@ export class ViewMotion extends BaseViewModel {
|
||||
this._state = state;
|
||||
this._item = item;
|
||||
this._block = block;
|
||||
this._attachments = attachments;
|
||||
|
||||
// TODO: Should be set using a a config variable
|
||||
/*this._configService.get('motions_default_line_numbering').subscribe(
|
||||
@ -255,6 +270,7 @@ export class ViewMotion extends BaseViewModel {
|
||||
|
||||
/**
|
||||
* Returns the motion comment for the given section. Null, if no comment exist.
|
||||
*
|
||||
* @param section The section to search the comment for.
|
||||
*/
|
||||
public getCommentForSection(section: ViewMotionCommentSection): MotionComment {
|
||||
@ -266,6 +282,7 @@ export class ViewMotion extends BaseViewModel {
|
||||
|
||||
/**
|
||||
* Updates the local objects if required
|
||||
*
|
||||
* @param update
|
||||
*/
|
||||
public updateValues(update: BaseModel): void {
|
||||
@ -279,11 +296,14 @@ export class ViewMotion extends BaseViewModel {
|
||||
this.updateMotionBlock(update);
|
||||
} else if (update instanceof User) {
|
||||
this.updateUser(update as User);
|
||||
} else if (update instanceof Mediafile) {
|
||||
this.updateAttachments(update as Mediafile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update routine for the category
|
||||
*
|
||||
* @param category potentially the changed category. Needs manual verification
|
||||
*/
|
||||
public updateCategory(category: Category): void {
|
||||
@ -294,6 +314,7 @@ export class ViewMotion extends BaseViewModel {
|
||||
|
||||
/**
|
||||
* Update routine for the workflow
|
||||
*
|
||||
* @param workflow potentially the changed workflow (state). Needs manual verification
|
||||
*/
|
||||
public updateWorkflow(workflow: Workflow): void {
|
||||
@ -304,6 +325,7 @@ export class ViewMotion extends BaseViewModel {
|
||||
|
||||
/**
|
||||
* Update routine for the agenda Item
|
||||
*
|
||||
* @param item potentially the changed agenda Item. Needs manual verification
|
||||
*/
|
||||
public updateItem(item: Item): void {
|
||||
@ -314,6 +336,7 @@ export class ViewMotion extends BaseViewModel {
|
||||
|
||||
/**
|
||||
* Update routine for the motion block
|
||||
*
|
||||
* @param block potentially the changed motion block. Needs manual verification
|
||||
*/
|
||||
public updateMotionBlock(block: MotionBlock): void {
|
||||
@ -323,7 +346,8 @@ export class ViewMotion extends BaseViewModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update routine for the agenda Item
|
||||
* Update routine for supporters and submitters
|
||||
*
|
||||
* @param update potentially the changed agenda Item. Needs manual verification
|
||||
*/
|
||||
public updateUser(update: User): void {
|
||||
@ -339,10 +363,28 @@ export class ViewMotion extends BaseViewModel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update routine for attachments
|
||||
*
|
||||
* @param update
|
||||
*/
|
||||
public updateAttachments(update: Mediafile): void {
|
||||
if (this.motion) {
|
||||
if (this.attachments_id && this.attachments_id.includes(update.id)) {
|
||||
const attachmentIndex = this.attachments.findIndex(mediafile => mediafile.id === update.id);
|
||||
this.attachments[attachmentIndex] = update as Mediafile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public hasSupporters(): boolean {
|
||||
return !!(this.supporters && this.supporters.length > 0);
|
||||
}
|
||||
|
||||
public hasAttachments(): boolean {
|
||||
return !!(this.attachments && this.attachments.length > 0);
|
||||
}
|
||||
|
||||
public isStatuteAmendment(): boolean {
|
||||
return !!this.statute_paragraph_id;
|
||||
}
|
||||
@ -372,7 +414,10 @@ export class ViewMotion extends BaseViewModel {
|
||||
this._submitters,
|
||||
this._supporters,
|
||||
this._workflow,
|
||||
this._state
|
||||
this._state,
|
||||
this._item,
|
||||
this._block,
|
||||
this._attachments
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ import { ViewMotion } from '../models/view-motion';
|
||||
import { Observable } from 'rxjs';
|
||||
import { MotionRepositoryService } from './motion-repository.service';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { ConfigService } from 'app/core/services/config.service';
|
||||
|
||||
/**
|
||||
* Repository service for motion blocks
|
||||
@ -28,14 +27,12 @@ export class MotionBlockRepositoryService extends BaseRepository<ViewMotionBlock
|
||||
* @param mapperService Mapping collection strings to classes
|
||||
* @param dataSend Send models to the server
|
||||
* @param motionRepo Accessing the motion repository
|
||||
* @param config To access config variables
|
||||
*/
|
||||
public constructor(
|
||||
DS: DataStoreService,
|
||||
mapperService: CollectionStringModelMapperService,
|
||||
private dataSend: DataSendService,
|
||||
private motionRepo: MotionRepositoryService,
|
||||
private config: ConfigService
|
||||
) {
|
||||
super(DS, mapperService, MotionBlock);
|
||||
}
|
||||
@ -103,15 +100,6 @@ export class MotionBlockRepositoryService extends BaseRepository<ViewMotionBlock
|
||||
return this.DS.filter(Motion, motion => motion.motion_block_id === block.id).length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get agenda visibility from the config
|
||||
*
|
||||
* @return An observable to the default agenda visibility
|
||||
*/
|
||||
public getDefaultAgendaVisibility(): Observable<number> {
|
||||
return this.config.get('agenda_new_items_default_visibility').pipe(map(key => +key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Observe the motion repository and return the motions belonging to the given
|
||||
* block as observable
|
||||
|
@ -27,6 +27,7 @@ import { TreeService } from 'app/core/services/tree.service';
|
||||
import { ViewMotionAmendedParagraph } from '../models/view-motion-amended-paragraph';
|
||||
import { CreateMotion } from '../models/create-motion';
|
||||
import { MotionBlock } from 'app/shared/models/motions/motion-block';
|
||||
import { Mediafile } from 'app/shared/models/mediafiles/mediafile';
|
||||
|
||||
/**
|
||||
* Repository Services for motions (and potentially categories)
|
||||
@ -64,7 +65,7 @@ export class MotionRepositoryService extends BaseRepository<ViewMotion, Motion>
|
||||
private readonly diff: DiffService,
|
||||
private treeService: TreeService
|
||||
) {
|
||||
super(DS, mapperService, Motion, [Category, User, Workflow, Item, MotionBlock]);
|
||||
super(DS, mapperService, Motion, [Category, User, Workflow, Item, MotionBlock, Mediafile]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,11 +83,12 @@ export class MotionRepositoryService extends BaseRepository<ViewMotion, Motion>
|
||||
const workflow = this.DS.get(Workflow, motion.workflow_id);
|
||||
const item = this.DS.get(Item, motion.agenda_item_id);
|
||||
const block = this.DS.get(MotionBlock, motion.motion_block_id);
|
||||
const attachments = this.DS.getMany(Mediafile, motion.attachments_id);
|
||||
let state: WorkflowState = null;
|
||||
if (workflow) {
|
||||
state = workflow.getStateById(motion.state_id);
|
||||
}
|
||||
return new ViewMotion(motion, category, submitters, supporters, workflow, state, item, block);
|
||||
return new ViewMotion(motion, category, submitters, supporters, workflow, state, item, block, attachments);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user