Merge pull request #4322 from MaximilianKrambach/motionDelegates
direct pdf export and hidden menus for unprivileged users
This commit is contained in:
commit
c5912f8515
@ -1,4 +1,4 @@
|
|||||||
<os-head-bar [mainButton]="true" (mainEvent)="onPlusButton()" [multiSelectMode]="isMultiSelect">
|
<os-head-bar [mainButton]="canManage" (mainEvent)="onPlusButton()" [multiSelectMode]="isMultiSelect">
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<div class="title-slot"><h2 translate>Agenda</h2></div>
|
<div class="title-slot"><h2 translate>Agenda</h2></div>
|
||||||
<!-- Menu -->
|
<!-- Menu -->
|
||||||
@ -80,7 +80,9 @@
|
|||||||
<ng-container matColumnDef="menu">
|
<ng-container matColumnDef="menu">
|
||||||
<mat-header-cell *matHeaderCellDef mat-sort-header>Menu</mat-header-cell>
|
<mat-header-cell *matHeaderCellDef mat-sort-header>Menu</mat-header-cell>
|
||||||
<mat-cell *matCellDef="let item">
|
<mat-cell *matCellDef="let item">
|
||||||
<button mat-icon-button [matMenuTriggerFor]="singleItemMenu" [matMenuTriggerData]="{ item: item }">
|
<button mat-icon-button
|
||||||
|
*osPerms="'agenda.can_manage'"
|
||||||
|
[matMenuTriggerFor]="singleItemMenu" [matMenuTriggerData]="{ item: item }">
|
||||||
<mat-icon>more_vert</mat-icon>
|
<mat-icon>more_vert</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</mat-cell>
|
</mat-cell>
|
||||||
@ -121,7 +123,7 @@
|
|||||||
<span translate>Current list of speakers</span>
|
<span translate>Current list of speakers</span>
|
||||||
</button>
|
</button>
|
||||||
<!-- CSV export -->
|
<!-- CSV export -->
|
||||||
<button mat-menu-item (click)="csvExportItemList()">
|
<button mat-menu-item *osPerms="'agenda.can_manage'" (click)="csvExportItemList()">
|
||||||
<mat-icon>archive</mat-icon>
|
<mat-icon>archive</mat-icon>
|
||||||
<span translate>Export as CSV</span>
|
<span translate>Export as CSV</span>
|
||||||
</button>
|
</button>
|
||||||
@ -201,17 +203,6 @@
|
|||||||
<span translate>Done</span>
|
<span translate>Done</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- List of speakers for mobile -->
|
|
||||||
<button mat-menu-item (click)="onSpeakerIcon(item)" *ngIf="vp.isMobile">
|
|
||||||
<mat-icon
|
|
||||||
[matBadge]="item.waitingSpeakerAmount > 0 ? item.waitingSpeakerAmount : null"
|
|
||||||
matBadgeColor="accent"
|
|
||||||
>
|
|
||||||
mic
|
|
||||||
</mat-icon>
|
|
||||||
<span translate>List of speakers</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Edit button -->
|
<!-- Edit button -->
|
||||||
<button mat-menu-item (click)="openEditInfo(item)">
|
<button mat-menu-item (click)="openEditInfo(item)">
|
||||||
<mat-icon>edit</mat-icon>
|
<mat-icon>edit</mat-icon>
|
||||||
|
@ -17,6 +17,7 @@ import { DurationService } from 'app/core/ui-services/duration.service';
|
|||||||
import { ItemInfoDialogComponent } from '../item-info-dialog/item-info-dialog.component';
|
import { ItemInfoDialogComponent } from '../item-info-dialog/item-info-dialog.component';
|
||||||
import { PdfDocumentService } from 'app/core/ui-services/pdf-document.service';
|
import { PdfDocumentService } from 'app/core/ui-services/pdf-document.service';
|
||||||
import { ViewportService } from 'app/core/ui-services/viewport.service';
|
import { ViewportService } from 'app/core/ui-services/viewport.service';
|
||||||
|
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List view for the agenda.
|
* List view for the agenda.
|
||||||
@ -35,10 +36,19 @@ export class AgendaListComponent extends ListViewBaseComponent<ViewItem> impleme
|
|||||||
/**
|
/**
|
||||||
* Determine the display columns in mobile view
|
* Determine the display columns in mobile view
|
||||||
*/
|
*/
|
||||||
public displayedColumnsMobile: string[] = ['title', 'menu'];
|
public displayedColumnsMobile: string[] = ['title', 'speakers', 'menu'];
|
||||||
|
|
||||||
public isNumberingAllowed: boolean;
|
public isNumberingAllowed: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to check main button permissions
|
||||||
|
*
|
||||||
|
* @returns true if the operator can manage agenda items
|
||||||
|
*/
|
||||||
|
public get canManage(): boolean {
|
||||||
|
return this.operator.hasPerms('agenda.can_manage');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The usual constructor for components
|
* The usual constructor for components
|
||||||
* @param titleService Setting the browser tab title
|
* @param titleService Setting the browser tab title
|
||||||
@ -56,6 +66,7 @@ export class AgendaListComponent extends ListViewBaseComponent<ViewItem> impleme
|
|||||||
* @param filterService: service for filtering data
|
* @param filterService: service for filtering data
|
||||||
* @param agendaPdfService: service for preparing a pdf of the agenda
|
* @param agendaPdfService: service for preparing a pdf of the agenda
|
||||||
* @param pdfService: Service for exporting a pdf
|
* @param pdfService: Service for exporting a pdf
|
||||||
|
* @param operator the current user
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
titleService: Title,
|
titleService: Title,
|
||||||
@ -72,7 +83,8 @@ export class AgendaListComponent extends ListViewBaseComponent<ViewItem> impleme
|
|||||||
private csvExport: AgendaCsvExportService,
|
private csvExport: AgendaCsvExportService,
|
||||||
public filterService: AgendaFilterListService,
|
public filterService: AgendaFilterListService,
|
||||||
private agendaPdfService: AgendaPdfService,
|
private agendaPdfService: AgendaPdfService,
|
||||||
private pdfService: PdfDocumentService
|
private pdfService: PdfDocumentService,
|
||||||
|
private operator: OperatorService
|
||||||
) {
|
) {
|
||||||
super(titleService, translate, matSnackBar);
|
super(titleService, translate, matSnackBar);
|
||||||
|
|
||||||
@ -116,6 +128,9 @@ export class AgendaListComponent extends ListViewBaseComponent<ViewItem> impleme
|
|||||||
* @param item The view item that was clicked
|
* @param item The view item that was clicked
|
||||||
*/
|
*/
|
||||||
public openEditInfo(item: ViewItem): void {
|
public openEditInfo(item: ViewItem): void {
|
||||||
|
if (!this.canManage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const dialogRef = this.dialog.open(ItemInfoDialogComponent, {
|
const dialogRef = this.dialog.open(ItemInfoDialogComponent, {
|
||||||
width: '400px',
|
width: '400px',
|
||||||
data: item,
|
data: item,
|
||||||
|
@ -30,8 +30,14 @@
|
|||||||
</os-head-bar>
|
</os-head-bar>
|
||||||
|
|
||||||
<mat-card>
|
<mat-card>
|
||||||
<button mat-raised-button color="primary" (click)="onFollowRecButton()" [disabled]="isFollowingProhibited()">
|
<button
|
||||||
<mat-icon>done_all</mat-icon>
|
*osPerms="['motions.can_manage', 'motions.can_manage_metadata']"
|
||||||
|
mat-raised-button
|
||||||
|
color="primary"
|
||||||
|
(click)="onFollowRecButton()"
|
||||||
|
[disabled]="isFollowingProhibited()"
|
||||||
|
>
|
||||||
|
<mat-icon>done_all</mat-icon>
|
||||||
<span translate>Follow recommendations for all motions</span>
|
<span translate>Follow recommendations for all motions</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@ -98,20 +104,20 @@
|
|||||||
<span translate>List of speakers</span>
|
<span translate>List of speakers</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button mat-menu-item>
|
<button mat-menu-item *osPerms="'core.can_manage_projector'">
|
||||||
<mat-icon>videocam</mat-icon>
|
<mat-icon>videocam</mat-icon>
|
||||||
<span translate>Project</span>
|
<span translate>Project</span>
|
||||||
</button>
|
</button>
|
||||||
|
<div *osPerms="['motions.can_manage', 'motions.can_manage_metadata']">
|
||||||
|
<button mat-menu-item (click)="toggleEditMode()">
|
||||||
|
<mat-icon>edit</mat-icon>
|
||||||
|
<span translate>Edit title</span>
|
||||||
|
</button>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<button mat-menu-item class="red-warning-text" (click)="onDeleteBlockButton()">
|
||||||
|
<mat-icon>delete</mat-icon>
|
||||||
<button mat-menu-item (click)="toggleEditMode()">
|
<span translate>Delete</span>
|
||||||
<mat-icon>edit</mat-icon>
|
</button>
|
||||||
<span translate>Edit title</span>
|
</div>
|
||||||
</button>
|
|
||||||
|
|
||||||
<button mat-menu-item class="red-warning-text" (click)="onDeleteBlockButton()">
|
|
||||||
<mat-icon>delete</mat-icon>
|
|
||||||
<span translate>Delete</span>
|
|
||||||
</button>
|
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
@ -13,6 +13,7 @@ import { MotionRepositoryService } from 'app/core/repositories/motions/motion-re
|
|||||||
import { ViewMotionBlock } from '../../models/view-motion-block';
|
import { ViewMotionBlock } from '../../models/view-motion-block';
|
||||||
import { PromptService } from 'app/core/ui-services/prompt.service';
|
import { PromptService } from 'app/core/ui-services/prompt.service';
|
||||||
import { ViewMotion } from '../../models/view-motion';
|
import { ViewMotion } from '../../models/view-motion';
|
||||||
|
import { OperatorService } from '../../../../core/core-services/operator.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detail component to display one motion block
|
* Detail component to display one motion block
|
||||||
@ -50,6 +51,7 @@ export class MotionBlockDetailComponent extends ListViewBaseComponent<ViewMotion
|
|||||||
* @param titleService Setting the title
|
* @param titleService Setting the title
|
||||||
* @param translate translations
|
* @param translate translations
|
||||||
* @param matSnackBar showing errors
|
* @param matSnackBar showing errors
|
||||||
|
* @param operator the current user
|
||||||
* @param router navigating
|
* @param router navigating
|
||||||
* @param route determine the blocks ID by the route
|
* @param route determine the blocks ID by the route
|
||||||
* @param repo the motion blocks repository
|
* @param repo the motion blocks repository
|
||||||
@ -60,6 +62,7 @@ export class MotionBlockDetailComponent extends ListViewBaseComponent<ViewMotion
|
|||||||
titleService: Title,
|
titleService: Title,
|
||||||
translate: TranslateService,
|
translate: TranslateService,
|
||||||
matSnackBar: MatSnackBar,
|
matSnackBar: MatSnackBar,
|
||||||
|
private operator: OperatorService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private repo: MotionBlockRepositoryService,
|
private repo: MotionBlockRepositoryService,
|
||||||
@ -117,7 +120,11 @@ export class MotionBlockDetailComponent extends ListViewBaseComponent<ViewMotion
|
|||||||
* @returns an array of strings building the column definition
|
* @returns an array of strings building the column definition
|
||||||
*/
|
*/
|
||||||
public getColumnDefinition(): string[] {
|
public getColumnDefinition(): string[] {
|
||||||
return ['title', 'state', 'recommendation', 'remove'];
|
let columns = ['title', 'state', 'recommendation'];
|
||||||
|
if (this.operator.hasPerms('motions.can_manage_manage')) {
|
||||||
|
columns = columns.concat('remove');
|
||||||
|
}
|
||||||
|
return columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<os-head-bar [nav]="false" [mainButton]="true" (mainEvent)="onPlusButton()">
|
<os-head-bar [nav]="false" [mainButton]="canEdit" (mainEvent)="onPlusButton()">
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<div class="title-slot"><h2 translate>Motion blocks</h2></div>
|
<div class="title-slot"><h2 translate>Motion blocks</h2></div>
|
||||||
</os-head-bar>
|
</os-head-bar>
|
||||||
@ -7,17 +7,11 @@
|
|||||||
<mat-card class="os-card" *ngIf="blockToCreate">
|
<mat-card class="os-card" *ngIf="blockToCreate">
|
||||||
<mat-card-title translate>New motion block</mat-card-title>
|
<mat-card-title translate>New motion block</mat-card-title>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<form [formGroup]="createBlockForm"
|
<form [formGroup]="createBlockForm" (keydown)="onKeyDown($event)">
|
||||||
(keydown)="onKeyDown($event)">
|
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<p>
|
<p>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<input
|
<input formControlName="title" matInput placeholder="{{ 'Title' | translate }}" required />
|
||||||
formControlName="title"
|
|
||||||
matInput
|
|
||||||
placeholder="{{ 'Title' | translate }}"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<mat-error *ngIf="createBlockForm.get('title').hasError('required')" translate>
|
<mat-error *ngIf="createBlockForm.get('title').hasError('required')" translate>
|
||||||
A name is required
|
A name is required
|
||||||
</mat-error>
|
</mat-error>
|
||||||
@ -76,7 +70,12 @@
|
|||||||
<ng-container matColumnDef="menu">
|
<ng-container matColumnDef="menu">
|
||||||
<mat-header-cell *matHeaderCellDef>Menu</mat-header-cell>
|
<mat-header-cell *matHeaderCellDef>Menu</mat-header-cell>
|
||||||
<mat-cell *matCellDef="let block">
|
<mat-cell *matCellDef="let block">
|
||||||
<button mat-icon-button [matMenuTriggerFor]="singleItemMenu" [matMenuTriggerData]="{ item: block }">
|
<button
|
||||||
|
*ngIf="canEdit"
|
||||||
|
mat-icon-button
|
||||||
|
[matMenuTriggerFor]="singleItemMenu"
|
||||||
|
[matMenuTriggerData]="{ item: block }"
|
||||||
|
>
|
||||||
<mat-icon>more_vert</mat-icon>
|
<mat-icon>more_vert</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</mat-cell>
|
</mat-cell>
|
||||||
|
@ -7,14 +7,15 @@ import { MatSnackBar } from '@angular/material';
|
|||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
|
||||||
|
import { itemVisibilityChoices } from 'app/shared/models/agenda/item';
|
||||||
import { ListViewBaseComponent } from 'app/site/base/list-view-base';
|
import { ListViewBaseComponent } from 'app/site/base/list-view-base';
|
||||||
import { MotionBlock } from 'app/shared/models/motions/motion-block';
|
import { MotionBlock } from 'app/shared/models/motions/motion-block';
|
||||||
import { itemVisibilityChoices } from 'app/shared/models/agenda/item';
|
|
||||||
import { MotionBlockRepositoryService } from 'app/core/repositories/motions/motion-block-repository.service';
|
import { MotionBlockRepositoryService } from 'app/core/repositories/motions/motion-block-repository.service';
|
||||||
import { ViewMotionBlock } from '../../models/view-motion-block';
|
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||||
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
|
|
||||||
import { PromptService } from 'app/core/ui-services/prompt.service';
|
import { PromptService } from 'app/core/ui-services/prompt.service';
|
||||||
import { ViewItem } from 'app/site/agenda/models/view-item';
|
import { ViewItem } from 'app/site/agenda/models/view-item';
|
||||||
|
import { ViewMotionBlock } from '../../models/view-motion-block';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table for the motion blocks
|
* Table for the motion blocks
|
||||||
@ -50,6 +51,15 @@ export class MotionBlockListComponent extends ListViewBaseComponent<ViewMotionBl
|
|||||||
*/
|
*/
|
||||||
public itemVisibility = itemVisibilityChoices;
|
public itemVisibility = itemVisibilityChoices;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* helper for permission checks
|
||||||
|
*
|
||||||
|
* @returns true if the user may alter motions or their metadata
|
||||||
|
*/
|
||||||
|
public get canEdit(): boolean {
|
||||||
|
return this.operator.hasPerms('motions.can_manage', 'motions.can_manage_metadata');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the motion block list view
|
* Constructor for the motion block list view
|
||||||
*
|
*
|
||||||
@ -63,6 +73,8 @@ export class MotionBlockListComponent extends ListViewBaseComponent<ViewMotionBl
|
|||||||
* @param DS the dataStore
|
* @param DS the dataStore
|
||||||
* @param formBuilder creates forms
|
* @param formBuilder creates forms
|
||||||
* @param promptService the delete prompt
|
* @param promptService the delete prompt
|
||||||
|
* @param itemRepo
|
||||||
|
* @param operator permission checks
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
titleService: Title,
|
titleService: Title,
|
||||||
@ -74,7 +86,8 @@ export class MotionBlockListComponent extends ListViewBaseComponent<ViewMotionBl
|
|||||||
private agendaRepo: ItemRepositoryService,
|
private agendaRepo: ItemRepositoryService,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private promptService: PromptService,
|
private promptService: PromptService,
|
||||||
private itemRepo: ItemRepositoryService
|
private itemRepo: ItemRepositoryService,
|
||||||
|
private operator: OperatorService
|
||||||
) {
|
) {
|
||||||
super(titleService, translate, matSnackBar);
|
super(titleService, translate, matSnackBar);
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
<span translate>List of speakers</span>
|
<span translate>List of speakers</span>
|
||||||
</button>
|
</button>
|
||||||
<!-- Project -->
|
<!-- Project -->
|
||||||
<button mat-menu-item>
|
<button mat-menu-item *osPerms="'core.can_manage_projector'">
|
||||||
<mat-icon>videocam</mat-icon>
|
<mat-icon>videocam</mat-icon>
|
||||||
<span translate>Project</span>
|
<span translate>Project</span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -193,6 +193,12 @@
|
|||||||
<span translate>Import</span>
|
<span translate>Import</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngIf="!perms.isAllowed('manage')">
|
||||||
|
<button mat-menu-item (click)="directPdfExport()">
|
||||||
|
<mat-icon>archive</mat-icon>
|
||||||
|
<span translate>Export as PDF</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="isMultiSelect">
|
<div *ngIf="isMultiSelect">
|
||||||
<button mat-menu-item (click)="selectAll()">
|
<button mat-menu-item (click)="selectAll()">
|
||||||
|
@ -17,7 +17,7 @@ import { MotionRepositoryService } from 'app/core/repositories/motions/motion-re
|
|||||||
import { MotionSortListService } from '../../services/motion-sort-list.service';
|
import { MotionSortListService } from '../../services/motion-sort-list.service';
|
||||||
import { TagRepositoryService } from 'app/core/repositories/tags/tag-repository.service';
|
import { TagRepositoryService } from 'app/core/repositories/tags/tag-repository.service';
|
||||||
import { ViewCategory } from '../../models/view-category';
|
import { ViewCategory } from '../../models/view-category';
|
||||||
import { ViewMotion } from '../../models/view-motion';
|
import { ViewMotion, LineNumberingMode, ChangeRecoMode } from '../../models/view-motion';
|
||||||
import { ViewMotionBlock } from '../../models/view-motion-block';
|
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';
|
||||||
@ -274,4 +274,15 @@ export class MotionListComponent extends ListViewBaseComponent<ViewMotion> imple
|
|||||||
public getStateLabel(motion: ViewMotion): string {
|
public getStateLabel(motion: ViewMotion): string {
|
||||||
return this.motionRepo.getExtendedStateLabel(motion);
|
return this.motionRepo.getExtendedStateLabel(motion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Directly export all motions as pdf, using the current default config settings
|
||||||
|
*/
|
||||||
|
public directPdfExport(): void {
|
||||||
|
this.pdfExport.exportMotionCatalog(
|
||||||
|
this.dataSource.data,
|
||||||
|
this.configService.instant<string>('motions_default_line_numbering') as LineNumberingMode,
|
||||||
|
this.configService.instant<string>('motions_recommendation_text_mode') as ChangeRecoMode
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,6 +108,7 @@ export class LocalPermissionsService {
|
|||||||
(motion.state &&
|
(motion.state &&
|
||||||
motion.state.allow_submitter_edit &&
|
motion.state.allow_submitter_edit &&
|
||||||
motion.submitters &&
|
motion.submitters &&
|
||||||
|
motion.submitters.length &&
|
||||||
motion.submitters.some(submitter => submitter.id === this.operator.user.id))
|
motion.submitters.some(submitter => submitter.id === this.operator.user.id))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -123,6 +124,7 @@ export class LocalPermissionsService {
|
|||||||
motion.state &&
|
motion.state &&
|
||||||
motion.state.allow_submitter_edit &&
|
motion.state.allow_submitter_edit &&
|
||||||
motion.submitters &&
|
motion.submitters &&
|
||||||
|
motion.submitters.length &&
|
||||||
motion.submitters.some(submitter => submitter.id === this.operator.user.id)
|
motion.submitters.some(submitter => submitter.id === this.operator.user.id)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="column-right">
|
<div class="column-right" *osPerms="'core.can_manage_projector'">
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<div class="button-size">{{ projector.scroll }}</div>
|
<div class="button-size">{{ projector.scroll }}</div>
|
||||||
<button type="button" mat-icon-button (click)="scroll(scrollScaleDirection.Up)">
|
<button type="button" mat-icon-button (click)="scroll(scrollScaleDirection.Up)">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<os-head-bar [nav]="true" [mainButton]="true" (mainEvent)="onPlusButton()">
|
<os-head-bar [nav]="true" [mainButton]="canManage" (mainEvent)="onPlusButton()">
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<div class="title-slot">
|
<div class="title-slot">
|
||||||
<h2 translate>Projectors</h2>
|
<h2 translate>Projectors</h2>
|
||||||
@ -44,7 +44,7 @@
|
|||||||
<ng-container class="meta-text-block-title">
|
<ng-container class="meta-text-block-title">
|
||||||
{{ projector.name | translate }}
|
{{ projector.name | translate }}
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container class="meta-text-block-action-row">
|
<ng-container class="meta-text-block-action-row" *ngIf="canManage">
|
||||||
<button mat-icon-button *ngIf="editId !== projector.id" (click)=onEditButton(projector)>
|
<button mat-icon-button *ngIf="editId !== projector.id" (click)=onEditButton(projector)>
|
||||||
<mat-icon>edit</mat-icon>
|
<mat-icon>edit</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
@ -11,6 +11,7 @@ import { Projector } from 'app/shared/models/core/projector';
|
|||||||
import { BaseViewComponent } from 'app/site/base/base-view';
|
import { BaseViewComponent } from 'app/site/base/base-view';
|
||||||
import { PromptService } from 'app/core/ui-services/prompt.service';
|
import { PromptService } from 'app/core/ui-services/prompt.service';
|
||||||
import { ClockSlideService } from '../../services/clock-slide.service';
|
import { ClockSlideService } from '../../services/clock-slide.service';
|
||||||
|
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All supported aspect rations for projectors.
|
* All supported aspect rations for projectors.
|
||||||
@ -61,6 +62,15 @@ export class ProjectorListComponent extends BaseViewComponent implements OnInit
|
|||||||
*/
|
*/
|
||||||
public projectors: ViewProjector[];
|
public projectors: ViewProjector[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to check manage permissions
|
||||||
|
*
|
||||||
|
* @returns true if the user can manage projectors
|
||||||
|
*/
|
||||||
|
public get canManage(): boolean {
|
||||||
|
return this.operator.hasPerms('core.can_manage_projector');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Initializes all forms.
|
* Constructor. Initializes all forms.
|
||||||
*
|
*
|
||||||
@ -70,6 +80,8 @@ export class ProjectorListComponent extends BaseViewComponent implements OnInit
|
|||||||
* @param repo
|
* @param repo
|
||||||
* @param formBuilder
|
* @param formBuilder
|
||||||
* @param promptService
|
* @param promptService
|
||||||
|
* @param clockSlideService
|
||||||
|
* @param operator OperatorService
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
titleService: Title,
|
titleService: Title,
|
||||||
@ -78,7 +90,8 @@ export class ProjectorListComponent extends BaseViewComponent implements OnInit
|
|||||||
private repo: ProjectorRepositoryService,
|
private repo: ProjectorRepositoryService,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private promptService: PromptService,
|
private promptService: PromptService,
|
||||||
private clockSlideService: ClockSlideService
|
private clockSlideService: ClockSlideService,
|
||||||
|
private operator: OperatorService
|
||||||
) {
|
) {
|
||||||
super(titleService, translate, matSnackBar);
|
super(titleService, translate, matSnackBar);
|
||||||
|
|
||||||
|
@ -15,25 +15,33 @@
|
|||||||
|
|
||||||
<!-- Menu -->
|
<!-- Menu -->
|
||||||
<div class="menu-slot">
|
<div class="menu-slot">
|
||||||
<button type="button" mat-icon-button [matMenuTriggerFor]="userExtraMenu">
|
<button
|
||||||
|
type="button"
|
||||||
|
mat-icon-button
|
||||||
|
*ngIf="isAllowed('changePersonal')"
|
||||||
|
[matMenuTriggerFor]="userExtraMenu"
|
||||||
|
>
|
||||||
<mat-icon>more_vert</mat-icon>
|
<mat-icon>more_vert</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<mat-menu #userExtraMenu="matMenu">
|
<mat-menu #userExtraMenu="matMenu">
|
||||||
<button mat-menu-item class="red-warning-text" (click)="deleteUserButton()">
|
<button mat-menu-item *ngIf="isAllowed('changePersonal')" (click)="changePassword()">
|
||||||
<mat-icon>delete</mat-icon>
|
|
||||||
<span translate>Delete</span>
|
|
||||||
</button>
|
|
||||||
<button mat-menu-item (click)="changePassword()">
|
|
||||||
<mat-icon>security</mat-icon>
|
<mat-icon>security</mat-icon>
|
||||||
<span translate>Change password</span>
|
<span translate>Change password</span>
|
||||||
</button>
|
</button>
|
||||||
<!-- PDF -->
|
<!-- PDF -->
|
||||||
<button mat-menu-item *ngIf="isAllowed('seePersonal')" (click)="onDownloadPdf()">
|
<button mat-menu-item *ngIf="isAllowed('manage')" (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>
|
||||||
|
<div *ngIf="isAllowed('delete')">
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<button mat-menu-item class="red-warning-text" (click)="deleteUserButton()">
|
||||||
|
<mat-icon>delete</mat-icon>
|
||||||
|
<span translate>Delete</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</os-head-bar>
|
</os-head-bar>
|
||||||
|
|
||||||
@ -61,7 +69,6 @@
|
|||||||
[value]="user.title"
|
[value]="user.title"
|
||||||
/>
|
/>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<!-- First name -->
|
<!-- First name -->
|
||||||
<mat-form-field
|
<mat-form-field
|
||||||
class="form37 distance force-min-with"
|
class="form37 distance force-min-with"
|
||||||
@ -97,7 +104,7 @@
|
|||||||
placeholder="{{ 'Email' | translate }}"
|
placeholder="{{ 'Email' | translate }}"
|
||||||
name="email"
|
name="email"
|
||||||
formControlName="email"
|
formControlName="email"
|
||||||
[value]="user.email"
|
[value]="user.email ? user.email: null"
|
||||||
/>
|
/>
|
||||||
<mat-error *ngIf="personalInfoForm.get('email').hasError('email')" translate>
|
<mat-error *ngIf="personalInfoForm.get('email').hasError('email')" translate>
|
||||||
Please enter a valid email address
|
Please enter a valid email address
|
||||||
@ -126,10 +133,7 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<!-- Participant Number -->
|
<!-- Participant Number -->
|
||||||
<mat-form-field
|
<mat-form-field class="form25 force-min-with" *ngIf="user.number || (editUser && isAllowed('manage'))">
|
||||||
class="form25 force-min-with"
|
|
||||||
*ngIf="user.number || (editUser && isAllowed('manage'))"
|
|
||||||
>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
matInput
|
matInput
|
||||||
@ -144,7 +148,9 @@
|
|||||||
<!-- Groups -->
|
<!-- Groups -->
|
||||||
<mat-form-field *ngIf="(user.groups && user.groups.length > 0) || editUser">
|
<mat-form-field *ngIf="(user.groups && user.groups.length > 0) || editUser">
|
||||||
<mat-select placeholder="{{ 'Groups' | translate }}" formControlName="groups_id" multiple>
|
<mat-select placeholder="{{ 'Groups' | translate }}" formControlName="groups_id" multiple>
|
||||||
<mat-option *ngFor="let group of groups" [value]="group.id">{{ group.getTitle() | translate }}</mat-option>
|
<mat-option *ngFor="let group of groups" [value]="group.id">{{
|
||||||
|
group.getTitle() | translate
|
||||||
|
}}</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
@ -166,6 +166,7 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
* correct permission to perform the given action.
|
* correct permission to perform the given action.
|
||||||
*
|
*
|
||||||
* actions might be:
|
* actions might be:
|
||||||
|
* - delete (deleting the user) (users.can_manage and not ownPage)
|
||||||
* - seeName (title, 1st, last) (user.can_see_name or ownPage)
|
* - seeName (title, 1st, last) (user.can_see_name or ownPage)
|
||||||
* - seeExtra (checkboxes, comment) (user.can_see_extra_data)
|
* - seeExtra (checkboxes, comment) (user.can_see_extra_data)
|
||||||
* - seePersonal (mail, username, about) (user.can_see_extra_data or ownPage)
|
* - seePersonal (mail, username, about) (user.can_see_extra_data or ownPage)
|
||||||
@ -176,6 +177,8 @@ export class UserDetailComponent extends BaseViewComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
public isAllowed(action: string): boolean {
|
public isAllowed(action: string): boolean {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
case 'delete':
|
||||||
|
return this.operator.hasPerms('users.can_manage') && !this.ownPage;
|
||||||
case 'manage':
|
case 'manage':
|
||||||
return this.operator.hasPerms('users.can_manage');
|
return this.operator.hasPerms('users.can_manage');
|
||||||
case 'seeName':
|
case 'seeName':
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<os-head-bar mainButton="true" (mainEvent)="onPlusButton()" [multiSelectMode]="isMultiSelect">
|
<os-head-bar [mainButton]="canAddUser" (mainEvent)="onPlusButton()" [multiSelectMode]="isMultiSelect">
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<div class="title-slot"><h2 translate>Participants</h2></div>
|
<div class="title-slot"><h2 translate>Participants</h2></div>
|
||||||
|
|
||||||
@ -50,7 +50,7 @@
|
|||||||
<ng-container matColumnDef="group">
|
<ng-container matColumnDef="group">
|
||||||
<mat-header-cell *matHeaderCellDef mat-sort-header>Group</mat-header-cell>
|
<mat-header-cell *matHeaderCellDef mat-sort-header>Group</mat-header-cell>
|
||||||
<mat-cell *matCellDef="let user">
|
<mat-cell *matCellDef="let user">
|
||||||
<div class='groupsCell'>
|
<div class="groupsCell">
|
||||||
<span *ngIf="user.groups && user.groups.length">
|
<span *ngIf="user.groups && user.groups.length">
|
||||||
<mat-icon>people</mat-icon>
|
<mat-icon>people</mat-icon>
|
||||||
{{ user.groups }}
|
{{ user.groups }}
|
||||||
@ -108,15 +108,14 @@
|
|||||||
<button mat-menu-item (click)="pdfExportUserList()">
|
<button mat-menu-item (click)="pdfExportUserList()">
|
||||||
<mat-icon>picture_as_pdf</mat-icon>
|
<mat-icon>picture_as_pdf</mat-icon>
|
||||||
<span translate>List of participants (PDF)</span>
|
<span translate>List of participants (PDF)</span>
|
||||||
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button mat-menu-item (click)="onDownloadAccessPdf()">
|
<button mat-menu-item *osPerms="'users.can_manage'" (click)="onDownloadAccessPdf()">
|
||||||
<mat-icon>picture_as_pdf</mat-icon>
|
<mat-icon>picture_as_pdf</mat-icon>
|
||||||
<span translate>Access data (PDF)</span>
|
<span translate>Access data (PDF)</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button mat-menu-item (click)="csvExportUserList()">
|
<button mat-menu-item *osPerms="'users.can_manage'" (click)="csvExportUserList()">
|
||||||
<mat-icon>archive</mat-icon>
|
<mat-icon>archive</mat-icon>
|
||||||
<span translate>Export as CSV</span>
|
<span translate>Export as CSV</span>
|
||||||
</button>
|
</button>
|
||||||
@ -125,70 +124,72 @@
|
|||||||
<mat-icon>cloud_upload</mat-icon>
|
<mat-icon>cloud_upload</mat-icon>
|
||||||
<span translate>Import</span><span> ...</span>
|
<span translate>Import</span><span> ...</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
|
||||||
<div *ngIf="isMultiSelect">
|
|
||||||
<button mat-menu-item (click)="selectAll()">
|
|
||||||
<mat-icon>done_all</mat-icon>
|
|
||||||
<span translate>Select all</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button mat-menu-item (click)="deselectAll()">
|
<div *ngIf="isMultiSelect">
|
||||||
<mat-icon>clear</mat-icon>
|
<button mat-menu-item (click)="selectAll()">
|
||||||
<span translate>Deselect all</span>
|
<mat-icon>done_all</mat-icon>
|
||||||
</button>
|
<span translate>Select all</span>
|
||||||
|
|
||||||
<div *osPerms="'users.can_manage'">
|
|
||||||
<mat-divider></mat-divider>
|
|
||||||
<button mat-menu-item (click)="setGroupSelected()">
|
|
||||||
<mat-icon>people</mat-icon>
|
|
||||||
<span translate>Add/remove groups ...</span>
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div *ngIf="presenceViewConfigured">
|
<button mat-menu-item (click)="deselectAll()">
|
||||||
<button mat-menu-item *osPerms="'users.can_manage'" routerLink="presence">
|
<mat-icon>clear</mat-icon>
|
||||||
<mat-icon>transfer_within_a_station</mat-icon>
|
<span translate>Deselect all</span>
|
||||||
<span translate>Presence</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button mat-menu-item *osPerms="'users.can_manage'" routerLink="import">
|
|
||||||
<mat-icon>cloud_upload</mat-icon>
|
|
||||||
<span translate>Import</span><span> ...</span>
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div *osPerms="'users.can_manage'">
|
<div *osPerms="'users.can_manage'">
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
<button mat-menu-item (click)="setGroupSelected()">
|
||||||
<button mat-menu-item (click)="setActiveSelected()">
|
<mat-icon>people</mat-icon>
|
||||||
<mat-icon>block</mat-icon>
|
<span translate>Add/remove groups ...</span>
|
||||||
<span translate>Enable/disable account ...</span>
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button mat-menu-item (click)="setPresentSelected()">
|
<div *ngIf="presenceViewConfigured">
|
||||||
<mat-icon>check_box</mat-icon>
|
<button mat-menu-item *osPerms="'users.can_manage'" routerLink="presence">
|
||||||
<span translate>Set presence ...</span>
|
<mat-icon>transfer_within_a_station</mat-icon>
|
||||||
|
<span translate>Presence</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button mat-menu-item *osPerms="'users.can_manage'" routerLink="import">
|
||||||
|
<mat-icon>save_alt</mat-icon>
|
||||||
|
<span translate>Import</span><span> ...</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button mat-menu-item (click)="setCommitteeSelected()">
|
<div *osPerms="'users.can_manage'">
|
||||||
<mat-icon>account_balance</mat-icon>
|
<mat-divider></mat-divider>
|
||||||
<span translate>Set committee ...</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<mat-divider></mat-divider>
|
<button mat-menu-item (click)="setActiveSelected()">
|
||||||
|
<mat-icon>block</mat-icon>
|
||||||
|
<span translate>Enable/disable account ...</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button mat-menu-item (click)="sendInvitationEmailSelected()">
|
<button mat-menu-item (click)="setPresentSelected()">
|
||||||
<mat-icon>mail</mat-icon>
|
<mat-icon>check_box</mat-icon>
|
||||||
<span translate>Send invitation email</span>
|
<span translate>Set presence ...</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item (click)="resetPasswordsSelected()">
|
|
||||||
<mat-icon>vpn_key</mat-icon>
|
<button mat-menu-item (click)="setCommitteeSelected()">
|
||||||
<span translate>Generate new passwords</span>
|
<mat-icon>account_balance</mat-icon>
|
||||||
</button>
|
<span translate>Set committee ...</span>
|
||||||
<mat-divider></mat-divider>
|
</button>
|
||||||
<button mat-menu-item class="red-warning-text" (click)="deleteSelected()">
|
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-divider></mat-divider>
|
||||||
<span translate>Delete</span>
|
|
||||||
</button>
|
<button mat-menu-item (click)="sendInvitationEmailSelected()">
|
||||||
|
<mat-icon>mail</mat-icon>
|
||||||
|
<span translate>Send invitation email</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button mat-menu-item (click)="resetPasswordsSelected()">
|
||||||
|
<mat-icon>vpn_key</mat-icon>
|
||||||
|
<span translate>Generate new passwords</span>
|
||||||
|
</button>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<button mat-menu-item class="red-warning-text" (click)="deleteSelected()">
|
||||||
|
<mat-icon>delete</mat-icon>
|
||||||
|
<span translate>Delete</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -51,6 +51,15 @@ export class UserListComponent extends ListViewBaseComponent<ViewUser> implement
|
|||||||
return this._presenceViewConfigured;
|
return this._presenceViewConfigured;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to check for main button permissions
|
||||||
|
*
|
||||||
|
* @returns true if the user should be able to create users
|
||||||
|
*/
|
||||||
|
public get canAddUser(): boolean {
|
||||||
|
return this.operator.hasPerms('users.can_manage');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The usual constructor for components
|
* The usual constructor for components
|
||||||
* @param titleService Serivce for setting the title
|
* @param titleService Serivce for setting the title
|
||||||
|
Loading…
Reference in New Issue
Block a user