From e36e4ed65505966564f4932032216363cf4166b2 Mon Sep 17 00:00:00 2001 From: Sean Engelhardt Date: Wed, 8 Aug 2018 17:25:39 +0200 Subject: [PATCH] First motion list view --- .../app/shared/models/motions/motion-log.ts | 25 +++ .../shared/models/motions/motion-submitter.ts | 25 +++ .../shared/models/motions/motion-version.ts | 39 ++++ .../src/app/shared/models/motions/motion.ts | 73 +++++++- .../src/app/shared/models/motions/workflow.ts | 10 + client/src/app/shared/shared.module.ts | 8 +- .../motion-list/motion-list.component.css | 0 .../motion-list/motion-list.component.html | 174 +++++------------- .../motion-list/motion-list.component.scss | 68 +++++++ .../motion-list/motion-list.component.ts | 57 +++++- 10 files changed, 344 insertions(+), 135 deletions(-) create mode 100644 client/src/app/shared/models/motions/motion-log.ts create mode 100644 client/src/app/shared/models/motions/motion-submitter.ts create mode 100644 client/src/app/shared/models/motions/motion-version.ts delete mode 100644 client/src/app/site/motions/motion-list/motion-list.component.css create mode 100644 client/src/app/site/motions/motion-list/motion-list.component.scss diff --git a/client/src/app/shared/models/motions/motion-log.ts b/client/src/app/shared/models/motions/motion-log.ts new file mode 100644 index 000000000..c6be1a092 --- /dev/null +++ b/client/src/app/shared/models/motions/motion-log.ts @@ -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; + } +} diff --git a/client/src/app/shared/models/motions/motion-submitter.ts b/client/src/app/shared/models/motions/motion-submitter.ts new file mode 100644 index 000000000..c355e8ecf --- /dev/null +++ b/client/src/app/shared/models/motions/motion-submitter.ts @@ -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; + } +} diff --git a/client/src/app/shared/models/motions/motion-version.ts b/client/src/app/shared/models/motions/motion-version.ts new file mode 100644 index 000000000..522d6c84f --- /dev/null +++ b/client/src/app/shared/models/motions/motion-version.ts @@ -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; + } +} diff --git a/client/src/app/shared/models/motions/motion.ts b/client/src/app/shared/models/motions/motion.ts index ec910af07..1f9cc7a8e 100644 --- a/client/src/app/shared/models/motions/motion.ts +++ b/client/src/app/shared/models/motions/motion.ts @@ -1,9 +1,14 @@ 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. * - * Untouched for now because of heavy maintainance on server side + * Slightly Defined cause heavy maintaince on server side. * * @ignore */ @@ -11,13 +16,13 @@ export class Motion extends BaseModel { protected _collectionString: string; id: number; identifier: string; - versions: Object[]; + versions: MotionVersion[]; active_version: number; parent_id: number; category_id: number; motion_block_id: number; origin: string; - submitters: Object[]; + submitters: MotionSubmitter[]; supporters_id: number[]; comments: Object; state_id: number; @@ -27,18 +32,18 @@ export class Motion extends BaseModel { attachments_id: number[]; polls: BaseModel[]; agenda_item_id: number; - log_messages: Object[]; + log_messages: MotionLog[]; constructor( id?: number, identifier?: string, - versions?: Object[], + versions?: MotionVersion[], active_version?: number, parent_id?: number, category_id?: number, motion_block_id?: number, origin?: string, - submitters?: Object[], + submitters?: MotionSubmitter[], supporters_id?: number[], comments?: Object, state_id?: number, @@ -48,7 +53,7 @@ export class Motion extends BaseModel { attachments_id?: number[], polls?: BaseModel[], agenda_item_id?: number, - log_messages?: Object[] + log_messages?: MotionLog[] ) { super(); this._collectionString = 'motions/motion'; @@ -72,4 +77,58 @@ export class Motion extends BaseModel { this.agenda_item_id = agenda_item_id; 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; + } } diff --git a/client/src/app/shared/models/motions/workflow.ts b/client/src/app/shared/models/motions/workflow.ts index c26cfe179..0487fb07b 100644 --- a/client/src/app/shared/models/motions/workflow.ts +++ b/client/src/app/shared/models/motions/workflow.ts @@ -21,6 +21,16 @@ export class Workflow extends BaseModel { 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 { Object.assign(this, input); if (input.states instanceof Array) { diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index 54fb55c32..cac662992 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts @@ -11,7 +11,9 @@ import { MatInputModule, MatProgressSpinnerModule, MatSidenavModule, - MatSnackBarModule + MatSnackBarModule, + MatTableModule, + MatPaginatorModule } from '@angular/material'; import { MatDialogModule } from '@angular/material/dialog'; import { MatListModule } from '@angular/material/list'; @@ -53,6 +55,8 @@ library.add(fas); MatToolbarModule, MatCardModule, MatInputModule, + MatTableModule, + MatPaginatorModule, MatProgressSpinnerModule, MatSidenavModule, MatListModule, @@ -70,6 +74,8 @@ library.add(fas); MatToolbarModule, MatCardModule, MatInputModule, + MatTableModule, + MatPaginatorModule, MatProgressSpinnerModule, MatSidenavModule, MatListModule, diff --git a/client/src/app/site/motions/motion-list/motion-list.component.css b/client/src/app/site/motions/motion-list/motion-list.component.css deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/src/app/site/motions/motion-list/motion-list.component.html b/client/src/app/site/motions/motion-list/motion-list.component.html index 23669987d..e8d2de377 100644 --- a/client/src/app/site/motions/motion-list/motion-list.component.html +++ b/client/src/app/site/motions/motion-list/motion-list.component.html @@ -14,128 +14,52 @@ - -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
- -
- Motion Works -
-
\ No newline at end of file +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + +
Bezeichner + + {{motion.identifier}} + + Titel + {{motion.versions[0].title}} +
+ + von + {{motion.submitterAsUser.username}} + +
Status + + +
+ + \ No newline at end of file diff --git a/client/src/app/site/motions/motion-list/motion-list.component.scss b/client/src/app/site/motions/motion-list/motion-list.component.scss new file mode 100644 index 000000000..4724580bc --- /dev/null +++ b/client/src/app/site/motions/motion-list/motion-list.component.scss @@ -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); +} diff --git a/client/src/app/site/motions/motion-list/motion-list.component.ts b/client/src/app/site/motions/motion-list/motion-list.component.ts index f6243b1da..0f061771a 100644 --- a/client/src/app/site/motions/motion-list/motion-list.component.ts +++ b/client/src/app/site/motions/motion-list/motion-list.component.ts @@ -1,20 +1,73 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, ViewChild } from '@angular/core'; import { Title } from '@angular/platform-browser'; import { BaseComponent } from 'app/base.component'; 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({ selector: 'app-motion-list', templateUrl: './motion-list.component.html', - styleUrls: ['./motion-list.component.css'] + styleUrls: ['./motion-list.component.scss'] }) export class MotionListComponent extends BaseComponent implements OnInit { + workflowArray: Array; + motionArray: Array; + dataSource: MatTableDataSource; + // dataSource: MatTableDataSource; + + @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) { super(titleService, translate); } ngOnInit() { 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() {