Merge pull request #4843 from GabrielInTheWorld/uiImprovements

Fixes dynamic growing cells in workflows
This commit is contained in:
Sean 2019-07-25 10:26:20 +02:00 committed by GitHub
commit ff7978b8ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 153 additions and 134 deletions

View File

@ -9,7 +9,7 @@ import { ViewUser } from 'app/site/users/models/view-user';
import { ViewTag } from 'app/site/tags/models/view-tag';
import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile';
import { ViewItem } from 'app/site/agenda/models/view-item';
import { ViewWorkflow, StateCssClassMapping } from './view-workflow';
import { ViewWorkflow } from './view-workflow';
import { ViewCategory } from './view-category';
import { ViewMotionBlock } from './view-motion-block';
import { BaseViewModel } from 'app/site/base/base-view-model';
@ -349,7 +349,7 @@ export class ViewMotion extends BaseViewModelWithAgendaItemAndListOfSpeakers<Mot
* @returns a string representing a color
*/
public get stateCssColor(): string {
return this.state ? StateCssClassMapping[this.state.css_class] : '';
return this.state ? this.state.css_class : '';
}
// This is set by the repository

View File

@ -2,14 +2,6 @@ import { Workflow } from 'app/shared/models/motions/workflow';
import { WorkflowState } from 'app/shared/models/motions/workflow-state';
import { BaseViewModel } from '../../base/base-view-model';
export const StateCssClassMapping = {
success: 'green',
danger: 'red',
default: 'grey',
primary: 'lightblue',
warning: 'yellow'
};
export interface WorkflowTitleInformation {
name: string;
}

View File

@ -16,7 +16,7 @@
</div>
<div class="extra-controls-slot">
<div *ngIf="isCategoryAvailable()">
<div *ngIf="isCategoryAvailable() && !isMultiSelect">
<button
mat-button
*ngIf="selectedView !== 'tiles'"

View File

@ -26,24 +26,23 @@
<div class="scrollable-matrix">
<table mat-table [dataSource]="getTableDataSource()">
<ng-container matColumnDef="perm" sticky>
<mat-header-cell class="group-head-table-cell" *matHeaderCellDef translate>Permissions</mat-header-cell>
<mat-cell *matCellDef="let perm">
<th mat-header-cell class="group-head-table-cell" *matHeaderCellDef translate>Permissions</th>
<td mat-cell *matCellDef="let perm">
<div class="permission-name">
{{ perm.name | translate }}
</div>
</mat-cell>
</td>
</ng-container>
<div *ngFor="let state of workflow.states; trackBy: trackByIndex">
<ng-container [matColumnDef]="getColumnDef(state)">
<mat-header-cell *matHeaderCellDef (click)="onClickStateName(state)">
<div class="clickable-cell">
<ng-container [matColumnDef]="getColumnDef(state)" *ngFor="let state of workflow.states; trackBy: trackByIndex">
<th mat-header-cell *matHeaderCellDef (click)="onClickStateName(state)">
<div class="clickable-cell stretch-to-fill-parent">
<div class="inner-table">
{{ state.name | translate }}
</div>
</div>
</mat-header-cell>
<mat-cell *matCellDef="let perm">
</th>
<td mat-cell *matCellDef="let perm">
<div class="inner-table" *ngIf="perm.type === 'check'">
<mat-checkbox
[checked]="state[perm.selector]"
@ -51,80 +50,87 @@
></mat-checkbox>
</div>
<div
class="clickable-cell"
*ngIf="perm.type === 'input'"
(click)="onClickInputPerm(perm, state)"
>
<div class="inner-table">
{{ (state[perm.selector] | translate) || '' }}
</div>
<div
class="clickable-cell stretch-to-fill-parent"
(click)="onClickInputPerm(perm, state)"
></div>
</div>
<div class="inner-table" *ngIf="perm.type === 'color'">
<mat-basic-chip
[matMenuTriggerFor]="colorMenu"
[matMenuTriggerData]="{ state: state }"
[disableRipple]="true"
[ngClass]="getStateCssColor(state[perm.selector])"
[ngClass]="state[perm.selector]"
>
{{ state[perm.selector] | translate }}
</mat-basic-chip>
</div>
<div
class="clickable-cell"
*ngIf="perm.type === 'state'"
[matMenuTriggerFor]="nextStatesMenu"
[matMenuTriggerData]="{ state: state }"
>
<div class="inner-table">
<div *ngIf="!state.next_states_id.length">
-
</div>
<div *ngIf="state.next_states_id.length">
<span
<div
*ngFor="
let nextstate of state.getNextStates(workflow.workflow);
let last = last
"
>
{{ nextstate.name | translate }}<span *ngIf="!last">,&nbsp;</span>
</span>
</div>
</div>
</div>
<div
class="clickable-cell"
*ngIf="perm.type === 'amendment'"
[matMenuTriggerFor]="mergeAmendmentMenu"
class="clickable-cell stretch-to-fill-parent"
[matMenuTriggerFor]="nextStatesMenu"
[matMenuTriggerData]="{ state: state }"
></div>
</div>
<div
*ngIf="perm.type === 'amendment'"
>
<div class="inner-table">
{{ getMergeAmendmentLabel(state.merge_amendment_into_final) | translate }}
</div>
<div
class="clickable-cell stretch-to-fill-parent"
[matMenuTriggerFor]="mergeAmendmentMenu"
[matMenuTriggerData]="{ state: state }"
></div>
</div>
<div
class="clickable-cell"
*ngIf="perm.type === 'restriction'"
[matMenuTriggerFor]="restrictionMenu"
[matMenuTriggerData]="{ state: state }"
>
<div class="inner-table">
<div *ngIf="!state.restriction.length">
-
</div>
<div *ngIf="state.restriction.length">
<span *ngFor="let restriction of state.restriction; let last = last">
<div *ngFor="let restriction of state.restriction; let last = last">
{{ getRestrictionLabel(restriction) | translate
}}<span *ngIf="!last">,&nbsp;</span>
</span>
</div>
</div>
</div>
</mat-cell>
<div
class="clickable-cell stretch-to-fill-parent"
[matMenuTriggerFor]="restrictionMenu"
[matMenuTriggerData]="{ state: state }"
></div>
</div>
</td>
</ng-container>
</div>
<mat-header-row *matHeaderRowDef="headerRowDef"></mat-header-row>
<mat-row *matRowDef="let row; columns: headerRowDef"></mat-row>
<tr mat-header-row *matHeaderRowDef="headerRowDef"></tr>
<tr mat-row *matRowDef="let row; columns: headerRowDef"></tr>
</table>
</div>
</div>

View File

@ -5,35 +5,25 @@
}
table {
.mat-header-cell {
min-width: 150px;
position: relative;
}
.mat-header-cell,
.mat-cell {
min-width: 150px;
min-width: 200px;
position: relative;
}
// scaled up version of an inner table
.clickable-cell {
position: absolute;
display: flex;
width: 100%;
height: 100%;
}
.clickable-cell:hover {
cursor: pointer;
&:hover {
background-color: rgba(0, 0, 0, 0.025);
}
}
.inner-table {
text-align: center;
align-items: center;
margin: auto;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding: 0 10px;
}

View File

@ -10,7 +10,7 @@ import { Title } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
import { BaseViewComponent } from 'app/site/base/base-view';
import { ViewWorkflow, StateCssClassMapping } from 'app/site/motions/models/view-workflow';
import { ViewWorkflow } from 'app/site/motions/models/view-workflow';
import { WorkflowRepositoryService } from 'app/core/repositories/motions/workflow-repository.service';
import { WorkflowState, MergeAmendment } from 'app/shared/models/motions/workflow-state';
import { PromptService } from 'app/core/ui-services/prompt.service';
@ -93,7 +93,7 @@ export class WorkflowDetailComponent extends BaseViewComponent implements OnInit
/**
* Determine label colors. Where they should come from is currently now know
*/
public labelColors = ['default', 'primary', 'success', 'danger', 'warning'];
public labelColors: string[] = ['grey', 'red', 'green', 'lightblue', 'yellow'];
/**
* Holds state permissions
@ -396,14 +396,4 @@ export class WorkflowDetailComponent extends BaseViewComponent implements OnInit
public trackElement(index: number): number {
return index;
}
/**
* Translate the state's css class into a color
*
* @param colorLabel the default color label of a selected workflow
* @returns a string representing a color
*/
public getStateCssColor(colorLabel: string): string {
return StateCssClassMapping[colorLabel] || '';
}
}

View File

@ -4,7 +4,6 @@ import { TranslateService } from '@ngx-translate/core';
import { MotionBlockSlideData, MotionBlockSlideMotionRepresentation } from './motion-block-slide-data';
import { MotionRepositoryService } from 'app/core/repositories/motions/motion-repository.service';
import { StateCssClassMapping } from 'app/site/motions/models/view-workflow';
import { BaseMotionSlideComponent } from '../base/base-motion-slide';
import { SlideData } from 'app/core/core-services/projector-data.service';
@ -187,6 +186,6 @@ export class MotionBlockSlideComponent extends BaseMotionSlideComponent<MotionBl
* @returns the css color for the state of the motion in cell i and j
*/
public getStateCssColor(i: number, j: number): string {
return StateCssClassMapping[this.getMotion(i, j).recommendation.css_class] || '';
return this.getMotion(i, j).recommendation.css_class || '';
}
}

View File

@ -0,0 +1,15 @@
# Generated by Finn Stutzenstein on 2019-07-17 08:32
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("motions", "0029_motioncommentsection_weight")]
operations = [
migrations.AlterField(
model_name="state",
name="css_class",
field=models.CharField(default="lightblue", max_length=255),
)
]

View File

@ -0,0 +1,28 @@
# Generated by Finn Stutzenstein on 2019-07-17 08:43
from django.db import migrations
LABEL_MAPPING = {
"default": "grey",
"primary": "lightblue",
"success": "green",
"danger": "red",
"warning": "yellow",
}
def rename_css_classes(apps, schema_editor):
State = apps.get_model("motions", "State")
for state in State.objects.all():
old_class = state.css_class
state.css_class = LABEL_MAPPING.get(old_class, "lightblue")
state.save(skip_autoupdate=True)
class Migration(migrations.Migration):
dependencies = [("motions", "0030_state_css_classes_1")]
operations = [migrations.RunPython(rename_css_classes)]

View File

@ -993,11 +993,10 @@ class State(RESTModelMixin, models.Model):
next_states = models.ManyToManyField("self", symmetrical=False, blank=True)
"""A many-to-many relation to all states, that can be choosen from this state."""
css_class = models.CharField(max_length=255, default="primary")
css_class = models.CharField(max_length=255, default="lightblue")
"""
A css class string for showing the state name in a coloured label based on bootstrap,
e.g. 'danger' (red), 'success' (green), 'warning' (yellow), 'default' (grey).
Default value is 'primary' (blue).
A css class string for showing the state name in a coloured label. Currently supported
values are grey, red, green, lightblue and yellow. The default is lightblue.
"""
restriction = JSONField(default=list)

View File

@ -26,7 +26,7 @@ def create_builtin_workflows(sender, **kwargs):
name="accepted",
workflow=workflow_1,
recommendation_label="Acceptance",
css_class="success",
css_class="green",
merge_amendment_into_final=1,
)
state_1_2.save(skip_autoupdate=True)
@ -34,7 +34,7 @@ def create_builtin_workflows(sender, **kwargs):
name="rejected",
workflow=workflow_1,
recommendation_label="Rejection",
css_class="danger",
css_class="red",
merge_amendment_into_final=-1,
)
state_1_3.save(skip_autoupdate=True)
@ -42,7 +42,7 @@ def create_builtin_workflows(sender, **kwargs):
name="not decided",
workflow=workflow_1,
recommendation_label="No decision",
css_class="default",
css_class="grey",
merge_amendment_into_final=-1,
)
state_1_4.save(skip_autoupdate=True)
@ -77,7 +77,7 @@ def create_builtin_workflows(sender, **kwargs):
name="accepted",
workflow=workflow_2,
recommendation_label="Acceptance",
css_class="success",
css_class="green",
merge_amendment_into_final=1,
)
state_2_3.save(skip_autoupdate=True)
@ -85,14 +85,14 @@ def create_builtin_workflows(sender, **kwargs):
name="rejected",
workflow=workflow_2,
recommendation_label="Rejection",
css_class="danger",
css_class="red",
merge_amendment_into_final=-1,
)
state_2_4.save(skip_autoupdate=True)
state_2_5 = State(
name="withdrawed",
workflow=workflow_2,
css_class="default",
css_class="grey",
merge_amendment_into_final=-1,
)
state_2_5.save(skip_autoupdate=True)
@ -100,7 +100,7 @@ def create_builtin_workflows(sender, **kwargs):
name="adjourned",
workflow=workflow_2,
recommendation_label="Adjournment",
css_class="default",
css_class="grey",
merge_amendment_into_final=-1,
)
state_2_6.save(skip_autoupdate=True)
@ -108,7 +108,7 @@ def create_builtin_workflows(sender, **kwargs):
name="not concerned",
workflow=workflow_2,
recommendation_label="No concernment",
css_class="default",
css_class="grey",
merge_amendment_into_final=-1,
)
state_2_7.save(skip_autoupdate=True)
@ -116,14 +116,14 @@ def create_builtin_workflows(sender, **kwargs):
name="refered to committee",
workflow=workflow_2,
recommendation_label="Referral to committee",
css_class="default",
css_class="grey",
merge_amendment_into_final=-1,
)
state_2_8.save(skip_autoupdate=True)
state_2_9 = State(
name="needs review",
workflow=workflow_2,
css_class="default",
css_class="grey",
merge_amendment_into_final=-1,
)
state_2_9.save(skip_autoupdate=True)
@ -131,7 +131,7 @@ def create_builtin_workflows(sender, **kwargs):
name="rejected (not authorized)",
workflow=workflow_2,
recommendation_label="Rejection (not authorized)",
css_class="default",
css_class="grey",
merge_amendment_into_final=-1,
)
state_2_10.save(skip_autoupdate=True)

View File

@ -177,7 +177,7 @@ def all_data():
"id": 1,
"name": "submitted",
"recommendation_label": None,
"css_class": "primary",
"css_class": "lightblue",
"restriction": [],
"allow_support": True,
"allow_create_poll": True,
@ -193,7 +193,7 @@ def all_data():
"id": 2,
"name": "accepted",
"recommendation_label": "Acceptance",
"css_class": "success",
"css_class": "green",
"restriction": [],
"allow_support": False,
"allow_create_poll": False,
@ -209,7 +209,7 @@ def all_data():
"id": 3,
"name": "rejected",
"recommendation_label": "Rejection",
"css_class": "danger",
"css_class": "red",
"restriction": [],
"allow_support": False,
"allow_create_poll": False,
@ -225,7 +225,7 @@ def all_data():
"id": 4,
"name": "not decided",
"recommendation_label": "No decision",
"css_class": "default",
"css_class": "grey",
"restriction": [],
"allow_support": False,
"allow_create_poll": False,