Merge pull request #5321 from tsiegleauq/projector-indicator-on-agenda

Projector indicator list view tables
This commit is contained in:
Emanuel Schütze 2020-05-05 17:50:27 +02:00 committed by GitHub
commit 77cf3e2785
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 95 additions and 48 deletions

View File

@ -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 -->

View File

@ -4,6 +4,7 @@ $pbl-height: var(--pbl-height);
.projector-button {
margin: auto;
display: flex;
}
.pbl-ngrid-row {

View File

@ -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;
}
}

View File

@ -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({

View File

@ -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;
}
/**

View File

@ -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>

View File

@ -16,10 +16,3 @@
.align-right {
margin-left: auto;
}
/*
* Where is this used?
*/
.done-check {
margin-right: 10px;
}

View File

@ -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>

View File

@ -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>

View File

@ -4,7 +4,7 @@
font-weight: 500;
font-size: 16px;
.attached-files {
.icon-prefix {
.mat-icon {
display: inline-flex;
vertical-align: middle;

View File

@ -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 */