enhance motion tables with observer
This commit is contained in:
parent
8cfb5bf597
commit
0099c34615
1
.gitignore
vendored
1
.gitignore
vendored
@ -65,6 +65,7 @@ client/node_modules
|
|||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
|
Compodoc
|
||||||
client/.sass-cache
|
client/.sass-cache
|
||||||
client/connect.lock
|
client/connect.lock
|
||||||
client/coverage
|
client/coverage
|
||||||
|
@ -13,7 +13,8 @@ import {
|
|||||||
MatSidenavModule,
|
MatSidenavModule,
|
||||||
MatSnackBarModule,
|
MatSnackBarModule,
|
||||||
MatTableModule,
|
MatTableModule,
|
||||||
MatPaginatorModule
|
MatPaginatorModule,
|
||||||
|
MatSortModule
|
||||||
} from '@angular/material';
|
} from '@angular/material';
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
import { MatListModule } from '@angular/material/list';
|
import { MatListModule } from '@angular/material/list';
|
||||||
@ -33,6 +34,7 @@ import { OsPermsDirective } from './directives/os-perms.directive';
|
|||||||
import { DomChangeDirective } from './directives/dom-change.directive';
|
import { DomChangeDirective } from './directives/dom-change.directive';
|
||||||
import { LegalnoticeDialogComponent } from './components/legal-notice/legal-notice.dialog.component';
|
import { LegalnoticeDialogComponent } from './components/legal-notice/legal-notice.dialog.component';
|
||||||
import { PrivacyPolicyDialogComponent } from './components/privacy-policy/privacy-policy.dialog.component';
|
import { PrivacyPolicyDialogComponent } from './components/privacy-policy/privacy-policy.dialog.component';
|
||||||
|
// import { CdkTableModule } from '@angular/cdk/table';
|
||||||
|
|
||||||
library.add(fas);
|
library.add(fas);
|
||||||
|
|
||||||
@ -56,6 +58,7 @@ library.add(fas);
|
|||||||
MatCardModule,
|
MatCardModule,
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
MatTableModule,
|
MatTableModule,
|
||||||
|
MatSortModule,
|
||||||
MatPaginatorModule,
|
MatPaginatorModule,
|
||||||
MatProgressSpinnerModule,
|
MatProgressSpinnerModule,
|
||||||
MatSidenavModule,
|
MatSidenavModule,
|
||||||
@ -75,6 +78,7 @@ library.add(fas);
|
|||||||
MatCardModule,
|
MatCardModule,
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
MatTableModule,
|
MatTableModule,
|
||||||
|
MatSortModule,
|
||||||
MatPaginatorModule,
|
MatPaginatorModule,
|
||||||
MatProgressSpinnerModule,
|
MatProgressSpinnerModule,
|
||||||
MatSidenavModule,
|
MatSidenavModule,
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
||||||
|
|
||||||
<div class='custom-table-header'>
|
<div class='custom-table-header on-transition-fade'>
|
||||||
<button mat-button>
|
<button mat-button>
|
||||||
SORIEREN NACH
|
SORIEREN NACH
|
||||||
</button>
|
</button>
|
||||||
@ -23,43 +23,47 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table mat-table [dataSource]="dataSource" matSort>
|
<mat-table class='on-transition-fade' [dataSource]="dataSource" matSort>
|
||||||
<!-- identifier column -->
|
<!-- identifier column -->
|
||||||
<ng-container matColumnDef="identifier">
|
<ng-container matColumnDef="identifier">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Bezeichner </th>
|
<mat-header-cell *matHeaderCellDef mat-sort-header> Bezeichner </mat-header-cell>
|
||||||
<td mat-cell *matCellDef="let motion">
|
<mat-cell *matCellDef="let motion">
|
||||||
<span>
|
<div class='innerTable'>
|
||||||
{{motion.identifier}}
|
{{motion.identifier}}
|
||||||
</span>
|
</div>
|
||||||
</td>
|
</mat-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- title column -->
|
<!-- title column -->
|
||||||
<ng-container matColumnDef="title">
|
<ng-container matColumnDef="title">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Titel </th>
|
<mat-header-cell *matHeaderCellDef mat-sort-header> Titel </mat-header-cell>
|
||||||
<td mat-cell *matCellDef="let motion">
|
<mat-cell *matCellDef="let motion">
|
||||||
<span class='motion-list-title'>{{motion.versions[0].title}}</span>
|
<div class='innerTable'>
|
||||||
<br>
|
<span class='motion-list-title'>{{motion.versions[0].title}}</span>
|
||||||
<span class='motion-list-from'>
|
<br>
|
||||||
<span translate>von</span>
|
<span class='motion-list-from'>
|
||||||
{{motion.submitterAsUser.username}}
|
<span translate>von</span>
|
||||||
</span>
|
{{motion.submitterAsUser.username}}
|
||||||
</td>
|
</span>
|
||||||
|
</div>
|
||||||
|
</mat-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- state column -->
|
<!-- state column -->
|
||||||
<ng-container matColumnDef="state">
|
<ng-container matColumnDef="state">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Status </th>
|
<mat-header-cell *matHeaderCellDef mat-sort-header> Status </mat-header-cell>
|
||||||
<td mat-cell *matCellDef="let motion">
|
<mat-cell *matCellDef="let motion">
|
||||||
<fa-icon icon={{getStateIcon(motion.stateName)}}></fa-icon>
|
<div class='innerTable'>
|
||||||
<!-- <span class='motion.list.state'>
|
<fa-icon icon={{getStateIcon(motion.stateName)}}></fa-icon>
|
||||||
{{motion.stateName}}
|
<!-- <span class='motion.list.state'>
|
||||||
</span> -->
|
{{motion.stateName}}
|
||||||
</td>
|
</span> -->
|
||||||
|
</div>
|
||||||
|
</mat-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="columnsToDisplayMinWidth"></tr>
|
<mat-header-row *matHeaderRowDef="columnsToDisplayMinWidth"></mat-header-row>
|
||||||
<tr mat-row *matRowDef="let row; columns: columnsToDisplayMinWidth"></tr>
|
<mat-row (click)='selectMotion(row)' *matRowDef="let row; columns: columnsToDisplayMinWidth"></mat-row>
|
||||||
</table>
|
</mat-table>
|
||||||
|
|
||||||
<mat-paginator [pageSizeOptions]="[20, 40, 60, 80]"></mat-paginator>
|
<mat-paginator class="on-transition-fade" [pageSizeOptions]="[20, 40, 60, 80]"></mat-paginator>
|
@ -1,68 +1,67 @@
|
|||||||
table {
|
|
||||||
/* margin-top: 40px; */
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** identifier */
|
|
||||||
.mat-column-identifier {
|
|
||||||
padding-left: 10px !important;
|
|
||||||
padding-right: 10px !important;
|
|
||||||
text-align: center;
|
|
||||||
flex: 0 0 70px !important;
|
|
||||||
|
|
||||||
span {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Title */
|
|
||||||
.mat-column-title {
|
|
||||||
width: 100%;
|
|
||||||
flex: 5 0 100 !important;
|
|
||||||
padding-left: 10px;
|
|
||||||
|
|
||||||
.motion-list-title {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.motion-list-from {
|
|
||||||
display: block;
|
|
||||||
margin-top: 5px;
|
|
||||||
color: rgba(0, 0, 0, 0.5);
|
|
||||||
font-size: 90%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** State */
|
|
||||||
.mat-column-state {
|
|
||||||
flex: 0 0 30 !important;
|
|
||||||
|
|
||||||
fa-icon {
|
|
||||||
font-size: 150%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** has to be in the theme also */
|
|
||||||
|
|
||||||
/** hide mat header row */
|
|
||||||
.mat-header-row {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** size of the mat row */
|
|
||||||
.mat-row {
|
|
||||||
height: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-table-header {
|
.custom-table-header {
|
||||||
/* display: inline-block; */
|
// display: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
line-height: 60px;
|
line-height: 60px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
/* vertical-align: middle; */
|
|
||||||
/** has to be in the theme */
|
|
||||||
background: white;
|
background: white;
|
||||||
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** css hacks https://codepen.io/edge0703/pen/iHJuA */
|
||||||
|
.innerTable {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-table {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
/** hide mat header row */
|
||||||
|
.mat-header-row {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** size of the mat row */
|
||||||
|
mat-row {
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** identifier */
|
||||||
|
.mat-column-identifier {
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 30px;
|
||||||
|
flex: 0 0 40px;
|
||||||
|
line-height: 60px; // set the text in the vertical middle, since vertical-align will not work
|
||||||
|
display: initial; // reset display
|
||||||
|
text-align: center; // center text
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Title */
|
||||||
|
.mat-column-title {
|
||||||
|
width: 100%;
|
||||||
|
flex: 1 0 200px;
|
||||||
|
padding-left: 10px;
|
||||||
|
|
||||||
|
.motion-list-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.motion-list-from {
|
||||||
|
margin-top: 5px;
|
||||||
|
color: rgba(0, 0, 0, 0.5);
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** State */
|
||||||
|
.mat-column-state {
|
||||||
|
flex: 0 0 30px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
fa-icon {
|
||||||
|
font-size: 150%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,63 +3,82 @@ import { Title } from '@angular/platform-browser';
|
|||||||
import { BaseComponent } from 'app/base.component';
|
import { BaseComponent } from 'app/base.component';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { Motion } from '../../../shared/models/motions/motion';
|
import { Motion } from '../../../shared/models/motions/motion';
|
||||||
import { MatPaginator, MatSort, MatTableDataSource } from '@angular/material';
|
import { MatTable, MatPaginator, MatSort, MatTableDataSource } from '@angular/material';
|
||||||
import { Workflow } from '../../../shared/models/motions/workflow';
|
import { Workflow } from '../../../shared/models/motions/workflow';
|
||||||
|
|
||||||
export interface PeriodicElement {
|
|
||||||
state_id: string;
|
|
||||||
identifier: number;
|
|
||||||
weight: number;
|
|
||||||
symbol: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ELEMENT_DATA: PeriodicElement[] = [
|
|
||||||
{ identifier: 1, state_id: 'Hydrogen', weight: 1.0079, symbol: 'H' },
|
|
||||||
{ identifier: 2, state_id: 'Helium', weight: 4.0026, symbol: 'He' },
|
|
||||||
{ identifier: 3, state_id: 'Lithium', weight: 6.941, symbol: 'Li' },
|
|
||||||
{ identifier: 4, state_id: 'Beryllium', weight: 9.0122, symbol: 'Be' },
|
|
||||||
{ identifier: 5, state_id: 'Boron', weight: 10.811, symbol: 'B' },
|
|
||||||
{ identifier: 6, state_id: 'Carbon', weight: 12.0107, symbol: 'C' },
|
|
||||||
{ identifier: 7, state_id: 'Nitrogen', weight: 14.0067, symbol: 'N' },
|
|
||||||
{ identifier: 8, state_id: 'Oxygen', weight: 15.9994, symbol: 'O' },
|
|
||||||
{ identifier: 9, state_id: 'Fluorine', weight: 18.9984, symbol: 'F' },
|
|
||||||
{ identifier: 10, state_id: 'Neon', weight: 20.1797, symbol: 'Ne' }
|
|
||||||
];
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-motion-list',
|
selector: 'app-motion-list',
|
||||||
templateUrl: './motion-list.component.html',
|
templateUrl: './motion-list.component.html',
|
||||||
styleUrls: ['./motion-list.component.scss']
|
styleUrls: ['./motion-list.component.scss']
|
||||||
})
|
})
|
||||||
export class MotionListComponent extends BaseComponent implements OnInit {
|
export class MotionListComponent extends BaseComponent implements OnInit {
|
||||||
|
/**
|
||||||
|
* Store motion workflows (to check the status of the motions)
|
||||||
|
*/
|
||||||
workflowArray: Array<Workflow>;
|
workflowArray: Array<Workflow>;
|
||||||
motionArray: Array<Motion>;
|
|
||||||
dataSource: MatTableDataSource<Motion>;
|
|
||||||
// dataSource: MatTableDataSource<any>;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the motions
|
||||||
|
*/
|
||||||
|
motionArray: Array<Motion>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will be processed by the mat-table
|
||||||
|
*/
|
||||||
|
dataSource: MatTableDataSource<Motion>;
|
||||||
|
|
||||||
|
@ViewChild(MatTable) table: MatTable<Motion>;
|
||||||
@ViewChild(MatPaginator) paginator: MatPaginator;
|
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||||
@ViewChild(MatSort) sort: MatSort;
|
@ViewChild(MatSort) sort: MatSort;
|
||||||
|
|
||||||
/** which colummns to display in the table */
|
/**
|
||||||
|
* Use for minimal width
|
||||||
|
*/
|
||||||
columnsToDisplayMinWidth = ['identifier', 'title', 'state'];
|
columnsToDisplayMinWidth = ['identifier', 'title', 'state'];
|
||||||
// columnsToDisplayMinWidth = ['title'];
|
/**
|
||||||
|
* Use for maximal width
|
||||||
|
*/
|
||||||
columnsToDisplayFullWidth = ['identifier', 'title', 'meta', 'state'];
|
columnsToDisplayFullWidth = ['identifier', 'title', 'meta', 'state'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor implements title and translation Module.
|
||||||
|
* @param titleService
|
||||||
|
* @param translate
|
||||||
|
*/
|
||||||
constructor(titleService: Title, protected translate: TranslateService) {
|
constructor(titleService: Title, protected translate: TranslateService) {
|
||||||
super(titleService, translate);
|
super(titleService, translate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init function
|
||||||
|
*/
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
super.setTitle('Motions');
|
super.setTitle('Motions');
|
||||||
|
|
||||||
this.workflowArray = this.DS.get(Workflow) as Workflow[];
|
this.workflowArray = this.DS.get(Workflow) as Workflow[];
|
||||||
this.motionArray = this.DS.get(Motion) as Motion[];
|
this.motionArray = this.DS.get(Motion) as Motion[];
|
||||||
this.dataSource = new MatTableDataSource(this.motionArray);
|
this.dataSource = new MatTableDataSource(this.motionArray);
|
||||||
// this.dataSource = new MatTableDataSource(ELEMENT_DATA);
|
|
||||||
this.dataSource.paginator = this.paginator;
|
this.dataSource.paginator = this.paginator;
|
||||||
this.dataSource.sort = this.sort;
|
this.dataSource.sort = this.sort;
|
||||||
|
|
||||||
|
// Observe DataStore for motions. Initially, executes once for every motion.
|
||||||
|
// The alternative approach is to put the observable as DataSource to the table
|
||||||
|
this.DS.getObservable().subscribe(newModel => {
|
||||||
|
if (newModel instanceof Motion) {
|
||||||
|
this.motionArray.push(newModel as Motion);
|
||||||
|
this.dataSource.data = this.motionArray;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectMotion(motion) {
|
||||||
|
console.log('clicked a row, :', motion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the icon to the coresponding Motion Status
|
||||||
|
* TODO Needs to be more accessible (Motion workflow needs adjustment on the server)
|
||||||
|
* @param stateName the name of the state
|
||||||
|
*/
|
||||||
getStateIcon(stateName) {
|
getStateIcon(stateName) {
|
||||||
if (stateName === 'accepted') {
|
if (stateName === 'accepted') {
|
||||||
return 'thumbs-up';
|
return 'thumbs-up';
|
||||||
@ -70,6 +89,9 @@ export class MotionListComponent extends BaseComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download all motions As PDF and DocX
|
||||||
|
*/
|
||||||
downloadMotionsButton() {
|
downloadMotionsButton() {
|
||||||
console.log('Download Motions Button');
|
console.log('Download Motions Button');
|
||||||
}
|
}
|
||||||
|
@ -39,11 +39,11 @@ export class StartComponent extends BaseComponent implements OnInit {
|
|||||||
* Set title and observe DataStore for changes.
|
* Set title and observe DataStore for changes.
|
||||||
*/
|
*/
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
//required dummy translation, cause translations for config values were never set
|
// required dummy translation, cause translations for config values were never set
|
||||||
const welcomeTitleTranslateDummy = this.translate.instant('Welcome to OpenSlides');
|
const welcomeTitleTranslateDummy = this.translate.instant('Welcome to OpenSlides');
|
||||||
super.setTitle('Home');
|
super.setTitle('Home');
|
||||||
|
|
||||||
//set welcome title and text
|
// set welcome title and text
|
||||||
const welcomeTitleConfig = this.DS.filter(
|
const welcomeTitleConfig = this.DS.filter(
|
||||||
Config,
|
Config,
|
||||||
config => config.key === 'general_event_welcome_title'
|
config => config.key === 'general_event_welcome_title'
|
||||||
@ -63,7 +63,7 @@ export class StartComponent extends BaseComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
console.log(this.DS.filter(Config, config => config.key === 'general_event_welcome_title'));
|
console.log(this.DS.filter(Config, config => config.key === 'general_event_welcome_title'));
|
||||||
|
|
||||||
//observe title and text in DS
|
// observe title and text in DS
|
||||||
this.DS.getObservable().subscribe(newModel => {
|
this.DS.getObservable().subscribe(newModel => {
|
||||||
if (newModel instanceof Config) {
|
if (newModel instanceof Config) {
|
||||||
if (newModel.key === 'general_event_welcome_title') {
|
if (newModel.key === 'general_event_welcome_title') {
|
||||||
|
Loading…
Reference in New Issue
Block a user