First motion list view

This commit is contained in:
Sean Engelhardt 2018-08-08 17:25:39 +02:00 committed by FinnStutzenstein
parent cbb9185c2a
commit e36e4ed655
10 changed files with 344 additions and 135 deletions

View File

@ -0,0 +1,25 @@
import { Deserializable } from '../deserializable.model';
/**
* Representation of a Motion Version.
*
* @ignore
*/
export class MotionLog implements Deserializable {
message_list: string[];
person_id: number;
time: string;
message: string;
constructor(message_list?: string[], person_id?: number, time?: string, message?: string) {
this.message_list = message_list;
this.person_id = person_id;
this.time = time;
this.message = message;
}
deserialize(input: any): this {
Object.assign(this, input);
return this;
}
}

View File

@ -0,0 +1,25 @@
import { Deserializable } from '../deserializable.model';
/**
* Representation of a Motion Submitter.
*
* @ignore
*/
export class MotionSubmitter implements Deserializable {
id: number;
user_id: number;
motion_id: number;
weight: number;
constructor(id?: number, user_id?: number, motion_id?: number, weight?: number) {
this.id = id;
this.user_id = user_id;
this.motion_id = motion_id;
this.weight = weight;
}
deserialize(input: any): this {
Object.assign(this, input);
return this;
}
}

View File

@ -0,0 +1,39 @@
import { Deserializable } from '../deserializable.model';
/**
* Representation of a Motion Version.
*
* @ignore
*/
export class MotionVersion implements Deserializable {
id: number;
version_number: number;
creation_time: string;
title: string;
text: string;
amendment_paragraphs: string;
reason: string;
constructor(
id?: number,
version_number?: number,
creation_time?: string,
title?: string,
text?: string,
amendment_paragraphs?: string,
reason?: string
) {
this.id = id;
this.version_number = version_number;
this.creation_time = creation_time;
this.title = title;
this.text = text;
this.amendment_paragraphs = amendment_paragraphs;
this.reason = reason;
}
deserialize(input: any): this {
Object.assign(this, input);
return this;
}
}

View File

@ -1,9 +1,14 @@
import { BaseModel } from '../base.model'; import { BaseModel } from '../base.model';
import { MotionVersion } from './motion-version';
import { MotionSubmitter } from './motion-submitter';
import { MotionLog } from './motion-log';
import { Config } from '../core/config';
import { Workflow } from './workflow';
/** /**
* Representation of Motion. * Representation of Motion.
* *
* Untouched for now because of heavy maintainance on server side * Slightly Defined cause heavy maintaince on server side.
* *
* @ignore * @ignore
*/ */
@ -11,13 +16,13 @@ export class Motion extends BaseModel {
protected _collectionString: string; protected _collectionString: string;
id: number; id: number;
identifier: string; identifier: string;
versions: Object[]; versions: MotionVersion[];
active_version: number; active_version: number;
parent_id: number; parent_id: number;
category_id: number; category_id: number;
motion_block_id: number; motion_block_id: number;
origin: string; origin: string;
submitters: Object[]; submitters: MotionSubmitter[];
supporters_id: number[]; supporters_id: number[];
comments: Object; comments: Object;
state_id: number; state_id: number;
@ -27,18 +32,18 @@ export class Motion extends BaseModel {
attachments_id: number[]; attachments_id: number[];
polls: BaseModel[]; polls: BaseModel[];
agenda_item_id: number; agenda_item_id: number;
log_messages: Object[]; log_messages: MotionLog[];
constructor( constructor(
id?: number, id?: number,
identifier?: string, identifier?: string,
versions?: Object[], versions?: MotionVersion[],
active_version?: number, active_version?: number,
parent_id?: number, parent_id?: number,
category_id?: number, category_id?: number,
motion_block_id?: number, motion_block_id?: number,
origin?: string, origin?: string,
submitters?: Object[], submitters?: MotionSubmitter[],
supporters_id?: number[], supporters_id?: number[],
comments?: Object, comments?: Object,
state_id?: number, state_id?: number,
@ -48,7 +53,7 @@ export class Motion extends BaseModel {
attachments_id?: number[], attachments_id?: number[],
polls?: BaseModel[], polls?: BaseModel[],
agenda_item_id?: number, agenda_item_id?: number,
log_messages?: Object[] log_messages?: MotionLog[]
) { ) {
super(); super();
this._collectionString = 'motions/motion'; this._collectionString = 'motions/motion';
@ -72,4 +77,58 @@ export class Motion extends BaseModel {
this.agenda_item_id = agenda_item_id; this.agenda_item_id = agenda_item_id;
this.log_messages = log_messages; this.log_messages = log_messages;
} }
/**
* return the submitters as uses objects
*/
get submitterAsUser() {
const submitterIds = [];
this.submitters.forEach(submitter => {
submitterIds.push(submitter.user_id);
});
const users = this.DS.get('users/user', ...submitterIds);
return users;
}
/**
* return the workflow state
*
* Right now only the default workflow is assumes
*/
get stateName() {
//get the default workflow
const motionsWorkflowConfig = this.DS.filter(Config, config => config.key === 'motions_workflow')[0] as Config;
//make sure this is a number
const workflowId = +motionsWorkflowConfig.value;
//get the workflow for out motion
const selectedWorkflow = this.DS.get(Workflow, workflowId) as Workflow;
return selectedWorkflow.getStateNameById(this.state_id);
}
deserialize(input: any): this {
Object.assign(this, input);
if (input.versions instanceof Array) {
this.versions = [];
input.versions.forEach(motionVersionData => {
this.versions.push(new MotionVersion().deserialize(motionVersionData));
});
}
if (input.submitters instanceof Array) {
this.submitters = [];
input.submitters.forEach(SubmitterData => {
this.submitters.push(new MotionSubmitter().deserialize(SubmitterData));
});
}
if (input.log_messages instanceof Array) {
this.log_messages = [];
input.log_messages.forEach(logData => {
this.log_messages.push(new MotionLog().deserialize(logData));
});
}
return this;
}
} }

View File

@ -21,6 +21,16 @@ export class Workflow extends BaseModel {
this.first_state = first_state; this.first_state = first_state;
} }
getStateNameById(id: number): string {
let stateName = 'NULL';
this.states.forEach(state => {
if (id === state.id) {
stateName = state.name;
}
});
return stateName;
}
deserialize(input: any): this { deserialize(input: any): this {
Object.assign(this, input); Object.assign(this, input);
if (input.states instanceof Array) { if (input.states instanceof Array) {

View File

@ -11,7 +11,9 @@ import {
MatInputModule, MatInputModule,
MatProgressSpinnerModule, MatProgressSpinnerModule,
MatSidenavModule, MatSidenavModule,
MatSnackBarModule MatSnackBarModule,
MatTableModule,
MatPaginatorModule
} 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';
@ -53,6 +55,8 @@ library.add(fas);
MatToolbarModule, MatToolbarModule,
MatCardModule, MatCardModule,
MatInputModule, MatInputModule,
MatTableModule,
MatPaginatorModule,
MatProgressSpinnerModule, MatProgressSpinnerModule,
MatSidenavModule, MatSidenavModule,
MatListModule, MatListModule,
@ -70,6 +74,8 @@ library.add(fas);
MatToolbarModule, MatToolbarModule,
MatCardModule, MatCardModule,
MatInputModule, MatInputModule,
MatTableModule,
MatPaginatorModule,
MatProgressSpinnerModule, MatProgressSpinnerModule,
MatSidenavModule, MatSidenavModule,
MatListModule, MatListModule,

View File

@ -14,128 +14,52 @@
</mat-toolbar> </mat-toolbar>
<mat-card class="os-card card-plus-distance"> <div class='custom-table-header'>
<div class="app-content"> <button mat-button>
Motion Works SORIEREN NACH
</button>
<button mat-button>
FILTER
</button>
</div> </div>
</mat-card>
<mat-card class="os-card card-plus-distance"> <table mat-table [dataSource]="dataSource" matSort>
<div class="app-content"> <!-- identifier column -->
Motion Works <ng-container matColumnDef="identifier">
</div> <th mat-header-cell *matHeaderCellDef mat-sort-header> Bezeichner </th>
</mat-card> <td mat-cell *matCellDef="let motion">
<mat-card class="os-card card-plus-distance"> <span>
<div class="app-content"> {{motion.identifier}}
Motion Works </span>
</div> </td>
</mat-card> </ng-container>
<mat-card class="os-card card-plus-distance">
<div class="app-content"> <!-- title column -->
Motion Works <ng-container matColumnDef="title">
</div> <th mat-header-cell *matHeaderCellDef mat-sort-header> Titel </th>
</mat-card> <td mat-cell *matCellDef="let motion">
<mat-card class="os-card card-plus-distance"> <span class='motion-list-title'>{{motion.versions[0].title}}</span>
<div class="app-content"> <br>
Motion Works <span class='motion-list-from'>
</div> <span translate>von</span>
</mat-card> {{motion.submitterAsUser.username}}
<mat-card class="os-card card-plus-distance"> </span>
<div class="app-content"> </td>
Motion Works </ng-container>
</div>
</mat-card> <!-- state column -->
<mat-card class="os-card card-plus-distance"> <ng-container matColumnDef="state">
<div class="app-content"> <th mat-header-cell *matHeaderCellDef mat-sort-header> Status </th>
Motion Works <td mat-cell *matCellDef="let motion">
</div> <fa-icon icon={{getStateIcon(motion.stateName)}}></fa-icon>
</mat-card> <!-- <span class='motion.list.state'>
<mat-card class="os-card card-plus-distance"> {{motion.stateName}}
<div class="app-content"> </span> -->
Motion Works </td>
</div> </ng-container>
</mat-card>
<mat-card class="os-card card-plus-distance"> <tr mat-header-row *matHeaderRowDef="columnsToDisplayMinWidth"></tr>
<div class="app-content"> <tr mat-row *matRowDef="let row; columns: columnsToDisplayMinWidth"></tr>
Motion Works </table>
</div>
</mat-card> <mat-paginator [pageSizeOptions]="[20, 40, 60, 80]"></mat-paginator>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>
<mat-card class="os-card card-plus-distance">
<div class="app-content">
Motion Works
</div>
</mat-card>

View File

@ -0,0 +1,68 @@
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 {
/* display: inline-block; */
width: 100%;
height: 60px;
line-height: 60px;
text-align: right;
/* vertical-align: middle; */
/** has to be in the theme */
background: white;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}

View File

@ -1,20 +1,73 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit, ViewChild } from '@angular/core';
import { Title } from '@angular/platform-browser'; 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 { MatPaginator, MatSort, MatTableDataSource } from '@angular/material';
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.css'] styleUrls: ['./motion-list.component.scss']
}) })
export class MotionListComponent extends BaseComponent implements OnInit { export class MotionListComponent extends BaseComponent implements OnInit {
workflowArray: Array<Workflow>;
motionArray: Array<Motion>;
dataSource: MatTableDataSource<Motion>;
// dataSource: MatTableDataSource<any>;
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
/** which colummns to display in the table */
columnsToDisplayMinWidth = ['identifier', 'title', 'state'];
// columnsToDisplayMinWidth = ['title'];
columnsToDisplayFullWidth = ['identifier', 'title', 'meta', 'state'];
constructor(titleService: Title, protected translate: TranslateService) { constructor(titleService: Title, protected translate: TranslateService) {
super(titleService, translate); super(titleService, translate);
} }
ngOnInit() { ngOnInit() {
super.setTitle('Motions'); super.setTitle('Motions');
this.workflowArray = this.DS.get(Workflow) as Workflow[];
this.motionArray = this.DS.get(Motion) as Motion[];
this.dataSource = new MatTableDataSource(this.motionArray);
// this.dataSource = new MatTableDataSource(ELEMENT_DATA);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
getStateIcon(stateName) {
if (stateName === 'accepted') {
return 'thumbs-up';
} else if (stateName === 'rejected') {
return 'thumbs-down';
} else if (stateName === 'not decided') {
return 'question';
}
} }
downloadMotionsButton() { downloadMotionsButton() {