Merge pull request #4843 from GabrielInTheWorld/uiImprovements
Fixes dynamic growing cells in workflows
This commit is contained in:
commit
ff7978b8ae
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
</div>
|
||||
|
||||
<div class="extra-controls-slot">
|
||||
<div *ngIf="isCategoryAvailable()">
|
||||
<div *ngIf="isCategoryAvailable() && !isMultiSelect">
|
||||
<button
|
||||
mat-button
|
||||
*ngIf="selectedView !== 'tiles'"
|
||||
|
@ -26,105 +26,111 @@
|
||||
<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">
|
||||
<div class="inner-table">
|
||||
{{ state.name | translate }}
|
||||
</div>
|
||||
<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>
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let perm">
|
||||
<div class="inner-table" *ngIf="perm.type === 'check'">
|
||||
<mat-checkbox
|
||||
[checked]="state[perm.selector]"
|
||||
(change)="onToggleStatePerm(state, perm.selector, $event)"
|
||||
></mat-checkbox>
|
||||
</div>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let perm">
|
||||
<div class="inner-table" *ngIf="perm.type === 'check'">
|
||||
<mat-checkbox
|
||||
[checked]="state[perm.selector]"
|
||||
(change)="onToggleStatePerm(state, perm.selector, $event)"
|
||||
></mat-checkbox>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="perm.type === 'input'"
|
||||
>
|
||||
<div class="inner-table">
|
||||
{{ (state[perm.selector] | translate) || '–' }}
|
||||
</div>
|
||||
<div
|
||||
class="clickable-cell"
|
||||
*ngIf="perm.type === 'input'"
|
||||
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]="state[perm.selector]"
|
||||
>
|
||||
<div class="inner-table">
|
||||
{{ (state[perm.selector] | translate) || '–' }}
|
||||
{{ state[perm.selector] | translate }}
|
||||
</mat-basic-chip>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="perm.type === 'state'"
|
||||
>
|
||||
<div class="inner-table">
|
||||
<div *ngIf="!state.next_states_id.length">
|
||||
-
|
||||
</div>
|
||||
<div *ngIf="state.next_states_id.length">
|
||||
<div
|
||||
*ngFor="
|
||||
let nextstate of state.getNextStates(workflow.workflow);
|
||||
let last = last
|
||||
"
|
||||
>
|
||||
{{ nextstate.name | translate }}<span *ngIf="!last">, </span>
|
||||
</div>
|
||||
</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])"
|
||||
>
|
||||
{{ state[perm.selector] | translate }}
|
||||
</mat-basic-chip>
|
||||
</div>
|
||||
<div
|
||||
class="clickable-cell"
|
||||
*ngIf="perm.type === 'state'"
|
||||
class="clickable-cell stretch-to-fill-parent"
|
||||
[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
|
||||
*ngFor="
|
||||
let nextstate of state.getNextStates(workflow.workflow);
|
||||
let last = last
|
||||
"
|
||||
>
|
||||
{{ nextstate.name | translate }}<span *ngIf="!last">, </span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
></div>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="perm.type === 'amendment'"
|
||||
>
|
||||
<div class="inner-table">
|
||||
{{ getMergeAmendmentLabel(state.merge_amendment_into_final) | translate }}
|
||||
</div>
|
||||
<div
|
||||
class="clickable-cell"
|
||||
*ngIf="perm.type === 'amendment'"
|
||||
class="clickable-cell stretch-to-fill-parent"
|
||||
[matMenuTriggerFor]="mergeAmendmentMenu"
|
||||
[matMenuTriggerData]="{ state: state }"
|
||||
>
|
||||
<div class="inner-table">
|
||||
{{ getMergeAmendmentLabel(state.merge_amendment_into_final) | translate }}
|
||||
></div>
|
||||
</div>
|
||||
<div
|
||||
*ngIf="perm.type === 'restriction'"
|
||||
>
|
||||
<div class="inner-table">
|
||||
<div *ngIf="!state.restriction.length">
|
||||
-
|
||||
</div>
|
||||
<div *ngIf="state.restriction.length">
|
||||
<div *ngFor="let restriction of state.restriction; let last = last">
|
||||
{{ getRestrictionLabel(restriction) | translate
|
||||
}}<span *ngIf="!last">, </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="clickable-cell"
|
||||
*ngIf="perm.type === 'restriction'"
|
||||
class="clickable-cell stretch-to-fill-parent"
|
||||
[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">
|
||||
{{ getRestrictionLabel(restriction) | translate
|
||||
}}<span *ngIf="!last">, </span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
</div>
|
||||
></div>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<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>
|
||||
|
@ -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;
|
||||
background-color: rgba(0, 0, 0, 0.025);
|
||||
&: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;
|
||||
}
|
||||
|
||||
|
@ -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] || '';
|
||||
}
|
||||
}
|
||||
|
@ -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 || '';
|
||||
}
|
||||
}
|
||||
|
15
openslides/motions/migrations/0030_state_css_classes_1.py
Normal file
15
openslides/motions/migrations/0030_state_css_classes_1.py
Normal 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),
|
||||
)
|
||||
]
|
28
openslides/motions/migrations/0031_state_css_classes_2.py
Normal file
28
openslides/motions/migrations/0031_state_css_classes_2.py
Normal 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)]
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user