Cleanup main routing page and ngrid lists

Sets the main container to absolute,
makes it easier to detect the pages height
ngrid lists can dynamically detect the page height using flexbox,
remove external class injection from list-views,
add "spacer-bottom-60" class for the jitsi-container,
add it everywhere where the jitsi container could hide the content.
This commit is contained in:
Sean 2020-06-17 15:24:23 +02:00
parent f70953f454
commit 22a374a150
31 changed files with 290 additions and 340 deletions

View File

@ -1,70 +1,72 @@
<mat-drawer-container *ngIf="columns && columnSet"> <mat-drawer-container class="list-view-frame" *ngIf="columns && columnSet">
<os-sort-filter-bar <div class="list-view-table-wrapper">
*ngIf="showFilterBar" <os-sort-filter-bar
[totalCount]="totalCount" class="sort-filter-bar"
[filterCount]="countFilter" *ngIf="showFilterBar"
[filterService]="filterService" [totalCount]="totalCount"
[sortService]="sortService" [filterCount]="countFilter"
[searchFieldInput]="inputValue" [filterService]="filterService"
(searchFieldChange)="searchFilter($event)" [sortService]="sortService"
> [searchFieldInput]="inputValue"
</os-sort-filter-bar> (searchFieldChange)="searchFilter($event)"
>
</os-sort-filter-bar>
<!-- vScrollFixed="110" --> <pbl-ngrid
<!-- vScrollAuto () --> class="vscroll-list-view"
<pbl-ngrid [attr.vScrollFixed]="vScrollFixed !== -1 ? vScrollFixed : false"
[ngClass]="cssClasses" [attr.vScrollAuto]="vScrollFixed === -1"
[attr.vScrollFixed]="vScrollFixed !== -1 ? vScrollFixed : false" [showHeader]="!showFilterBar || !fullScreen"
[attr.vScrollAuto]="vScrollFixed === -1" [showHeader]="false"
[showHeader]="!showFilterBar || !fullScreen" matCheckboxSelection="selection"
matCheckboxSelection="selection" [dataSource]="dataSource"
[dataSource]="dataSource" [columns]="columnSet"
[columns]="columnSet" [hideColumns]="hiddenColumns"
[hideColumns]="hiddenColumns" (rowClick)="onSelectRow($event)"
(rowClick)="onSelectRow($event)" [rowClassUpdate]="isElementProjected"
[rowClassUpdate]="isElementProjected" rowClassUpdateFreq="ngDoCheck"
rowClassUpdateFreq="ngDoCheck" >
> <!-- "row" has the view model -->
<!-- "row" has the view model --> <!-- "value" has the property, that was defined in the columnDefinition -->
<!-- "value" has the property, that was defined in the columnDefinition --> <!-- "col" has a column reference -->
<!-- "col" has a column reference -->
<!-- Projector column --> <!-- Projector column -->
<div *pblNgridCellDef="'projector'; row as viewModel" class="fill ngrid-lg"> <div *pblNgridCellDef="'projector'; row as viewModel" class="fill ngrid-lg">
<os-projector-button <os-projector-button
*osPerms="'core.can_manage_projector'" *osPerms="'core.can_manage_projector'"
class="projector-button" class="projector-button"
[object]="getProjectable(viewModel)" [object]="getProjectable(viewModel)"
(changeEvent)="viewUpdateEvent()" (changeEvent)="viewUpdateEvent()"
></os-projector-button> ></os-projector-button>
<!-- Projector indicator --> <!-- Projector indicator -->
<div class="projector-button" *osPerms="'core.can_manage_projector'; complement: true"> <div class="projector-button" *osPerms="'core.can_manage_projector'; complement: true">
<mat-icon <mat-icon
color="accent" color="accent"
*ngIf="projectorService.isProjected(getProjectable(viewModel))" *ngIf="projectorService.isProjected(getProjectable(viewModel))"
matTooltip="{{ 'Currently projected' | translate }}" matTooltip="{{ 'Currently projected' | translate }}"
> >
videocam videocam
</mat-icon> </mat-icon>
</div>
</div> </div>
</div>
<!-- No Results --> <!-- No Results -->
<div *pblNgridNoDataRef class="pbl-ngrid-no-data"> <div *pblNgridNoDataRef class="pbl-ngrid-no-data">
<span>{{ 'No data' | translate }}</span> <span>{{ 'No data' | translate }}</span>
</div> </div>
<!-- Slot transclusion for the individual cells --> <!-- Slot transclusion for the individual cells -->
<div #contentWrapper> <div #contentWrapper>
<ng-content class="ngrid-lg" select=".cell-slot"></ng-content> <ng-content class="ngrid-lg" select=".cell-slot"></ng-content>
</div> </div>
<!-- Speaker --> <!-- Speaker -->
<div *pblNgridCellDef="'speaker'; row as viewModel; rowContext as rowContext" class="fill"> <div *pblNgridCellDef="'speaker'; row as viewModel; rowContext as rowContext" class="fill">
<os-speaker-button <os-speaker-button
[object]="viewModel.contentObjectData ? viewModel.contentObjectData : viewModel" [object]="viewModel.contentObjectData ? viewModel.contentObjectData : viewModel"
[disabled]="multiSelect" [disabled]="multiSelect"
></os-speaker-button> ></os-speaker-button>
</div> </div>
</pbl-ngrid> </pbl-ngrid>
</div>
</mat-drawer-container> </mat-drawer-container>

View File

@ -2,26 +2,45 @@
$pbl-height: var(--pbl-height); $pbl-height: var(--pbl-height);
.projector-button { .list-view-frame {
margin: auto; // remove the height of the top-bar
height: calc(100vh - 64px);
}
.list-view-table-wrapper {
display: flex; display: flex;
} flex-flow: column;
height: 100%;
.pbl-ngrid-row { .sort-filter-bar {
height: $pbl-height; flex: 0 1 auto;
} display: block;
}
// additional space if the jitsi integration is active .vscroll-list-view {
.pbl-ngrid-row:last-of-type { flex: 1 1 auto;
margin-bottom: 30px !important;
}
.pbl-ngrid-cell { .projector-button {
height: inherit; margin: auto;
} display: flex;
}
.multiselect { .pbl-ngrid-row {
.pbl-ngrid-cell { height: $pbl-height;
cursor: pointer; }
.pbl-ngrid-row:last-of-type {
margin-bottom: 60px !important;
}
.pbl-ngrid-cell {
height: inherit;
}
.multiselect {
.pbl-ngrid-cell {
cursor: pointer;
}
}
} }
} }

View File

@ -214,31 +214,6 @@ export class ListViewTableComponent<V extends BaseViewModel | BaseViewModelWithC
@Input() @Input()
public fullScreen = true; public fullScreen = true;
/**
* Option to apply additional classes to the virtual-scrolling-list.
*/
@Input()
public set cssClasses(values: CssClassDefinition) {
this._cssClasses = values;
}
/**
* Returns the list of classes, that are applied to the virtual-scrolling-list.
* Already prepared for the `[ngClass]`-property.
*
* `Warning: The defaultClasses will overwrite custom classes with the same key.`
*
* @returns An object looking like `{ [key: string]: boolean }`.
*/
public get cssClasses(): CssClassDefinition {
const defaultClasses = {
'virtual-scroll-with-head-bar ngrid-hide-head': this.fullScreen && this.showFilterBar,
'virtual-scroll-full-page': this.fullScreen && !this.showFilterBar,
multiselect: this.multiSelect
};
return Object.assign(this._cssClasses, defaultClasses);
}
/** /**
* Inform about changes in the dataSource * Inform about changes in the dataSource
*/ */
@ -275,11 +250,6 @@ export class ListViewTableComponent<V extends BaseViewModel | BaseViewModelWithC
*/ */
public inputValue: string; public inputValue: string;
/**
* Private variable to hold all classes for the virtual-scrolling-list.
*/
private _cssClasses: CssClassDefinition = {};
/** /**
* Collect subsciptions * Collect subsciptions
*/ */

View File

@ -1,4 +1,4 @@
<mat-card [ngClass]="isEditing ? 'os-form-card' : 'os-card'"> <mat-card class="spacer-bottom-60" [ngClass]="isEditing ? 'os-form-card' : 'os-card'">
<ng-container *ngIf="!isEditing"> <ng-container *ngIf="!isEditing">
<div *ngIf="privacyPolicy" [innerHtml]="privacyPolicy | trust: 'html'"></div> <div *ngIf="privacyPolicy" [innerHtml]="privacyPolicy | trust: 'html'"></div>
<div *ngIf="!privacyPolicy"> <div *ngIf="!privacyPolicy">

View File

@ -10,7 +10,7 @@
</div> </div>
</os-head-bar> </os-head-bar>
<mat-card class="os-card"> <mat-card class="os-card spacer-bottom-60">
<ng-container [ngTemplateOutlet]="viewTemplate"></ng-container> <ng-container [ngTemplateOutlet]="viewTemplate"></ng-container>
</mat-card> </mat-card>
@ -46,6 +46,7 @@
<div class="named-result-table" *ngIf="poll.type === 'named'"> <div class="named-result-table" *ngIf="poll.type === 'named'">
<h3>{{ 'Single votes' | translate }}</h3> <h3>{{ 'Single votes' | translate }}</h3>
<os-list-view-table <os-list-view-table
class="single-votes-table"
*ngIf="votesDataObservable" *ngIf="votesDataObservable"
[listObservable]="votesDataObservable" [listObservable]="votesDataObservable"
[columns]="columnDefinitionSingleVotes" [columns]="columnDefinitionSingleVotes"
@ -56,7 +57,6 @@
listStorageKey="assignment-poll-vote" listStorageKey="assignment-poll-vote"
[showListOfSpeakers]="false" [showListOfSpeakers]="false"
[showMenu]="false" [showMenu]="false"
[cssClasses]="{ 'single-votes-table': true }"
> >
<!-- Header --> <!-- Header -->
<div *pblNgridHeaderCellDef="'user'; col as col"> <div *pblNgridHeaderCellDef="'user'; col as col">

View File

@ -13,6 +13,10 @@
display: block; display: block;
height: 500px; height: 500px;
.list-view-frame {
height: 100%;
}
.single-vote-result + .single-vote-result { .single-vote-result + .single-vote-result {
margin-top: 1em; margin-top: 1em;
} }

View File

@ -54,7 +54,7 @@
</mat-card> </mat-card>
</mat-card> </mat-card>
<mat-card class="os-card" *osPerms="'users.can_manage'"> <mat-card class="os-card spacer-bottom-60" *osPerms="'users.can_manage'">
<h2>{{ 'Statistics' | translate }}</h2> <h2>{{ 'Statistics' | translate }}</h2>
<div> <div>
<h3>{{ 'Active users' | translate }}</h3> <h3>{{ 'Active users' | translate }}</h3>

View File

@ -12,7 +12,7 @@
</div> </div>
</os-head-bar> </os-head-bar>
<mat-card [ngClass]="isEditing ? 'os-form-card' : 'os-card'"> <mat-card class="spacer-bottom-60" [ngClass]="isEditing ? 'os-form-card' : 'os-card'">
<ng-container *ngIf="!isEditing"> <ng-container *ngIf="!isEditing">
<div class="app-content"> <div class="app-content">
<h1>{{ startContent.general_event_welcome_title | translate }}</h1> <h1>{{ startContent.general_event_welcome_title | translate }}</h1>

View File

@ -20,6 +20,7 @@
</tr> </tr>
</table> </table>
<os-list-view-table <os-list-view-table
class="user-statistics-table--virtual-scroll "
[listObservable]="statisticsByStructureLevelObservable" [listObservable]="statisticsByStructureLevelObservable"
[columns]="columnDefinition" [columns]="columnDefinition"
[filterProps]="filterProps" [filterProps]="filterProps"
@ -27,7 +28,6 @@
[allowProjector]="false" [allowProjector]="false"
[fullScreen]="false" [fullScreen]="false"
[showListOfSpeakers]="false" [showListOfSpeakers]="false"
[cssClasses]="{ 'user-statistics-table--virtual-scroll': true }"
> >
<!-- Header --> <!-- Header -->
<div *pblNgridHeaderCellDef="'*'; col as col"> <div *pblNgridHeaderCellDef="'*'; col as col">

View File

@ -17,9 +17,10 @@
} }
.user-statistics-table--virtual-scroll { .user-statistics-table--virtual-scroll {
display: block;
height: 500px; height: 500px;
.pbl-ngrid-header-cell:not(:first-child):before { .list-view-frame {
display: none; height: 100%;
} }
} }

View File

@ -22,7 +22,7 @@
<div class="spacer-top-20"></div> <div class="spacer-top-20"></div>
<mat-card class="os-card" *ngIf="configGroup"> <mat-card class="os-card spacer-bottom-60" *ngIf="configGroup">
<div id="wrapper"> <div id="wrapper">
<ng-container *ngFor="let subgroup of configGroup.subgroups; trackBy: trackByIndex"> <ng-container *ngFor="let subgroup of configGroup.subgroups; trackBy: trackByIndex">
<h3 class="accent" *ngIf="configGroup.subgroups.length > 1">{{ subgroup.name | translate }}</h3> <h3 class="accent" *ngIf="configGroup.subgroups.length > 1">{{ subgroup.name | translate }}</h3>

View File

@ -11,73 +11,75 @@
</div> </div>
</os-head-bar> </os-head-bar>
<div class="custom-table-header"> <mat-card class="os-card spacer-bottom-60">
<div> <div class="history-table-header">
<span [formGroup]="modelSelectForm"> <div>
<span [formGroup]="modelSelectForm">
<mat-form-field>
<os-search-value-selector
formControlName="model"
[multiple]="false"
[includeNone]="false"
placeholder="{{ 'Motion' | translate }}"
[inputListValues]="collectionObserver"
></os-search-value-selector>
</mat-form-field>
</span>
<span class="spacer-left-20">
<button mat-button (click)="refresh()" *ngIf="currentModelId">
<mat-icon>refresh</mat-icon>
<span>{{ 'Refresh' | translate }}</span>
</button>
</span>
</div>
<div>
<mat-form-field> <mat-form-field>
<os-search-value-selector <input matInput (keyup)="applySearch($event.target.value)" placeholder="{{ 'Search' | translate }}" />
formControlName="model" <mat-icon matSuffix>search</mat-icon>
[multiple]="false"
[includeNone]="false"
placeholder="{{ 'Motion' | translate }}"
[inputListValues]="collectionObserver"
></os-search-value-selector>
</mat-form-field> </mat-form-field>
</span> </div>
<span class="spacer-left-20">
<button mat-button (click)="refresh()" *ngIf="currentModelId">
<mat-icon>refresh</mat-icon>
<span>{{ 'Refresh' | translate }}</span>
</button>
</span>
</div> </div>
<div>
<mat-form-field>
<input matInput (keyup)="applySearch($event.target.value)" placeholder="{{ 'Search' | translate }}" />
<mat-icon matSuffix>search</mat-icon>
</mat-form-field>
</div>
</div>
<mat-table [dataSource]="dataSource" matSort class="os-headed-listview-table"> <mat-table [dataSource]="dataSource" matSort class="os-headed-listview-table">
<!-- Timestamp --> <!-- Timestamp -->
<ng-container matColumnDef="time"> <ng-container matColumnDef="time">
<mat-header-cell *matHeaderCellDef>{{ 'Timestamp' | translate }}</mat-header-cell> <mat-header-cell *matHeaderCellDef>{{ 'Timestamp' | translate }}</mat-header-cell>
<mat-cell *matCellDef="let history">{{ getTimestamp(history) }}</mat-cell> <mat-cell *matCellDef="let history">{{ getTimestamp(history) }}</mat-cell>
</ng-container> </ng-container>
<!-- Element --> <!-- Element -->
<ng-container matColumnDef="element"> <ng-container matColumnDef="element">
<mat-header-cell *matHeaderCellDef>{{ 'Element' | translate }}</mat-header-cell> <mat-header-cell *matHeaderCellDef>{{ 'Element' | translate }}</mat-header-cell>
<mat-cell *matCellDef="let history"> <mat-cell *matCellDef="let history">
<div *ngIf="getElementInfo(history)">{{ getElementInfo(history) | translate }}</div> <div *ngIf="getElementInfo(history)">{{ getElementInfo(history) | translate }}</div>
<div <div
class="no-info" class="no-info"
matTooltip="{{ 'This element does not exist at this time.' | translate }}" matTooltip="{{ 'This element does not exist at this time.' | translate }}"
*ngIf="!getElementInfo(history)" *ngIf="!getElementInfo(history)"
> >
<span>{{ 'No information available' | translate }} ({{ history.element_id }})</span> <span>{{ 'No information available' | translate }} ({{ history.element_id }})</span>
</div> </div>
</mat-cell> </mat-cell>
</ng-container> </ng-container>
<!-- Info --> <!-- Info -->
<ng-container matColumnDef="info"> <ng-container matColumnDef="info">
<mat-header-cell *matHeaderCellDef>{{ 'Comment' | translate }}</mat-header-cell> <mat-header-cell *matHeaderCellDef>{{ 'Comment' | translate }}</mat-header-cell>
<mat-cell *matCellDef="let history">{{ parseInformation(history) }}</mat-cell> <mat-cell *matCellDef="let history">{{ parseInformation(history) }}</mat-cell>
</ng-container> </ng-container>
<!-- User --> <!-- User -->
<ng-container matColumnDef="user"> <ng-container matColumnDef="user">
<mat-header-cell *matHeaderCellDef>{{ 'Changed by' | translate }}</mat-header-cell> <mat-header-cell *matHeaderCellDef>{{ 'Changed by' | translate }}</mat-header-cell>
<mat-cell *matCellDef="let history">{{ getUserName(history) }}</mat-cell> <mat-cell *matCellDef="let history">{{ getUserName(history) }}</mat-cell>
</ng-container> </ng-container>
<mat-header-row *matHeaderRowDef="getRowDef()"></mat-header-row> <mat-header-row *matHeaderRowDef="getRowDef()"></mat-header-row>
<mat-row *matRowDef="let row; columns: getRowDef()" (click)="onClickRow(row)"></mat-row> <mat-row *matRowDef="let row; columns: getRowDef()" (click)="onClickRow(row)"></mat-row>
</mat-table> </mat-table>
<mat-paginator [pageSizeOptions]="pageSizes"></mat-paginator> <mat-paginator [pageSizeOptions]="pageSizes"></mat-paginator>
</mat-card>
<mat-menu #historyMenu="matMenu"> <mat-menu #historyMenu="matMenu">
<button mat-menu-item class="red-warning-text" (click)="clearHistory()"> <button mat-menu-item class="red-warning-text" (click)="clearHistory()">

View File

@ -1,13 +1,16 @@
.no-info { .no-info {
font-style: italic; font-style: italic;
color: slategray; // TODO: Colors per theme
} }
.custom-table-header { .history-table-header {
display: flex;
justify-content: space-between; justify-content: space-between;
text-align: left; }
& > div { .os-headed-listview-table {
padding: 0 20px; .mat-header-cell,
.mat-cell {
padding-left: 5px;
padding-right: 5px;
} }
} }

View File

@ -82,7 +82,7 @@
<!-- the actual file manager --> <!-- the actual file manager -->
<pbl-ngrid <pbl-ngrid
class="virtual-scroll-with-head-bar ngrid-hide-head file-manager-table" class="file-manager-table"
showHeader="false" showHeader="false"
vScrollAuto vScrollAuto
[dataSource]="dataSource" [dataSource]="dataSource"

View File

@ -51,6 +51,9 @@ $navbar-size: 64px;
} }
.file-manager-table { .file-manager-table {
display: block;
height: calc(100vh - 130px);
.file-title { .file-title {
font-weight: 500; font-weight: 500;
font-size: 16px; font-size: 16px;
@ -68,4 +71,8 @@ $navbar-size: 64px;
height: $size !important; height: $size !important;
} }
} }
.pbl-ngrid-row:last-of-type {
margin-bottom: 60px !important;
}
} }

View File

@ -1,22 +1 @@
@import '~assets/styles/tables.scss'; @import '~assets/styles/tables.scss';
.os-headed-listview-table {
// Title
.mat-column-title {
flex: 9 0 0;
}
// Amount
.mat-column-amount {
flex: 1 0 60px;
}
// Menu
.mat-column-menu {
flex: 0 0 40px;
}
}
.mat-cell > div {
z-index: 1 !important;
}

View File

@ -6,7 +6,6 @@
</os-head-bar> </os-head-bar>
<os-list-view-table <os-list-view-table
class="block-list"
[vScrollFixed]="64" [vScrollFixed]="64"
[listObservableProvider]="repo" [listObservableProvider]="repo"
[showFilterBar]="true" [showFilterBar]="true"

View File

@ -1,13 +1,5 @@
@import '~assets/styles/tables.scss'; @import '~assets/styles/tables.scss';
.block-list {
display: block;
.virtual-scroll-full-page {
height: calc(100vh - 150px);
}
}
.mat-dialog-container { .mat-dialog-container {
.mat-dialog-title { .mat-dialog-title {
margin: 0; margin: 0;

View File

@ -115,7 +115,7 @@
</mat-menu> </mat-menu>
</os-head-bar> </os-head-bar>
<div class="content-container" (touchstart)="swipe($event, 'start')" (touchend)="swipe($event, 'end')"> <div class="content-container spacer-bottom-60" (touchstart)="swipe($event, 'start')" (touchend)="swipe($event, 'end')">
<!-- Title --> <!-- Title -->
<div class="title" *ngIf="motion && !editMotion"> <div class="title" *ngIf="motion && !editMotion">
<div class="title-line"> <div class="title-line">

View File

@ -10,7 +10,7 @@
</div> </div>
</os-head-bar> </os-head-bar>
<mat-card class="os-card"> <mat-card class="os-card spacer-bottom-60">
<ng-container [ngTemplateOutlet]="viewTemplate"></ng-container> <ng-container [ngTemplateOutlet]="viewTemplate"></ng-container>
</mat-card> </mat-card>
@ -40,6 +40,7 @@
<h2>{{ 'Single votes' | translate }}</h2> <h2>{{ 'Single votes' | translate }}</h2>
<os-list-view-table <os-list-view-table
*ngIf="votesDataObservable" *ngIf="votesDataObservable"
class="single-votes-table"
[listObservable]="votesDataObservable" [listObservable]="votesDataObservable"
[columns]="columnDefinition" [columns]="columnDefinition"
[filterProps]="filterProps" [filterProps]="filterProps"
@ -47,7 +48,6 @@
[fullScreen]="true" [fullScreen]="true"
[vScrollFixed]="-1" [vScrollFixed]="-1"
listStorageKey="motion-poll-vote" listStorageKey="motion-poll-vote"
[cssClasses]="{ 'single-votes-table': true }"
> >
<!-- Header --> <!-- Header -->
<div *pblNgridHeaderCellDef="'*'; col as col"> <div *pblNgridHeaderCellDef="'*'; col as col">

View File

@ -26,7 +26,12 @@
} }
.single-votes-table { .single-votes-table {
display: block;
height: 500px; height: 500px;
.list-view-frame {
height: 100%;
}
} }
.openslides-theme .pbl-ngrid-no-data { .openslides-theme .pbl-ngrid-no-data {

View File

@ -1,14 +0,0 @@
.os-headed-listview-table {
/** name */
.mat-column-name {
width: 100%;
flex: 1 0 200px;
padding-left: 10px;
}
/** delete */
.mat-column-delete {
flex: 0 0 190px;
justify-content: flex-end !important;
}
}

View File

@ -12,30 +12,32 @@
</div> </div>
</os-head-bar> </os-head-bar>
<cdk-virtual-scroll-viewport itemSize="50" [ngClass]="statuteParagraphs.length ? 'virtual-scroll-full-page' : ''"> <cdk-virtual-scroll-viewport class="statute-vscroll-wrapper" itemSize="50">
<mat-accordion class="os-card"> <mat-card>
<mat-expansion-panel *cdkVirtualFor="let statuteParagraph of statuteParagraphs" multiple="false"> <mat-accordion>
<mat-expansion-panel-header> <mat-expansion-panel *cdkVirtualFor="let statuteParagraph of statuteParagraphs" multiple="false">
<mat-panel-title> <mat-expansion-panel-header>
{{ statuteParagraph.title }} <mat-panel-title>
</mat-panel-title> {{ statuteParagraph.title }}
</mat-expansion-panel-header> </mat-panel-title>
<mat-card> </mat-expansion-panel-header>
<mat-card-title>{{ statuteParagraph.title }}</mat-card-title> <mat-card>
<mat-card-content> <mat-card-title>{{ statuteParagraph.title }}</mat-card-title>
<div [innerHTML]="statuteParagraph.text | trust: 'html'"></div> <mat-card-content>
</mat-card-content> <div [innerHTML]="statuteParagraph.text | trust: 'html'"></div>
</mat-card> </mat-card-content>
<mat-action-row> </mat-card>
<button mat-button mat-icon-button (click)="openDialog(statuteParagraph)"> <mat-action-row>
<mat-icon>edit</mat-icon> <button mat-button mat-icon-button (click)="openDialog(statuteParagraph)">
</button> <mat-icon>edit</mat-icon>
<button mat-button mat-icon-button (click)="onDeleteButton(statuteParagraph)"> </button>
<mat-icon>delete</mat-icon> <button mat-button mat-icon-button (click)="onDeleteButton(statuteParagraph)">
</button> <mat-icon>delete</mat-icon>
</mat-action-row> </button>
</mat-expansion-panel> </mat-action-row>
</mat-accordion> </mat-expansion-panel>
</mat-accordion>
</mat-card>
</cdk-virtual-scroll-viewport> </cdk-virtual-scroll-viewport>
<mat-card *ngIf="statuteParagraphs.length === 0"> <mat-card *ngIf="statuteParagraphs.length === 0">

View File

@ -1,16 +1,11 @@
.head-spacer { .statute-vscroll-wrapper {
width: 100%; height: calc(100vh - 64px);
height: 60px;
line-height: 60px;
text-align: right;
background: white; /* TODO: remove this and replace with theme */
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}
mat-card { .mat-card {
margin-bottom: 20px; margin-bottom: 20px;
mat-form-field { .mat-form-field {
width: 100%; width: 100%;
}
} }
} }

View File

@ -1,4 +1,6 @@
<div *ngIf="poll" class="poll-progress-wrapper"> out of poll
<div class="poll-progress-wrapper">
in the poll
<div class="vote-number"> <div class="vote-number">
<span>{{ votescast }} / {{ max }}</span> <span>{{ votescast }} / {{ max }}</span>
</div> </div>

View File

@ -95,9 +95,7 @@
</main> </main>
</div> </div>
<div class="toolbars"> <div class="toolbars">
<!-- test -->
<os-jitsi></os-jitsi> <os-jitsi></os-jitsi>
<!-- <os-live-stream></os-live-stream> -->
</div> </div>
</mat-sidenav-content> </mat-sidenav-content>
</mat-sidenav-container> </mat-sidenav-container>

View File

@ -122,12 +122,11 @@ mat-sidenav-container {
position: relative; position: relative;
main { main {
position: absolute;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;
position: relative;
z-index: 50; z-index: 50;
flex: 1;
> *:not(router-outlet) { > *:not(router-outlet) {
flex: 1; flex: 1;
display: block; display: block;

View File

@ -5,53 +5,54 @@
</div> </div>
</os-head-bar> </os-head-bar>
<div class="hint-text"> <mat-card class="spacer-bottom-60">
<span>{{ 'All your changes are saved immediately.' | translate }}</span> <div class="hint-text">
</div> <span>{{ 'All your changes are saved immediately.' | translate }}</span>
</div>
<mat-accordion *ngFor="let app of appPermissions">
<mat-expansion-panel class="mat-elevation-z0" [expanded]="true">
<mat-expansion-panel-header>
<mat-panel-title>
{{ app.name | translate }}
</mat-panel-title>
</mat-expansion-panel-header>
<mat-accordion *ngFor="let app of appPermissions"> <div class="scrollable-perm-matrix">
<mat-expansion-panel class="mat-elevation-z0" [expanded]="true"> <table mat-table [dataSource]="getTableDataSource(app.permissions)">
<mat-expansion-panel-header> <ng-container matColumnDef="perm" sticky>
<mat-panel-title> <mat-header-cell *matHeaderCellDef>{{ 'Permissions' | translate }}</mat-header-cell>
{{ app.name | translate }}
</mat-panel-title>
</mat-expansion-panel-header>
<div class="scrollable-perm-matrix">
<table mat-table [dataSource]="getTableDataSource(app.permissions)">
<ng-container matColumnDef="perm" sticky>
<mat-header-cell *matHeaderCellDef>{{ 'Permissions' | translate }}</mat-header-cell>
<mat-cell *matCellDef="let perm">
{{ perm.display_name | translate }}
</mat-cell>
</ng-container>
<div *ngFor="let group of groups; trackBy: trackByIndex">
<ng-container [matColumnDef]="group.name">
<mat-header-cell class="group-head-table-cell" *matHeaderCellDef (click)="selectGroup(group)">
<div class="inner-table">
{{ group.name | translate }}
</div>
</mat-header-cell>
<mat-cell *matCellDef="let perm"> <mat-cell *matCellDef="let perm">
<div class="inner-table"> {{ perm.display_name | translate }}
<mat-checkbox
*ngIf="group.id !== 2"
[checked]="group.hasPermission(perm.value)"
(change)="togglePerm(group, perm.value)"
></mat-checkbox>
<mat-checkbox *ngIf="group.id === 2" [checked]="true" [disabled]="true"></mat-checkbox>
</div>
</mat-cell> </mat-cell>
</ng-container> </ng-container>
</div>
<mat-header-row *matHeaderRowDef="headerRowDef"></mat-header-row> <div *ngFor="let group of groups; trackBy: trackByIndex">
<mat-row *matRowDef="let row; columns: headerRowDef"></mat-row> <ng-container [matColumnDef]="group.name">
</table> <mat-header-cell class="group-head-table-cell" *matHeaderCellDef (click)="selectGroup(group)">
</div> <div class="inner-table">
</mat-expansion-panel> {{ group.name | translate }}
</mat-accordion> </div>
</mat-header-cell>
<mat-cell *matCellDef="let perm">
<div class="inner-table">
<mat-checkbox
*ngIf="group.id !== 2"
[checked]="group.hasPermission(perm.value)"
(change)="togglePerm(group, perm.value)"
></mat-checkbox>
<mat-checkbox *ngIf="group.id === 2" [checked]="true" [disabled]="true"></mat-checkbox>
</div>
</mat-cell>
</ng-container>
</div>
<mat-header-row *matHeaderRowDef="headerRowDef"></mat-header-row>
<mat-row *matRowDef="let row; columns: headerRowDef"></mat-row>
</table>
</div>
</mat-expansion-panel>
</mat-accordion>
</mat-card>
<ng-template #groupEditDialog> <ng-template #groupEditDialog>
<h1 mat-dialog-title> <h1 mat-dialog-title>

View File

@ -20,7 +20,7 @@ table {
} }
.hint-text { .hint-text {
padding-top: 30px; padding-top: 1em;
padding-left: 25px; padding-left: 25px;
} }

View File

@ -309,11 +309,6 @@ b,
@extend %os-table; @extend %os-table;
} }
/* TODO: find a better way to get more vertical space in (empty/small) tables for maximize filter dialog */
.mat-paginator {
min-height: 800px;
}
/* hide scrollbars caused by hidden filter dialog outside of the viewport */ /* hide scrollbars caused by hidden filter dialog outside of the viewport */
.mat-drawer-content { .mat-drawer-content {
overflow-x: hidden !important; overflow-x: hidden !important;
@ -447,6 +442,10 @@ button.mat-menu-item.selected {
margin-bottom: 40px !important; margin-bottom: 40px !important;
} }
.spacer-bottom-60 {
margin-bottom: 60px !important;
}
.spacer-left-10 { .spacer-left-10 {
margin-left: 10px; margin-left: 10px;
} }
@ -499,19 +498,6 @@ button.mat-menu-item.selected {
} }
} }
/**
* cdk-virtual-scroll-viewport requires a hight, otherwise it would always be 0
* Depending in mobile-mode and desktop mode we need to subtract different values
* from 100vh
*/
.virtual-scroll-full-page {
height: calc(100vh - 64px);
}
.virtual-scroll-with-head-bar {
height: calc(100vh - 129px);
}
/** css hacks https://codepen.io/edge0703/pen/iHJuA */ /** css hacks https://codepen.io/edge0703/pen/iHJuA */
.innerTable { .innerTable {
display: inline-block; display: inline-block;
@ -519,12 +505,13 @@ button.mat-menu-item.selected {
width: -webkit-fill-available; width: -webkit-fill-available;
} }
.ngrid-hide-head { /**
// For some reason, hiding the table header adds an empty meta bar. * Compilcated ngrid hack: The meta row won't disappear (just like that)
.pbl-ngrid-container { * Select the first ever container pbl-ngrid-container div and hide
> div { */
height: 0; .pbl-ngrid-container {
} > div {
height: 0;
} }
} }