Merge pull request #5321 from tsiegleauq/projector-indicator-on-agenda
Projector indicator list view tables
This commit is contained in:
commit
77cf3e2785
@ -22,6 +22,8 @@
|
||||
[columns]="columnSet"
|
||||
[hideColumns]="hiddenColumns"
|
||||
(rowClick)="onSelectRow($event)"
|
||||
[rowClassUpdate]="isElementProjected"
|
||||
rowClassUpdateFreq="ngDoCheck"
|
||||
>
|
||||
<!-- "row" has the view model -->
|
||||
<!-- "value" has the property, that was defined in the columnDefinition -->
|
||||
@ -30,10 +32,21 @@
|
||||
<!-- Projector column -->
|
||||
<div *pblNgridCellDef="'projector'; row as viewModel" class="fill ngrid-lg">
|
||||
<os-projector-button
|
||||
*osPerms="'core.can_manage_projector'"
|
||||
class="projector-button"
|
||||
[object]="getProjectable(viewModel)"
|
||||
(changeEvent)="viewUpdateEvent()"
|
||||
></os-projector-button>
|
||||
<!-- Projector indicator -->
|
||||
<div class="projector-button" *osPerms="'core.can_manage_projector'; complement: true">
|
||||
<mat-icon
|
||||
color="accent"
|
||||
*ngIf="projectorService.isProjected(getProjectable(viewModel))"
|
||||
matTooltip="{{ 'Currently projected' | translate }}"
|
||||
>
|
||||
videocam
|
||||
</mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- No Results -->
|
||||
|
@ -4,6 +4,7 @@ $pbl-height: var(--pbl-height);
|
||||
|
||||
.projector-button {
|
||||
margin: auto;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.pbl-ngrid-row {
|
||||
|
@ -0,0 +1,13 @@
|
||||
@import '~@angular/material/theming';
|
||||
|
||||
@mixin os-list-view-table-theme($theme) {
|
||||
$primary: map-get($theme, primary);
|
||||
$accent: map-get($theme, accent);
|
||||
$warn: map-get($theme, accent);
|
||||
$foreground: map-get($theme, foreground);
|
||||
$background: map-get($theme, background);
|
||||
|
||||
.projected {
|
||||
background-color: mat-color($background, hover) !important;
|
||||
}
|
||||
}
|
@ -5,8 +5,8 @@ import { E2EImportsModule } from 'e2e-imports.module';
|
||||
import { ListViewTableComponent } from './list-view-table.component';
|
||||
|
||||
describe('ListViewTableComponent', () => {
|
||||
let component: ListViewTableComponent<any, any>;
|
||||
let fixture: ComponentFixture<ListViewTableComponent<any, any>>;
|
||||
let component: ListViewTableComponent<any>;
|
||||
let fixture: ComponentFixture<ListViewTableComponent<any>>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
|
@ -13,18 +13,18 @@ import {
|
||||
import { NavigationStart, Router } from '@angular/router';
|
||||
|
||||
import { columnFactory, createDS, DataSourcePredicate, PblDataSource, PblNgridComponent } from '@pebula/ngrid';
|
||||
import { PblColumnDefinition, PblColumnFactory, PblNgridColumnSet } from '@pebula/ngrid/lib/grid';
|
||||
import { PblColumnDefinition, PblColumnFactory, PblNgridColumnSet, PblNgridRowContext } from '@pebula/ngrid/lib/grid';
|
||||
import { PblNgridDataMatrixRow } from '@pebula/ngrid/target-events';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { distinctUntilChanged, filter } from 'rxjs/operators';
|
||||
|
||||
import { OperatorService, Permission } from 'app/core/core-services/operator.service';
|
||||
import { ProjectorService } from 'app/core/core-services/projector.service';
|
||||
import { StorageService } from 'app/core/core-services/storage.service';
|
||||
import { HasViewModelListObservable } from 'app/core/definitions/has-view-model-list-observable';
|
||||
import { BaseFilterListService } from 'app/core/ui-services/base-filter-list.service';
|
||||
import { BaseSortListService } from 'app/core/ui-services/base-sort-list.service';
|
||||
import { ViewportService } from 'app/core/ui-services/viewport.service';
|
||||
import { BaseModel } from 'app/shared/models/base/base-model';
|
||||
import { BaseProjectableViewModel } from 'app/site/base/base-projectable-view-model';
|
||||
import { BaseViewModel } from 'app/site/base/base-view-model';
|
||||
import { BaseViewModelWithContentObject } from 'app/site/base/base-view-model-with-content-object';
|
||||
@ -89,7 +89,8 @@ export interface ColumnRestriction {
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel> implements OnInit, OnDestroy {
|
||||
export class ListViewTableComponent<V extends BaseViewModel | BaseViewModelWithContentObject>
|
||||
implements OnInit, OnDestroy {
|
||||
/**
|
||||
* Declare the table
|
||||
*/
|
||||
@ -254,11 +255,6 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
|
||||
*/
|
||||
private dataListObservable: Observable<V[]>;
|
||||
|
||||
/**
|
||||
* Minimal column width
|
||||
*/
|
||||
private columnMinWidth = '60px';
|
||||
|
||||
/**
|
||||
* The column set to display in the table
|
||||
*/
|
||||
@ -289,6 +285,14 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
|
||||
*/
|
||||
private subs: Subscription[] = [];
|
||||
|
||||
private get projectorColumnWidth(): number {
|
||||
if (this.operator.hasPerms('core.can_manage_projector')) {
|
||||
return 60;
|
||||
} else {
|
||||
return 24;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Most, of not all list views require these
|
||||
*/
|
||||
@ -302,7 +306,7 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
|
||||
{
|
||||
prop: 'projector',
|
||||
label: '',
|
||||
width: this.columnMinWidth
|
||||
width: `${this.projectorColumnWidth}px`
|
||||
}
|
||||
];
|
||||
return columns;
|
||||
@ -358,12 +362,7 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
|
||||
}
|
||||
|
||||
// hide the projector columns
|
||||
if (
|
||||
this.multiSelect ||
|
||||
this.isMobile ||
|
||||
!this.allowProjector ||
|
||||
!this.operator.hasPerms('core.can_manage_projector')
|
||||
) {
|
||||
if (this.multiSelect || this.isMobile || !this.allowProjector) {
|
||||
hidden.push('projector');
|
||||
}
|
||||
|
||||
@ -398,7 +397,8 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
|
||||
vp: ViewportService,
|
||||
router: Router,
|
||||
private store: StorageService,
|
||||
private cd: ChangeDetectorRef
|
||||
private cd: ChangeDetectorRef,
|
||||
public projectorService: ProjectorService
|
||||
) {
|
||||
vp.isMobileSubject.subscribe(mobile => {
|
||||
if (mobile !== this.isMobile) {
|
||||
@ -458,7 +458,7 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
|
||||
// Define the columns. Has to be in the OnInit cause "columns" is slower than
|
||||
// the constructor of this class
|
||||
this.columnSet = columnFactory()
|
||||
.default({ width: this.columnMinWidth })
|
||||
.default({ width: '60px' })
|
||||
.table(...this.defaultStartColumns, ...this.columns, ...this.defaultEndColumns)
|
||||
.build();
|
||||
|
||||
@ -483,6 +483,12 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
|
||||
}
|
||||
}
|
||||
|
||||
public isElementProjected = (context: PblNgridRowContext<V>) => {
|
||||
if (this.projectorService.isProjected(this.getProjectable(context.$implicit as V))) {
|
||||
return 'projected';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines and sets the raw data as observable lists according
|
||||
* to the used search and filter services
|
||||
@ -597,11 +603,8 @@ export class ListViewTableComponent<V extends BaseViewModel, M extends BaseModel
|
||||
* @param viewModel The model of the table
|
||||
* @returns a view model that can be projected
|
||||
*/
|
||||
public getProjectable(
|
||||
viewModel: BaseViewModelWithContentObject | BaseProjectableViewModel
|
||||
): BaseProjectableViewModel {
|
||||
const withContent = viewModel as BaseViewModelWithContentObject;
|
||||
return !!withContent.contentObject ? withContent.contentObject : viewModel;
|
||||
public getProjectable(viewModel: V): BaseProjectableViewModel {
|
||||
return (viewModel as BaseViewModelWithContentObject)?.contentObject ?? viewModel;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,19 +33,31 @@
|
||||
<div *pblNgridCellDef="'title'; row as item; rowContext as rowContext" class="cell-slot fill">
|
||||
<a class="detail-link" [routerLink]="getDetailUrl(item)" *ngIf="!isMultiSelect"></a>
|
||||
<div [ngStyle]="{ 'margin-left': item.level * 25 + 'px' }" class="innerTable">
|
||||
<os-icon-container [noWrap]="true" [icon]="item.closed ? 'check' : null" size="large">
|
||||
<div class="ellipsis-overflow">
|
||||
|
||||
<!-- Title line -->
|
||||
<div class="title-line ellipsis-overflow">
|
||||
<!-- Is Closed -->
|
||||
<span class="icon-prefix" *ngIf="item.closed">
|
||||
<mat-icon>check</mat-icon>
|
||||
</span>
|
||||
|
||||
<!-- Title -->
|
||||
<span>
|
||||
{{ item.getListTitle() }}
|
||||
</div>
|
||||
<div *ngIf="showSubtitle" class="subtitle ellipsis-overflow">
|
||||
{{ item.getSubtitle() }}
|
||||
</div>
|
||||
<div *ngIf="item.comment" class="subtitle ellipsis-overflow">
|
||||
<os-icon-container size="small" icon="comment" [noWrap]="true">
|
||||
{{ item.comment }}
|
||||
</os-icon-container>
|
||||
</div>
|
||||
</os-icon-container>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Subtitle line -->
|
||||
<div class="subtitle ellipsis-overflow">
|
||||
{{ item.getSubtitle() }}
|
||||
</div>
|
||||
|
||||
<!-- Comment line -->
|
||||
<div class="subtitle ellipsis-overflow" *ngIf="item.comment">
|
||||
<os-icon-container size="small" icon="comment" [noWrap]="true">
|
||||
{{ item.comment }}
|
||||
</os-icon-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -121,7 +133,12 @@
|
||||
<span>{{ 'Import' | translate }}</span>
|
||||
</button>
|
||||
<mat-divider></mat-divider>
|
||||
<button mat-menu-item *osPerms="'agenda.can_manage'" class="red-warning-text" (click)="deleteAllSpeakersOfAllListsOfSpeakers()">
|
||||
<button
|
||||
mat-menu-item
|
||||
*osPerms="'agenda.can_manage'"
|
||||
class="red-warning-text"
|
||||
(click)="deleteAllSpeakersOfAllListsOfSpeakers()"
|
||||
>
|
||||
<mat-icon>delete</mat-icon>
|
||||
<span>{{ 'Clear all list of speakers' | translate }}</span>
|
||||
</button>
|
||||
@ -229,7 +246,12 @@
|
||||
<span>{{ 'Remove from agenda' | translate }}</span>
|
||||
</button>
|
||||
|
||||
<button mat-menu-item class="red-warning-text" (click)="deleteTopic(item)" *ngIf="isTopic(item.contentObject)">
|
||||
<button
|
||||
mat-menu-item
|
||||
class="red-warning-text"
|
||||
(click)="deleteTopic(item)"
|
||||
*ngIf="isTopic(item.contentObject)"
|
||||
>
|
||||
<mat-icon>delete</mat-icon>
|
||||
<span>{{ 'Delete' | translate }}</span>
|
||||
</button>
|
||||
|
@ -16,10 +16,3 @@
|
||||
.align-right {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
* Where is this used?
|
||||
*/
|
||||
.done-check {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
@ -68,7 +68,7 @@
|
||||
</span>
|
||||
|
||||
<!-- Has File -->
|
||||
<span class="attached-files" *ngIf="motion.hasAttachments()">
|
||||
<span class="icon-prefix" *ngIf="motion.hasAttachments()">
|
||||
<mat-icon>attach_file</mat-icon>
|
||||
</span>
|
||||
|
||||
|
@ -74,7 +74,7 @@
|
||||
</span>
|
||||
|
||||
<!-- Has File -->
|
||||
<span class="attached-files" *ngIf="motion.hasAttachments()">
|
||||
<span class="icon-prefix" *ngIf="motion.hasAttachments()">
|
||||
<mat-icon>attach_file</mat-icon>
|
||||
</span>
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
|
||||
.attached-files {
|
||||
.icon-prefix {
|
||||
.mat-icon {
|
||||
display: inline-flex;
|
||||
vertical-align: middle;
|
||||
|
@ -33,6 +33,7 @@
|
||||
@import './app/site/assignments/components/assignment-poll-detail/assignment-poll-detail-component.scss-theme.scss';
|
||||
@import './app/shared/components/progress-snack-bar/progress-snack-bar.component.scss-theme.scss';
|
||||
@import './app/shared/components/jitsi/jitsi.component.scss-theme.scss';
|
||||
@import './app/shared/components/list-view-table/list-view-table.component.scss-theme.scss';
|
||||
|
||||
/** fonts */
|
||||
@import './assets/styles/fonts.scss';
|
||||
@ -66,6 +67,7 @@ $narrow-spacing: (
|
||||
@include os-assignment-poll-detail-style($theme);
|
||||
@include os-progress-snack-bar-style($theme);
|
||||
@include os-jitsi-theme($theme);
|
||||
@include os-list-view-table-theme($theme);
|
||||
}
|
||||
|
||||
/** Load projector specific SCSS values */
|
||||
|
Loading…
Reference in New Issue
Block a user