Motion detail with routing

For small screens only
This commit is contained in:
Sean Engelhardt 2018-08-09 16:03:24 +02:00 committed by FinnStutzenstein
parent 7856b7e07f
commit f01d3a5f6a
13 changed files with 271 additions and 14 deletions

View File

@ -8,7 +8,11 @@
"sourceRoot": "src",
"projectType": "application",
"prefix": "app",
"schematics": {},
"schematics": {
"@schematics/angular:component": {
"styleext": "scss"
}
},
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",

View File

@ -17,4 +17,8 @@ export class Category extends BaseModel {
this.name = name;
this.prefix = prefix;
}
public toString = (): string => {
return this.prefix + ' - ' + this.name;
};
}

View File

@ -4,6 +4,8 @@ import { MotionSubmitter } from './motion-submitter';
import { MotionLog } from './motion-log';
import { Config } from '../core/config';
import { Workflow } from './workflow';
import { User } from '../users/user';
import { Category } from './category';
/**
* Representation of Motion.
@ -78,6 +80,31 @@ export class Motion extends BaseModel {
this.log_messages = log_messages;
}
/**
* returns the most current title from versions
*/
get currentTitle() {
if (this.versions[0]) {
return this.versions[0].title;
} else {
return '';
}
}
/**
* returns the most current motion text from versions
*/
get currentText() {
return this.versions[0].text;
}
/**
* returns the most current motion reason text from versions
*/
get currentReason() {
return this.versions[0].reason;
}
/**
* return the submitters as uses objects
*/
@ -86,14 +113,39 @@ export class Motion extends BaseModel {
this.submitters.forEach(submitter => {
submitterIds.push(submitter.user_id);
});
const users = this.DS.get('users/user', ...submitterIds);
const users = this.DS.get(User, ...submitterIds);
return users;
}
/**
* returns the name of the first submitter
*/
get submitterName() {
const mainSubmitter = this.DS.get(User, this.submitters[0].user_id) as User;
if (mainSubmitter) {
return mainSubmitter.username;
} else {
return '';
}
}
/**
* get the category of a motion as object
*/
get category() {
if (this.category_id) {
const motionCategory = this.DS.get(Category, this.category_id);
return motionCategory;
} else {
return 'none';
}
}
/**
* return the workflow state
*
* Right now only the default workflow is assumes
* TODO: Motion workflow needs to be specific on the server
*/
get stateName() {
//get the default workflow

View File

@ -0,0 +1,63 @@
<mat-toolbar color='primary'>
<button class='generic-mini-button on-transition-fade' mat-mini-fab>
<fa-icon icon='pen'></fa-icon>
</button>
<!-- motion.identifier -->
<!-- motion.versions[0].title -->
<div class='motion-title on-transition-fade'>
<span translate>Motion</span> {{motion.identifier}} {{motion.currentTitle}}
<br>
<div class='motion-submitter'>
<span translate>by</span> {{motion.submitterName}}
</div>
</div>
</mat-toolbar>
<mat-accordion multi='true' class='on-transition-fade'>
<mat-expansion-panel [expanded]='true' class='meta-info-panel'>
<mat-expansion-panel-header>
<mat-panel-title>
<fa-icon icon='info-circle' [fixedWidth]="true"></fa-icon>
<span translate>Meta information</span>
</mat-panel-title>
</mat-expansion-panel-header>
<div class='meta-info-panel-body'>
<h3 translate>Submitters</h3>
{{motion.submitterName}}
<h3 translate>Supporters</h3>
<h3 translate>Status</h3>
{{motion.stateName}}
<h3 translate>Empfehlung der ABK</h3>
<h3 translate>Category</h3>
{{motion.category}}
<h3 translate>Origin</h3>
<h3 translate>Voting</h3>
</div>
</mat-expansion-panel>
<mat-expansion-panel [expanded]='true'>
<mat-expansion-panel-header>
<mat-panel-title>
<fa-icon icon='file-signature' [fixedWidth]="true"></fa-icon>
<span translate>Personal note</span>
</mat-panel-title>
</mat-expansion-panel-header>
TEST
</mat-expansion-panel>
<mat-expansion-panel [expanded]='true' class='content-panel'>
<mat-expansion-panel-header>
<mat-panel-title>
<fa-icon icon='align-left' [fixedWidth]="true"></fa-icon>
<span translate>Content</span>
</mat-panel-title>
</mat-expansion-panel-header>
<h3 translate>The assembly may decide:</h3>
<div [innerHtml]='motion.currentText'></div>
<h4 translate class='motion-reason-label'>Reason</h4>
<div [innerHtml]='motion.currentReason'></div>
</mat-expansion-panel>
</mat-accordion>

View File

@ -0,0 +1,47 @@
span {
margin: 0;
}
.motion-title {
padding-left: 20px;
line-height: 100%;
}
.motion-submitter {
display: inline;
font-weight: bold;
font-size: 70%;
}
mat-panel-title {
fa-icon {
margin-right: 35px; //on line with text
}
}
.meta-info-panel {
padding-top: 25px;
h3 {
display: block;
font-size: 80%;
color: gray;
}
.meta-info-panel-body {
padding-left: 55px;
}
}
.content-panel {
h3 {
font-weight: initial;
font-size: 100%;
display: block;
}
h4 {
display: block;
font-weight: bold;
font-size: 100%;
}
}

View File

@ -0,0 +1,24 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MotionDetailComponent } from './motion-detail.component';
describe('MotionDetailComponent', () => {
let component: MotionDetailComponent;
let fixture: ComponentFixture<MotionDetailComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MotionDetailComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MotionDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,43 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { OpenSlidesComponent } from '../../../openslides.component';
import { BaseComponent } from '../../../base.component';
import { Motion } from '../../../shared/models/motions/motion';
@Component({
selector: 'app-motion-detail',
templateUrl: './motion-detail.component.html',
styleUrls: ['./motion-detail.component.scss']
})
export class MotionDetailComponent extends BaseComponent implements OnInit {
motion: Motion;
constructor(private route: ActivatedRoute) {
super();
this.route.params.subscribe(params => {
console.log(params.id);
// has the motion of the DataStore was initialized before.
// Otherwise we need to observe DS
this.motion = this.DS.get(Motion, params.id) as Motion;
// Observe motion to get the motion in the parameter and also get the changes
this.DS.getObservable().subscribe(newModel => {
if (newModel instanceof Motion) {
if (newModel.id === +params.id) {
this.motion = newModel as Motion;
console.log('this.motion = ', this.motion);
}
}
});
});
}
ngOnInit() {
console.log('(init)the motion: ', this.motion);
}
downloadSingleMotionButton() {
console.log('Download this motion');
}
}

View File

@ -16,17 +16,17 @@
<div class='custom-table-header on-transition-fade'>
<button mat-button>
SORIEREN NACH
<span translate>SORT</span>
</button>
<button mat-button>
FILTER
<span translate>FILTER</span>
</button>
</div>
<mat-table class='on-transition-fade' [dataSource]="dataSource" matSort>
<!-- identifier column -->
<ng-container matColumnDef="identifier">
<mat-header-cell *matHeaderCellDef mat-sort-header> Bezeichner </mat-header-cell>
<mat-header-cell *matHeaderCellDef mat-sort-header> Identifier </mat-header-cell>
<mat-cell *matCellDef="let motion">
<div class='innerTable'>
{{motion.identifier}}
@ -36,13 +36,13 @@
<!-- title column -->
<ng-container matColumnDef="title">
<mat-header-cell *matHeaderCellDef mat-sort-header> Titel </mat-header-cell>
<mat-header-cell *matHeaderCellDef mat-sort-header> Title </mat-header-cell>
<mat-cell *matCellDef="let motion">
<div class='innerTable'>
<span class='motion-list-title'>{{motion.versions[0].title}}</span>
<br>
<span class='motion-list-from'>
<span translate>von</span>
<span translate>by</span>
{{motion.submitterAsUser.username}}
</span>
</div>
@ -51,13 +51,10 @@
<!-- state column -->
<ng-container matColumnDef="state">
<mat-header-cell *matHeaderCellDef mat-sort-header> Status </mat-header-cell>
<mat-header-cell *matHeaderCellDef mat-sort-header> State </mat-header-cell>
<mat-cell *matCellDef="let motion">
<div class='innerTable'>
<fa-icon icon={{getStateIcon(motion.stateName)}}></fa-icon>
<!-- <span class='motion.list.state'>
{{motion.stateName}}
</span> -->
</div>
</mat-cell>
</ng-container>

View File

@ -28,6 +28,11 @@ mat-table {
height: 60px;
}
mat-row:hover {
cursor: pointer;
background-color: rgba(0, 0, 0, 0.025);
}
/** identifier */
.mat-column-identifier {
padding-left: 10px;

View File

@ -1,4 +1,5 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Title } from '@angular/platform-browser';
import { BaseComponent } from 'app/base.component';
import { TranslateService } from '@ngx-translate/core';
@ -45,7 +46,12 @@ export class MotionListComponent extends BaseComponent implements OnInit {
* @param titleService
* @param translate
*/
constructor(titleService: Title, protected translate: TranslateService) {
constructor(
public router: Router,
titleService: Title,
protected translate: TranslateService,
private route: ActivatedRoute
) {
super(titleService, translate);
}
@ -72,6 +78,8 @@ export class MotionListComponent extends BaseComponent implements OnInit {
selectMotion(motion) {
console.log('clicked a row, :', motion);
this.router.navigate(['./' + motion.id], { relativeTo: this.route });
}
/**

View File

@ -1,8 +1,13 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { MotionListComponent } from './motion-list/motion-list.component';
import { MotionDetailComponent } from './motion-detail/motion-detail.component';
const routes: Routes = [{ path: '', component: MotionListComponent }];
const routes: Routes = [
{ path: '', component: MotionListComponent },
{ path: 'dummy', component: MotionDetailComponent },
{ path: ':id', component: MotionDetailComponent }
];
@NgModule({
imports: [RouterModule.forChild(routes)],

View File

@ -4,9 +4,10 @@ import { CommonModule } from '@angular/common';
import { MotionsRoutingModule } from './motions-routing.module';
import { SharedModule } from '../../shared/shared.module';
import { MotionListComponent } from './motion-list/motion-list.component';
import { MotionDetailComponent } from './motion-detail/motion-detail.component';
@NgModule({
imports: [CommonModule, MotionsRoutingModule, SharedModule],
declarations: [MotionListComponent]
declarations: [MotionListComponent, MotionDetailComponent]
})
export class MotionsModule {}

View File

@ -48,6 +48,10 @@ router-outlet ~ * {
z-index: 100;
}
.generic-mini-button {
bottom: -28px;
z-index: 100;
}
.os-card {
max-width: 90%;
margin-top: 10px;