check permissions for motions
This commit is contained in:
parent
2d40072f44
commit
fb51b54d5c
@ -1,17 +1,24 @@
|
|||||||
<h4 translate>
|
<h4 translate>
|
||||||
<span translate>Submitters</span>
|
<span translate>Submitters</span>
|
||||||
<button class="small-button" type="button" mat-icon-button disableRipple *ngIf="!isEditMode" (click)="onEdit()">
|
<button
|
||||||
|
class="small-button"
|
||||||
|
type="button"
|
||||||
|
mat-icon-button
|
||||||
|
disableRipple
|
||||||
|
*ngIf="!isEditMode && perms.isAllowed('change_metadata')"
|
||||||
|
(click)="onEdit()"
|
||||||
|
>
|
||||||
<mat-icon>edit</mat-icon>
|
<mat-icon>edit</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<div *ngIf="!isEditMode">
|
<div *ngIf="!isEditMode || !perms.isAllowed('change_metadata')">
|
||||||
<mat-chip-list *ngFor="let submitter of motion.submitters" class="user">
|
<mat-chip-list *ngFor="let submitter of motion.submitters" class="user">
|
||||||
<mat-chip>{{ submitter.full_name }}</mat-chip>
|
<mat-chip>{{ submitter.full_name }}</mat-chip>
|
||||||
</mat-chip-list>
|
</mat-chip-list>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="isEditMode">
|
<div *ngIf="isEditMode && perms.isAllowed('change_metadata')">
|
||||||
<os-sorting-list
|
<os-sorting-list
|
||||||
[input]="editSubmitterObservable"
|
[input]="editSubmitterObservable"
|
||||||
[live]="true"
|
[live]="true"
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input } from '@angular/core';
|
||||||
import { FormGroup, FormControl } from '@angular/forms';
|
import { FormGroup, FormControl } from '@angular/forms';
|
||||||
|
import { MatSnackBar } from '@angular/material';
|
||||||
import { Title } from '@angular/platform-browser';
|
import { Title } from '@angular/platform-browser';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { MatSnackBar } from '@angular/material';
|
|
||||||
|
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
|
||||||
import { ViewMotion } from '../../models/view-motion';
|
|
||||||
import { User } from 'app/shared/models/users/user';
|
|
||||||
import { DataStoreService } from 'app/core/services/data-store.service';
|
|
||||||
import { MotionRepositoryService } from '../../services/motion-repository.service';
|
|
||||||
import { BaseViewComponent } from 'app/site/base/base-view';
|
import { BaseViewComponent } from 'app/site/base/base-view';
|
||||||
|
import { DataStoreService } from 'app/core/services/data-store.service';
|
||||||
|
import { LocalPermissionsService } from '../../services/local-permissions.service';
|
||||||
|
import { MotionRepositoryService } from '../../services/motion-repository.service';
|
||||||
|
import { User } from 'app/shared/models/users/user';
|
||||||
|
import { ViewMotion } from '../../models/view-motion';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component for the motion comments view
|
* Component for the motion comments view
|
||||||
@ -61,13 +62,15 @@ export class ManageSubmittersComponent extends BaseViewComponent {
|
|||||||
* @param matSnackBar
|
* @param matSnackBar
|
||||||
* @param DS
|
* @param DS
|
||||||
* @param repo
|
* @param repo
|
||||||
|
* @param perms permission checks for the motion
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
title: Title,
|
title: Title,
|
||||||
translate: TranslateService,
|
translate: TranslateService,
|
||||||
matSnackBar: MatSnackBar,
|
matSnackBar: MatSnackBar,
|
||||||
private DS: DataStoreService,
|
private DS: DataStoreService,
|
||||||
private repo: MotionRepositoryService
|
private repo: MotionRepositoryService,
|
||||||
|
public perms: LocalPermissionsService
|
||||||
) {
|
) {
|
||||||
super(title, translate, matSnackBar);
|
super(title, translate, matSnackBar);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<os-head-bar
|
<os-head-bar
|
||||||
[mainButton]="opCanEdit()"
|
[mainButton]="perms.isAllowed('update_motion', motion)"
|
||||||
mainButtonIcon="edit"
|
mainButtonIcon="edit"
|
||||||
[nav]="false"
|
[nav]="false"
|
||||||
[editMode]="editMotion"
|
[editMode]="editMotion"
|
||||||
@ -61,13 +61,12 @@
|
|||||||
<mat-menu #motionExtraMenu="matMenu">
|
<mat-menu #motionExtraMenu="matMenu">
|
||||||
<div *ngIf="motion">
|
<div *ngIf="motion">
|
||||||
<!-- PDF -->
|
<!-- PDF -->
|
||||||
<button mat-menu-item
|
<button mat-menu-item (click)="onDownloadPdf()">
|
||||||
(click)="onDownloadPdf()">
|
|
||||||
<mat-icon>picture_as_pdf</mat-icon>
|
<mat-icon>picture_as_pdf</mat-icon>
|
||||||
<span translate>PDF</span>
|
<span translate>PDF</span>
|
||||||
</button>
|
</button>
|
||||||
<!-- List of speakers -->
|
<!-- List of speakers -->
|
||||||
<button mat-menu-item [routerLink]="getSpeakerLink()">
|
<button mat-menu-item [routerLink]="getSpeakerLink()" *osPerms="'agenda.can_see'">
|
||||||
<mat-icon>mic</mat-icon>
|
<mat-icon>mic</mat-icon>
|
||||||
<span translate>List of speakers</span>
|
<span translate>List of speakers</span>
|
||||||
</button>
|
</button>
|
||||||
@ -80,7 +79,7 @@
|
|||||||
<button
|
<button
|
||||||
mat-menu-item
|
mat-menu-item
|
||||||
(click)="createAmendment()"
|
(click)="createAmendment()"
|
||||||
*ngIf="amendmentsEnabled && motion && !motion.isParagraphBasedAmendment()"
|
*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>
|
||||||
@ -95,14 +94,15 @@
|
|||||||
<span translate>Show entire motion text</span>
|
<span translate>Show entire motion text</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<div *ngIf="perms.isAllowed('manage')">
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<!-- Delete -->
|
<!-- Delete -->
|
||||||
<button mat-menu-item class="red-warning-text" (click)="deleteMotionButton()">
|
<button mat-menu-item class="red-warning-text" (click)="deleteMotionButton()">
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
<span translate>Delete</span>
|
<span translate>Delete</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</os-head-bar>
|
</os-head-bar>
|
||||||
|
|
||||||
@ -110,9 +110,7 @@
|
|||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<div class="title on-transition-fade" *ngIf="motion && !editMotion">
|
<div class="title on-transition-fade" *ngIf="motion && !editMotion">
|
||||||
<div class="title-line">
|
<div class="title-line">
|
||||||
<h1>
|
<h1>{{ motion.title }}</h1>
|
||||||
{{ motion.title }}
|
|
||||||
</h1>
|
|
||||||
<button mat-icon-button color="primary" (click)="toggleFavorite()">
|
<button mat-icon-button color="primary" (click)="toggleFavorite()">
|
||||||
<mat-icon>{{ motion.star ? 'star' : 'star_border' }}</mat-icon>
|
<mat-icon>{{ motion.star ? 'star' : 'star_border' }}</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
@ -124,18 +122,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-template #mobileView>
|
<ng-template #mobileView>
|
||||||
|
|
||||||
<!-- Meta info -->
|
<!-- Meta info -->
|
||||||
<div class="hspacing">
|
<div class="hspacing"><ng-container *ngTemplateOutlet="metaInfoTemplate"></ng-container></div>
|
||||||
<ng-container *ngTemplateOutlet="metaInfoTemplate"></ng-container>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<mat-divider class="spacer-top-10 spacer-bottom-20"></mat-divider>
|
<mat-divider class="spacer-top-10 spacer-bottom-20"></mat-divider>
|
||||||
|
|
||||||
<!-- Content -->
|
<!-- Content -->
|
||||||
<div class="hspacing">
|
<div class="hspacing"><ng-container *ngTemplateOutlet="contentTemplate"></ng-container></div>
|
||||||
<ng-container *ngTemplateOutlet="contentTemplate"></ng-container>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<mat-divider class="spacer-top-10 spacer-bottom-20"></mat-divider>
|
<mat-divider class="spacer-top-10 spacer-bottom-20"></mat-divider>
|
||||||
|
|
||||||
@ -145,11 +138,14 @@
|
|||||||
<!-- Personal note -->
|
<!-- Personal note -->
|
||||||
<os-personal-note *ngIf="!editMotion" [motion]="motion"></os-personal-note>
|
<os-personal-note *ngIf="!editMotion" [motion]="motion"></os-personal-note>
|
||||||
|
|
||||||
<!-- Motoin log -->
|
<ng-container *ngTemplateOutlet="motionLogTemplate"></ng-container>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template #motionLogTemplate>
|
||||||
<button mat-button *ngIf="canShowLog" (click)="motionLogExpanded = !motionLogExpanded">
|
<button mat-button *ngIf="canShowLog" (click)="motionLogExpanded = !motionLogExpanded">
|
||||||
<span translate>Show motion log</span>
|
<span translate>Show motion log</span>
|
||||||
</button>
|
</button>
|
||||||
<os-motion-log *ngIf="motionLogExpanded" [motion]="motion"></os-motion-log>
|
<os-motion-log *ngIf="canShowLog && motionLogExpanded" [motion]="motion"></os-motion-log>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template #desktopView>
|
<ng-template #desktopView>
|
||||||
@ -162,10 +158,7 @@
|
|||||||
|
|
||||||
<os-motion-comments *ngIf="!editMotion" [motion]="motion"></os-motion-comments>
|
<os-motion-comments *ngIf="!editMotion" [motion]="motion"></os-motion-comments>
|
||||||
<os-personal-note *ngIf="!editMotion" [motion]="motion"></os-personal-note>
|
<os-personal-note *ngIf="!editMotion" [motion]="motion"></os-personal-note>
|
||||||
<button mat-button *ngIf="canShowLog" (click)="motionLogExpanded =!motionLogExpanded">
|
<ng-container *ngTemplateOutlet="motionLogTemplate"></ng-container>
|
||||||
<span translate>Show motion log</span>
|
|
||||||
</button>
|
|
||||||
<os-motion-log *ngIf="motionLogExpanded" [motion]="motion"></os-motion-log>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="desktop-right ">
|
<div class="desktop-right ">
|
||||||
<!-- Content -->
|
<!-- Content -->
|
||||||
@ -229,24 +222,23 @@
|
|||||||
{{ state.name | translate }}
|
{{ state.name | translate }}
|
||||||
</button>
|
</button>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<button mat-menu-item (click)="setState(null)">
|
<button mat-menu-item (click)="setState(null)" *ngIf="perms.isAllowed('change_metadata', motion)">
|
||||||
<mat-icon>replay</mat-icon> {{ 'Reset state' | translate }}
|
<mat-icon>replay</mat-icon> {{ 'Reset state' | translate }}
|
||||||
</button>
|
</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
<mat-basic-chip
|
<mat-basic-chip
|
||||||
*ngIf="motion.state"
|
*ngIf="perms.isAllowed('change_metadata', motion)"
|
||||||
[matMenuTriggerFor]="stateMenu"
|
[matMenuTriggerFor]="stateMenu"
|
||||||
[ngClass]="{
|
[ngClass]="getStateCssColor()"
|
||||||
green: motion.state.css_class === 'success',
|
>
|
||||||
red: motion.state.css_class === 'danger',
|
{{ motion.state.name | translate }}
|
||||||
grey: motion.state.css_class === 'default',
|
</mat-basic-chip>
|
||||||
lightblue: motion.state.css_class === 'primary'
|
<mat-basic-chip
|
||||||
}"
|
*ngIf="!perms.isAllowed('change_metadata', motion)"
|
||||||
|
[ngClass]="getStateCssColor()"
|
||||||
>
|
>
|
||||||
{{ motion.state.name | translate }}
|
{{ motion.state.name | translate }}
|
||||||
</mat-basic-chip>
|
</mat-basic-chip>
|
||||||
|
|
||||||
<!--*osPerms="['motions.can_manage', 'motions.can_manage_metadata']; -->
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Recommendation -->
|
<!-- Recommendation -->
|
||||||
@ -261,17 +253,33 @@
|
|||||||
{{ recommendation.recommendation_label | translate }}
|
{{ recommendation.recommendation_label | translate }}
|
||||||
</button>
|
</button>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<button mat-menu-item (click)="setRecommendation(null)">
|
<button 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>
|
||||||
<mat-basic-chip [matMenuTriggerFor]="recommendationMenu" class="bluegrey">
|
<mat-basic-chip
|
||||||
|
*ngIf="perms.isAllowed('change_metadata', motion)"
|
||||||
|
[matMenuTriggerFor]="recommendationMenu"
|
||||||
|
class="bluegrey"
|
||||||
|
>
|
||||||
{{
|
{{
|
||||||
motion.recommendation
|
motion.recommendation
|
||||||
? (motion.recommendation.recommendation_label | translate)
|
? (motion.recommendation.recommendation_label | translate)
|
||||||
: ('not set' | translate)
|
: ('not set' | translate)
|
||||||
}}
|
}}
|
||||||
</mat-basic-chip>
|
</mat-basic-chip>
|
||||||
|
<mat-basic-chip
|
||||||
|
*ngIf="!perms.isAllowed('change_metadata', motion)"
|
||||||
|
class="bluegrey"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
motion.recommendation
|
||||||
|
? (motion.recommendation.recommendation_label | translate)
|
||||||
|
: ('not set' | translate)
|
||||||
|
}}
|
||||||
|
</mat-basic-chip>
|
||||||
|
|
||||||
<button mat-button *ngIf="canFollowRecommendation()" (click)="onFollowRecButton()">
|
<button mat-button *ngIf="canFollowRecommendation()" (click)="onFollowRecButton()">
|
||||||
<span translate>Follow recommendation</span>
|
<span translate>Follow recommendation</span>
|
||||||
</button>
|
</button>
|
||||||
@ -291,7 +299,10 @@
|
|||||||
{{ category }}
|
{{ category }}
|
||||||
</button>
|
</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
<mat-basic-chip [matMenuTriggerFor]="categoryMenu" class="grey">
|
<mat-basic-chip *ngIf="perms.isAllowed('change_metadata', motion)" [matMenuTriggerFor]="categoryMenu" class="grey">
|
||||||
|
{{ motion.category ? motion.category : '–' }}
|
||||||
|
</mat-basic-chip>
|
||||||
|
<mat-basic-chip *ngIf="!perms.isAllowed('change_metadata', motion)" class="grey">
|
||||||
{{ motion.category ? motion.category : '–' }}
|
{{ motion.category ? motion.category : '–' }}
|
||||||
</mat-basic-chip>
|
</mat-basic-chip>
|
||||||
</div>
|
</div>
|
||||||
@ -305,7 +316,10 @@
|
|||||||
{{ block }}
|
{{ block }}
|
||||||
</button>
|
</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
<mat-basic-chip [matMenuTriggerFor]="blockMenu" class="grey">
|
<mat-basic-chip *ngIf="perms.isAllowed('change_metadata', motion)" [matMenuTriggerFor]="blockMenu" class="grey">
|
||||||
|
{{ motion.motion_block ? motion.motion_block : '–' }}
|
||||||
|
</mat-basic-chip>
|
||||||
|
<mat-basic-chip *ngIf="!perms.isAllowed('change_metadata', motion)" class="grey">
|
||||||
{{ motion.motion_block ? motion.motion_block : '–' }}
|
{{ motion.motion_block ? motion.motion_block : '–' }}
|
||||||
</mat-basic-chip>
|
</mat-basic-chip>
|
||||||
</div>
|
</div>
|
||||||
@ -380,7 +394,7 @@
|
|||||||
|
|
||||||
<!-- Submitter -->
|
<!-- Submitter -->
|
||||||
<div *ngIf="newMotion" class="content-field">
|
<div *ngIf="newMotion" class="content-field">
|
||||||
<div *osPerms="['motions.can_manage', 'motions.can_manage_metadata']">
|
<div *ngIf="perms.isAllowed('change_metadata', motion)">
|
||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="contentForm"
|
[form]="contentForm"
|
||||||
@ -537,7 +551,7 @@
|
|||||||
|
|
||||||
<!-- Supporter form -->
|
<!-- Supporter form -->
|
||||||
<div class="content-field" *ngIf="editMotion && minSupporters">
|
<div class="content-field" *ngIf="editMotion && minSupporters">
|
||||||
<div *osPerms="['motions.can_manage', 'motions.can_manage_metadata']">
|
<div *ngIf="perms.isAllowed('change_metadata', motion)">
|
||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="contentForm"
|
[form]="contentForm"
|
||||||
@ -551,7 +565,7 @@
|
|||||||
|
|
||||||
<!-- Workflow -->
|
<!-- Workflow -->
|
||||||
<div class="content-field" *ngIf="editMotion && workflowObserver.value.length > 1">
|
<div class="content-field" *ngIf="editMotion && workflowObserver.value.length > 1">
|
||||||
<div *osPerms="['motions.can_manage', 'motions.can_manage_metadata']">
|
<div *ngIf="perms.isAllowed('change_metadata', motion)">
|
||||||
<os-search-value-selector
|
<os-search-value-selector
|
||||||
ngDefaultControl
|
ngDefaultControl
|
||||||
[form]="contentForm"
|
[form]="contentForm"
|
||||||
@ -565,7 +579,7 @@
|
|||||||
|
|
||||||
<!-- Origin form -->
|
<!-- Origin form -->
|
||||||
<div class="content-field" *ngIf="editMotion">
|
<div class="content-field" *ngIf="editMotion">
|
||||||
<div *osPerms="['motions.can_manage', 'motions.can_manage_metadata']">
|
<div *ngIf="perms.isAllowed('change_metadata', motion)">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<input
|
<input
|
||||||
matInput
|
matInput
|
||||||
|
@ -1,45 +1,43 @@
|
|||||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
import { BehaviorSubject, Subscription, ReplaySubject, concat } from 'rxjs';
|
||||||
|
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||||
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
|
import { DomSanitizer, SafeHtml, Title } from '@angular/platform-browser';
|
||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
import { MatDialog, MatExpansionPanel, MatSnackBar, MatCheckboxChange } from '@angular/material';
|
import { MatDialog, MatExpansionPanel, MatSnackBar, MatCheckboxChange } from '@angular/material';
|
||||||
import { take, takeWhile, multicast, skipWhile } from 'rxjs/operators';
|
import { take, takeWhile, multicast, skipWhile } from 'rxjs/operators';
|
||||||
|
|
||||||
import { Category } from '../../../../shared/models/motions/category';
|
|
||||||
import { ViewportService } from '../../../../core/services/viewport.service';
|
|
||||||
import { MotionRepositoryService } from '../../services/motion-repository.service';
|
|
||||||
import { ChangeRecoMode, LineNumberingMode, ViewMotion } from '../../models/view-motion';
|
|
||||||
import { User } from '../../../../shared/models/users/user';
|
|
||||||
import { DataStoreService } from '../../../../core/services/data-store.service';
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { Motion } from '../../../../shared/models/motions/motion';
|
|
||||||
import { BehaviorSubject, Subscription, ReplaySubject, concat } from 'rxjs';
|
import { AgendaRepositoryService } from 'app/site/agenda/services/agenda-repository.service';
|
||||||
|
import { BaseViewComponent } from '../../../base/base-view';
|
||||||
|
import { Category } from '../../../../shared/models/motions/category';
|
||||||
|
import { ChangeRecommendationRepositoryService } from '../../services/change-recommendation-repository.service';
|
||||||
|
import { ChangeRecoMode, LineNumberingMode, ViewMotion } from '../../models/view-motion';
|
||||||
|
import { CreateMotion } from '../../models/create-motion';
|
||||||
|
import { ConfigService } from '../../../../core/services/config.service';
|
||||||
|
import { DataStoreService } from '../../../../core/services/data-store.service';
|
||||||
import { DiffLinesInParagraph, LineRange } from '../../services/diff.service';
|
import { DiffLinesInParagraph, LineRange } from '../../services/diff.service';
|
||||||
|
import { itemVisibilityChoices, Item } from 'app/shared/models/agenda/item';
|
||||||
|
import { LocalPermissionsService } from '../../services/local-permissions.service';
|
||||||
|
import { Mediafile } from 'app/shared/models/mediafiles/mediafile';
|
||||||
|
import { Motion } from '../../../../shared/models/motions/motion';
|
||||||
|
import { MotionBlock } from 'app/shared/models/motions/motion-block';
|
||||||
import {
|
import {
|
||||||
MotionChangeRecommendationComponent,
|
MotionChangeRecommendationComponent,
|
||||||
MotionChangeRecommendationComponentData
|
MotionChangeRecommendationComponentData
|
||||||
} from '../motion-change-recommendation/motion-change-recommendation.component';
|
} from '../motion-change-recommendation/motion-change-recommendation.component';
|
||||||
import { ChangeRecommendationRepositoryService } from '../../services/change-recommendation-repository.service';
|
|
||||||
import { ViewChangeReco } from '../../models/view-change-reco';
|
|
||||||
|
|
||||||
import { ViewUnifiedChange } from '../../models/view-unified-change';
|
|
||||||
import { OperatorService } from '../../../../core/services/operator.service';
|
|
||||||
import { BaseViewComponent } from '../../../base/base-view';
|
|
||||||
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 { 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';
|
|
||||||
import { MotionPdfExportService } from '../../services/motion-pdf-export.service';
|
import { MotionPdfExportService } from '../../services/motion-pdf-export.service';
|
||||||
import { PersonalNoteService } from '../../services/personal-note.service';
|
import { MotionRepositoryService } from '../../services/motion-repository.service';
|
||||||
import { PersonalNoteContent } from 'app/shared/models/users/personal-note';
|
import { PersonalNoteContent } from 'app/shared/models/users/personal-note';
|
||||||
|
import { PersonalNoteService } from '../../services/personal-note.service';
|
||||||
|
import { PromptService } from 'app/core/services/prompt.service';
|
||||||
|
import { StatuteParagraphRepositoryService } from '../../services/statute-paragraph-repository.service';
|
||||||
|
import { User } from '../../../../shared/models/users/user';
|
||||||
|
import { ViewChangeReco } from '../../models/view-change-reco';
|
||||||
|
import { ViewCreateMotion } from '../../models/view-create-motion';
|
||||||
|
import { ViewportService } from '../../../../core/services/viewport.service';
|
||||||
|
import { ViewUnifiedChange } from '../../models/view-unified-change';
|
||||||
|
import { ViewStatuteParagraph } from '../../models/view-statute-paragraph';
|
||||||
|
import { Workflow } from 'app/shared/models/motions/workflow';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component for the motion detail view
|
* Component for the motion detail view
|
||||||
@ -107,6 +105,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
if (
|
if (
|
||||||
this.motion &&
|
this.motion &&
|
||||||
!this.editMotion &&
|
!this.editMotion &&
|
||||||
|
this.perms.isAllowed('manage') &&
|
||||||
this.motion.motion.log_messages &&
|
this.motion.motion.log_messages &&
|
||||||
this.motion.motion.log_messages.length
|
this.motion.motion.log_messages.length
|
||||||
) {
|
) {
|
||||||
@ -316,7 +315,6 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
matSnackBar: MatSnackBar,
|
matSnackBar: MatSnackBar,
|
||||||
public vp: ViewportService,
|
public vp: ViewportService,
|
||||||
public perms: LocalPermissionsService,
|
public perms: LocalPermissionsService,
|
||||||
private op: OperatorService,
|
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
@ -984,15 +982,8 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the user has the correct requirements to alter the motion
|
* Handler for creating a poll
|
||||||
* 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');
|
|
||||||
}
|
|
||||||
|
|
||||||
public async createPoll(): Promise<void> {
|
public async createPoll(): Promise<void> {
|
||||||
await this.repo.createPoll(this.motion);
|
await this.repo.createPoll(this.motion);
|
||||||
}
|
}
|
||||||
@ -1000,7 +991,7 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
/**
|
/**
|
||||||
* Check if a recommendation can be followed. Checks for permissions and additionally if a recommentadion is present
|
* Check if a recommendation can be followed. Checks for permissions and additionally if a recommentadion is present
|
||||||
*/
|
*/
|
||||||
public get canFollowRecommendation(): boolean {
|
public canFollowRecommendation(): boolean {
|
||||||
if (
|
if (
|
||||||
this.perms.isAllowed('createPoll', this.motion) &&
|
this.perms.isAllowed('createPoll', this.motion) &&
|
||||||
this.motion.recommendation &&
|
this.motion.recommendation &&
|
||||||
@ -1024,4 +1015,24 @@ export class MotionDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
public async toggleFavorite(): Promise<void> {
|
public async toggleFavorite(): Promise<void> {
|
||||||
this.personalNoteService.setPersonalNoteStar(this.motion.motion, !this.motion.star);
|
this.personalNoteService.setPersonalNoteStar(this.motion.motion, !this.motion.star);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate the state's css class into a color
|
||||||
|
*
|
||||||
|
* @returns a string representing a color
|
||||||
|
*/
|
||||||
|
public getStateCssColor(): string {
|
||||||
|
switch (this.motion.state.css_class) {
|
||||||
|
case 'success':
|
||||||
|
return 'green';
|
||||||
|
case 'danger':
|
||||||
|
return 'red';
|
||||||
|
case 'default':
|
||||||
|
return 'grey';
|
||||||
|
case 'primary':
|
||||||
|
return 'lightblue';
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<os-head-bar [mainButton]="true" (mainEvent)="onPlusButton()" [multiSelectMode]="isMultiSelect">
|
<os-head-bar [mainButton]="perms.isAllowed('create')" (mainEvent)="onPlusButton()" [multiSelectMode]="isMultiSelect">
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<div class="title-slot"><h2 translate>Motions</h2></div>
|
<div class="title-slot"><h2 translate>Motions</h2></div>
|
||||||
|
|
||||||
@ -126,14 +126,18 @@
|
|||||||
</mat-table>
|
</mat-table>
|
||||||
|
|
||||||
<mat-paginator class="on-transition-fade" [pageSizeOptions]="[25, 50, 75, 100, 125]"></mat-paginator>
|
<mat-paginator class="on-transition-fade" [pageSizeOptions]="[25, 50, 75, 100, 125]"></mat-paginator>
|
||||||
|
</mat-drawer-container>
|
||||||
|
|
||||||
<mat-menu #motionListMenu="matMenu">
|
<mat-menu #motionListMenu="matMenu">
|
||||||
<div *ngIf="!isMultiSelect">
|
<div *ngIf="!isMultiSelect">
|
||||||
<button mat-menu-item *osPerms="'motions.can_manage'" (click)="toggleMultiSelect()">
|
<div *ngIf="perms.isAllowed('change_metadata')">
|
||||||
|
<button mat-menu-item (click)="toggleMultiSelect()">
|
||||||
<mat-icon>library_add</mat-icon>
|
<mat-icon>library_add</mat-icon>
|
||||||
<span translate>Multiselect</span>
|
<span translate>Multiselect</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item *osPerms="'motions.can_manage'" routerLink="call-list">
|
</div>
|
||||||
|
<div *ngIf="perms.isAllowed('manage')">
|
||||||
|
<button mat-menu-item routerLink="call-list">
|
||||||
<mat-icon>sort</mat-icon>
|
<mat-icon>sort</mat-icon>
|
||||||
<span translate>Call list</span>
|
<span translate>Call list</span>
|
||||||
</button>
|
</button>
|
||||||
@ -161,11 +165,12 @@
|
|||||||
<mat-icon>archive</mat-icon>
|
<mat-icon>archive</mat-icon>
|
||||||
<span translate>Export as CSV</span>
|
<span translate>Export as CSV</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item *osPerms="'motions.can_manage'" routerLink="import">
|
<button mat-menu-item routerLink="import">
|
||||||
<mat-icon>save_alt</mat-icon>
|
<mat-icon>save_alt</mat-icon>
|
||||||
<span translate>Import</span><span> ...</span>
|
<span translate>Import</span><span> ...</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div *ngIf="isMultiSelect">
|
<div *ngIf="isMultiSelect">
|
||||||
<button mat-menu-item (click)="selectAll()">
|
<button mat-menu-item (click)="selectAll()">
|
||||||
<mat-icon>done_all</mat-icon>
|
<mat-icon>done_all</mat-icon>
|
||||||
@ -175,7 +180,7 @@
|
|||||||
<mat-icon>clear</mat-icon>
|
<mat-icon>clear</mat-icon>
|
||||||
<span translate>Deselect all</span>
|
<span translate>Deselect all</span>
|
||||||
</button>
|
</button>
|
||||||
<div *osPerms="'motions.can_manage'">
|
<div *ngIf="perms.isAllowed('change_metadata')">
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<button mat-menu-item (click)="multiselectWrapper(multiselectService.setStateOfMultiple(selectedRows))">
|
<button mat-menu-item (click)="multiselectWrapper(multiselectService.setStateOfMultiple(selectedRows))">
|
||||||
<mat-icon>label</mat-icon>
|
<mat-icon>label</mat-icon>
|
||||||
@ -217,6 +222,7 @@
|
|||||||
<span translate>Move to agenda item</span>
|
<span translate>Move to agenda item</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngIf="perms.isAllowed('manage')">
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<button
|
<button
|
||||||
mat-menu-item
|
mat-menu-item
|
||||||
@ -227,5 +233,6 @@
|
|||||||
<span translate>Delete</span>
|
<span translate>Delete</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</mat-drawer-container>
|
|
||||||
|
@ -3,22 +3,23 @@ import { Router, ActivatedRoute } from '@angular/router';
|
|||||||
import { Title } from '@angular/platform-browser';
|
import { Title } from '@angular/platform-browser';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { ConfigService } from '../../../../core/services/config.service';
|
|
||||||
import { MotionCsvExportService } from '../../services/motion-csv-export.service';
|
|
||||||
import { ListViewBaseComponent } from '../../../base/list-view-base';
|
|
||||||
import { MatSnackBar } from '@angular/material';
|
|
||||||
import { ViewMotion } from '../../models/view-motion';
|
|
||||||
import { WorkflowState } from '../../../../shared/models/motions/workflow-state';
|
|
||||||
import { MotionMultiselectService } from '../../services/motion-multiselect.service';
|
|
||||||
import { TagRepositoryService } from 'app/site/tags/services/tag-repository.service';
|
|
||||||
import { CategoryRepositoryService } from '../../services/category-repository.service';
|
import { CategoryRepositoryService } from '../../services/category-repository.service';
|
||||||
|
import { ConfigService } from '../../../../core/services/config.service';
|
||||||
|
import { ListViewBaseComponent } from '../../../base/list-view-base';
|
||||||
|
import { LocalPermissionsService } from '../../services/local-permissions.service';
|
||||||
|
import { MatSnackBar } from '@angular/material';
|
||||||
import { MotionBlockRepositoryService } from '../../services/motion-block-repository.service';
|
import { MotionBlockRepositoryService } from '../../services/motion-block-repository.service';
|
||||||
|
import { MotionCsvExportService } from '../../services/motion-csv-export.service';
|
||||||
import { MotionFilterListService } from '../../services/motion-filter-list.service';
|
import { MotionFilterListService } from '../../services/motion-filter-list.service';
|
||||||
|
import { MotionMultiselectService } from '../../services/motion-multiselect.service';
|
||||||
import { MotionSortListService } from '../../services/motion-sort-list.service';
|
import { MotionSortListService } from '../../services/motion-sort-list.service';
|
||||||
|
import { TagRepositoryService } from 'app/site/tags/services/tag-repository.service';
|
||||||
|
import { ViewCategory } from '../../models/view-category';
|
||||||
|
import { ViewMotion } from '../../models/view-motion';
|
||||||
|
import { ViewMotionBlock } from '../../models/view-motion-block';
|
||||||
import { ViewTag } from 'app/site/tags/models/view-tag';
|
import { ViewTag } from 'app/site/tags/models/view-tag';
|
||||||
import { ViewWorkflow } from '../../models/view-workflow';
|
import { ViewWorkflow } from '../../models/view-workflow';
|
||||||
import { ViewCategory } from '../../models/view-category';
|
import { WorkflowState } from '../../../../shared/models/motions/workflow-state';
|
||||||
import { ViewMotionBlock } from '../../models/view-motion-block';
|
|
||||||
import { WorkflowRepositoryService } from '../../services/workflow-repository.service';
|
import { WorkflowRepositoryService } from '../../services/workflow-repository.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,6 +76,7 @@ export class MotionListComponent extends ListViewBaseComponent<ViewMotion> imple
|
|||||||
* @param userRepo
|
* @param userRepo
|
||||||
* @param sortService
|
* @param sortService
|
||||||
* @param filterService
|
* @param filterService
|
||||||
|
* @param perms LocalPermissionService
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
titleService: Title,
|
titleService: Title,
|
||||||
@ -90,7 +92,8 @@ export class MotionListComponent extends ListViewBaseComponent<ViewMotion> imple
|
|||||||
private motionCsvExport: MotionCsvExportService,
|
private motionCsvExport: MotionCsvExportService,
|
||||||
public multiselectService: MotionMultiselectService,
|
public multiselectService: MotionMultiselectService,
|
||||||
public sortService: MotionSortListService,
|
public sortService: MotionSortListService,
|
||||||
public filterService: MotionFilterListService
|
public filterService: MotionFilterListService,
|
||||||
|
public perms: LocalPermissionsService
|
||||||
) {
|
) {
|
||||||
super(titleService, translate, matSnackBar);
|
super(titleService, translate, matSnackBar);
|
||||||
|
|
||||||
|
@ -6,10 +6,13 @@
|
|||||||
<div *ngIf="poll.has_votes" class="on-transition-fade poll-result">
|
<div *ngIf="poll.has_votes" class="on-transition-fade poll-result">
|
||||||
<div *ngFor="let key of pollValues">
|
<div *ngFor="let key of pollValues">
|
||||||
<div class="poll-progress on-transition-fade" *ngIf="poll[key] !== undefined">
|
<div class="poll-progress on-transition-fade" *ngIf="poll[key] !== undefined">
|
||||||
<mat-icon class="main-nav-color" matTooltip="{{ getLabel(key) | translate }}"> {{ getIcon(key) }} </mat-icon>
|
<mat-icon class="main-nav-color" matTooltip="{{ getLabel(key) | translate }}">
|
||||||
|
{{ getIcon(key) }}
|
||||||
|
</mat-icon>
|
||||||
<div class="progress-container">
|
<div class="progress-container">
|
||||||
<div>
|
<div>
|
||||||
<span translate>{{ getLabel(key) }}</span>: {{ getNumber(key) }}
|
<span translate>{{ getLabel(key) }}</span
|
||||||
|
>: {{ getNumber(key) }}
|
||||||
<span *ngIf="!isAbstractValue(key)">({{ getPercent(key) }}%)</span>
|
<span *ngIf="!isAbstractValue(key)">({{ getPercent(key) }}%)</span>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="!isAbstractValue(key)" class="poll-progress-bar">
|
<div *ngIf="!isAbstractValue(key)" class="poll-progress-bar">
|
||||||
@ -25,6 +28,7 @@
|
|||||||
<hr *ngIf="key === 'abstain'" flex />
|
<hr *ngIf="key === 'abstain'" flex />
|
||||||
</div>
|
</div>
|
||||||
<!-- quorum -->
|
<!-- quorum -->
|
||||||
|
<div *osPerms="'motions.can_manage'">
|
||||||
<div *ngIf="abstractPoll"><span translate>Quorum not calculable.</span></div>
|
<div *ngIf="abstractPoll"><span translate>Quorum not calculable.</span></div>
|
||||||
<div class="poll-quorum-line" *ngIf="!abstractPoll">
|
<div class="poll-quorum-line" *ngIf="!abstractPoll">
|
||||||
<span>
|
<span>
|
||||||
@ -33,8 +37,10 @@
|
|||||||
<mat-icon color="primary" *ngIf="quorumYesReached"> thumb_up </mat-icon>
|
<mat-icon color="primary" *ngIf="quorumYesReached"> thumb_up </mat-icon>
|
||||||
</span>
|
</span>
|
||||||
<button mat-button [matMenuTriggerFor]="majorityMenu">
|
<button mat-button [matMenuTriggerFor]="majorityMenu">
|
||||||
<span translate>{{ getQuorumLabel() }}</span>
|
<span translate>{{ getQuorumLabel() }}</span> <span
|
||||||
<span *ngIf="majorityChoice !== 'disabled'">({{ yesQuorum }})</span>
|
*ngIf="majorityChoice !== 'disabled'"
|
||||||
|
>({{ yesQuorum }})</span
|
||||||
|
>
|
||||||
</button>
|
</button>
|
||||||
<span *ngIf="majorityChoice !== 'disabled'">
|
<span *ngIf="majorityChoice !== 'disabled'">
|
||||||
<span *ngIf="quorumYesReached" translate> reached.</span>
|
<span *ngIf="quorumYesReached" translate> reached.</span>
|
||||||
@ -46,15 +52,26 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container class="meta-text-block-action-row" *osPerms="'motions.can_manage'">
|
<ng-container class="meta-text-block-action-row" *osPerms="'motions.can_manage_metadata'">
|
||||||
<button mat-icon-button class="main-nav-color" matTooltip="{{ 'Edit poll' | translate }}" (click)="editPoll()">
|
<button mat-icon-button class="main-nav-color" matTooltip="{{ 'Edit poll' | translate }}" (click)="editPoll()">
|
||||||
<mat-icon inline>edit</mat-icon>
|
<mat-icon inline>edit</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button mat-icon-button class="main-nav-color" matTooltip="{{ 'Print ballots' | translate }}" (click)="printBallots()">
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
class="main-nav-color"
|
||||||
|
matTooltip="{{ 'Print ballots' | translate }}"
|
||||||
|
(click)="printBallots()"
|
||||||
|
>
|
||||||
<mat-icon inline>local_printshop</mat-icon>
|
<mat-icon inline>local_printshop</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button mat-icon-button class="main-nav-color" matTooltip="{{ 'Delete poll' | translate }}" (click)="deletePoll()">
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
class="main-nav-color"
|
||||||
|
matTooltip="{{ 'Delete poll' | translate }}"
|
||||||
|
(click)="deletePoll()"
|
||||||
|
>
|
||||||
<mat-icon inline>delete</mat-icon>
|
<mat-icon inline>delete</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@ -2,35 +2,60 @@ import { Injectable } from '@angular/core';
|
|||||||
import { OperatorService } from '../../../core/services/operator.service';
|
import { OperatorService } from '../../../core/services/operator.service';
|
||||||
import { ViewMotion } from '../models/view-motion';
|
import { ViewMotion } from '../models/view-motion';
|
||||||
import { ConfigService } from '../../../core/services/config.service';
|
import { ConfigService } from '../../../core/services/config.service';
|
||||||
|
import { ConstantsService } from 'app/core/services/constants.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class LocalPermissionsService {
|
export class LocalPermissionsService {
|
||||||
public configMinSupporters: number;
|
public configMinSupporters: number;
|
||||||
|
private amendmentEnabled: boolean;
|
||||||
|
private amendmentOfAmendment: boolean;
|
||||||
|
|
||||||
public constructor(private operator: OperatorService, private configService: ConfigService) {
|
public constructor(
|
||||||
|
private operator: OperatorService,
|
||||||
|
private configService: ConfigService,
|
||||||
|
private constants: ConstantsService
|
||||||
|
) {
|
||||||
// load config variables
|
// load config variables
|
||||||
this.configService
|
this.configService
|
||||||
.get('motions_min_supporters')
|
.get('motions_min_supporters')
|
||||||
.subscribe(supporters => (this.configMinSupporters = supporters));
|
.subscribe(supporters => (this.configMinSupporters = supporters));
|
||||||
|
this.configService.get('motions_amendments_enabled').subscribe(enabled => (this.amendmentEnabled = enabled));
|
||||||
|
this.constants
|
||||||
|
.get('OpenSlidesSettings')
|
||||||
|
.subscribe(settings => (this.amendmentOfAmendment = settings.MOTIONS_ALLOW_AMENDMENTS_OF_AMENDMENTS));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Should determine if the user (Operator) has the
|
* Determine if the user (Operator) has the correct permission to perform the given action.
|
||||||
* correct permission to perform the given action.
|
|
||||||
*
|
*
|
||||||
* actions might be:
|
* actions might be:
|
||||||
|
* - create
|
||||||
* - support
|
* - support
|
||||||
* - unsupport
|
* - unsupport
|
||||||
* - createpoll
|
* - createpoll
|
||||||
|
* - update
|
||||||
|
* - update_submitters
|
||||||
|
* - delete
|
||||||
|
* - change_metadata
|
||||||
|
* - reset_state
|
||||||
|
* - change_recommendation
|
||||||
|
* - can_create_amendments
|
||||||
|
* - can_manage_metadata
|
||||||
|
* - manage
|
||||||
*
|
*
|
||||||
* @param action the action the user tries to perform
|
* @param action the action the user tries to perform
|
||||||
|
* @param motion the motion for which to perform the action
|
||||||
*/
|
*/
|
||||||
public isAllowed(action: string, motion?: ViewMotion): boolean {
|
public isAllowed(action: string, motion?: ViewMotion): boolean {
|
||||||
if (motion) {
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
case 'create':
|
||||||
|
return this.operator.hasPerms('motions.can_create');
|
||||||
case 'support':
|
case 'support':
|
||||||
|
if (!motion) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
this.operator.hasPerms('motions.can_support') &&
|
this.operator.hasPerms('motions.can_support') &&
|
||||||
this.configMinSupporters > 0 &&
|
this.configMinSupporters > 0 &&
|
||||||
@ -39,12 +64,62 @@ export class LocalPermissionsService {
|
|||||||
motion.supporters.indexOf(this.operator.user) === -1
|
motion.supporters.indexOf(this.operator.user) === -1
|
||||||
);
|
);
|
||||||
case 'unsupport':
|
case 'unsupport':
|
||||||
|
if (!motion) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return motion.state.allow_support && motion.supporters.indexOf(this.operator.user) !== -1;
|
return motion.state.allow_support && motion.supporters.indexOf(this.operator.user) !== -1;
|
||||||
case 'createpoll':
|
case 'createpoll':
|
||||||
return this.operator.hasPerms('motions.can_manage') && motion.state.allow_create_poll;
|
if (!motion) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
(this.operator.hasPerms('motions.can_manage') ||
|
||||||
|
this.operator.hasPerms('motions.can_manage_metadata')) &&
|
||||||
|
motion.state.allow_create_poll
|
||||||
|
);
|
||||||
|
case 'update':
|
||||||
|
if (!motion) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
this.operator.hasPerms('motions.can_manage') &&
|
||||||
|
motion.state.allow_submitter_edit &&
|
||||||
|
motion.submitters.some(submitter => submitter.id === this.operator.user.id)
|
||||||
|
);
|
||||||
|
case 'update_submitters':
|
||||||
|
return this.operator.hasPerms('motions.can_manage');
|
||||||
|
case 'delete':
|
||||||
|
if (!motion) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
this.operator.hasPerms('motions.can_manage') &&
|
||||||
|
motion.state.allow_submitter_edit &&
|
||||||
|
motion.submitters.some(submitter => submitter.id === this.operator.user.id)
|
||||||
|
);
|
||||||
|
case 'change_metadata':
|
||||||
|
return (
|
||||||
|
this.operator.hasPerms('motions.can_manage') ||
|
||||||
|
this.operator.hasPerms('motions.can_manage_metadata')
|
||||||
|
);
|
||||||
|
case 'can_create_amendments':
|
||||||
|
if (!motion) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
this.operator.hasPerms('motions.can_create_amendments') &&
|
||||||
|
this.amendmentEnabled &&
|
||||||
|
(!motion.parent_id || (motion.parent_id && this.amendmentOfAmendment))
|
||||||
|
);
|
||||||
|
case 'can_manage_metadata':
|
||||||
|
return (
|
||||||
|
this.operator.hasPerms('motions.can_manage') &&
|
||||||
|
this.operator.hasPerms('motions.can_manage_metadata')
|
||||||
|
);
|
||||||
|
case 'manage':
|
||||||
|
return this.operator.hasPerms('motions.can_manage');
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -692,4 +692,13 @@ export class MotionRepositoryService extends BaseRepository<ViewMotion, Motion>
|
|||||||
await this.httpService.post(restPath);
|
await this.httpService.post(restPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Check if a motion currently has any amendments
|
||||||
|
*
|
||||||
|
* @param motion A viewMotion
|
||||||
|
* @returns True if there is at eleast one amendment
|
||||||
|
*/
|
||||||
|
public hasAmendments(motion: ViewMotion): boolean {
|
||||||
|
return this.getViewModelList().filter(allMotions => allMotions.parent_id === motion.id).length > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user