Merge pull request #4419 from MaximilianKrambach/countdown
countdown: new title field, description made optional
This commit is contained in:
commit
69fe4632f4
@ -8,7 +8,8 @@ export class Countdown extends BaseModel<Countdown> {
|
|||||||
public static COLLECTIONSTRING = 'core/countdown';
|
public static COLLECTIONSTRING = 'core/countdown';
|
||||||
|
|
||||||
public id: number;
|
public id: number;
|
||||||
public description: string;
|
public description?: string;
|
||||||
|
public title: string;
|
||||||
public default_time: number;
|
public default_time: number;
|
||||||
public countdown_time: number;
|
public countdown_time: number;
|
||||||
public running: boolean;
|
public running: boolean;
|
||||||
|
@ -64,7 +64,7 @@ export class ViewTopic extends BaseAgendaViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getTitle = () => {
|
public getTitle = () => {
|
||||||
if (this.agendaItem) {
|
if (this.agendaItem && this.agendaItem.itemNumber) {
|
||||||
return this.agendaItem.itemNumber + ' · ' + this.title;
|
return this.agendaItem.itemNumber + ' · ' + this.title;
|
||||||
} else {
|
} else {
|
||||||
return this.title;
|
return this.title;
|
||||||
|
@ -9,18 +9,23 @@
|
|||||||
<mat-card *ngIf="countdownToCreate">
|
<mat-card *ngIf="countdownToCreate">
|
||||||
<mat-card-title translate>New countdown</mat-card-title>
|
<mat-card-title translate>New countdown</mat-card-title>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<form [formGroup]="createForm"
|
<form [formGroup]="createForm" (keydown)="onKeyDownCreate($event)">
|
||||||
(keydown)="onKeyDownCreate($event)">
|
|
||||||
<p>
|
<p>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<input formControlName="description" matInput placeholder="{{'Description' | translate}}" required>
|
<input formControlName="title" matInput placeholder="{{ 'Title' | translate }}" required />
|
||||||
<mat-hint *ngIf="!createForm.controls.description.valid">
|
<mat-hint *ngIf="!createForm.controls.title.valid">
|
||||||
<span translate>Required</span>
|
<span translate>Required</span>
|
||||||
</mat-hint>
|
</mat-hint>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</p><p>
|
</p>
|
||||||
|
<p>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<input formControlName="default_time" matInput placeholder="{{ 'Time' | translate}}" required>
|
<input formControlName="description" matInput placeholder="{{ 'Description' | translate }}" />
|
||||||
|
</mat-form-field>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<mat-form-field>
|
||||||
|
<input formControlName="default_time" matInput placeholder="{{ 'Time' | translate }}" required />
|
||||||
<mat-hint *ngIf="!createForm.controls.default_time.valid">
|
<mat-hint *ngIf="!createForm.controls.default_time.valid">
|
||||||
<span translate>Required</span>
|
<span translate>Required</span>
|
||||||
</mat-hint>
|
</mat-hint>
|
||||||
@ -39,9 +44,13 @@
|
|||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
||||||
<mat-accordion class="os-card">
|
<mat-accordion class="os-card">
|
||||||
<mat-expansion-panel *ngFor="let countdown of countdowns" (opened)="openId = countdown.id"
|
<mat-expansion-panel
|
||||||
(closed)="panelClosed(countdown)" [expanded]="openId === countdown.id" multiple="false">
|
*ngFor="let countdown of countdowns"
|
||||||
|
(opened)="openId = countdown.id"
|
||||||
|
(closed)="panelClosed(countdown)"
|
||||||
|
[expanded]="openId === countdown.id"
|
||||||
|
multiple="false"
|
||||||
|
>
|
||||||
<!-- Projector button and countdown description-->
|
<!-- Projector button and countdown description-->
|
||||||
<mat-expansion-panel-header>
|
<mat-expansion-panel-header>
|
||||||
<mat-panel-title>
|
<mat-panel-title>
|
||||||
@ -50,7 +59,7 @@
|
|||||||
<os-projector-button [object]="countdown"></os-projector-button>
|
<os-projector-button [object]="countdown"></os-projector-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-name">
|
<div class="header-name">
|
||||||
{{ countdown.description }}
|
{{ countdown.getTitle() | translate }}
|
||||||
</div>
|
</div>
|
||||||
<div class="header-controls">
|
<div class="header-controls">
|
||||||
<os-countdown-controls [countdown]="countdown"></os-countdown-controls>
|
<os-countdown-controls [countdown]="countdown"></os-countdown-controls>
|
||||||
@ -58,20 +67,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</mat-panel-title>
|
</mat-panel-title>
|
||||||
</mat-expansion-panel-header>
|
</mat-expansion-panel-header>
|
||||||
<form [formGroup]="updateForm"
|
<form [formGroup]="updateForm" *ngIf="editId === countdown.id" (keydown)="onKeyDownUpdate($event)">
|
||||||
*ngIf="editId === countdown.id"
|
|
||||||
(keydown)="onKeyDownUpdate($event)">
|
|
||||||
<h5 translate>Edit countdown</h5>
|
<h5 translate>Edit countdown</h5>
|
||||||
<p>
|
<p>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<input formControlName="description" matInput placeholder="{{ 'Description' | translate}}" required>
|
<input formControlName="title" matInput placeholder="{{ 'Title' | translate }}" required />
|
||||||
<mat-hint *ngIf="!updateForm.controls.description.valid">
|
<mat-hint *ngIf="!updateForm.controls.title.valid">
|
||||||
<span translate>Required</span>
|
<span translate>Required</span>
|
||||||
</mat-hint>
|
</mat-hint>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</p><p>
|
</p>
|
||||||
|
<p>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<input formControlName="default_time" matInput placeholder="{{ 'Time' | translate}}" required>
|
<input
|
||||||
|
formControlName="description"
|
||||||
|
matInput
|
||||||
|
placeholder="{{ 'Description' | translate }}"
|
||||||
|
/>
|
||||||
|
</mat-form-field>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<mat-form-field>
|
||||||
|
<input formControlName="default_time" matInput placeholder="{{ 'Time' | translate }}" required />
|
||||||
<mat-hint *ngIf="!updateForm.controls.default_time.valid">
|
<mat-hint *ngIf="!updateForm.controls.default_time.valid">
|
||||||
<span translate>Required</span>
|
<span translate>Required</span>
|
||||||
</mat-hint>
|
</mat-hint>
|
||||||
@ -79,19 +96,34 @@
|
|||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
<mat-action-row>
|
<mat-action-row>
|
||||||
<button *ngIf="editId !== countdown.id" mat-button class="on-transition-fade" (click)="onEditButton(countdown)"
|
<button
|
||||||
mat-icon-button>
|
*ngIf="editId !== countdown.id"
|
||||||
|
mat-button
|
||||||
|
class="on-transition-fade"
|
||||||
|
(click)="onEditButton(countdown)"
|
||||||
|
mat-icon-button
|
||||||
|
>
|
||||||
<mat-icon>edit</mat-icon>
|
<mat-icon>edit</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="editId === countdown.id" mat-button class="on-transition-fade" (click)="onCancelUpdate()"
|
<button
|
||||||
mat-icon-button>
|
*ngIf="editId === countdown.id"
|
||||||
|
mat-button
|
||||||
|
class="on-transition-fade"
|
||||||
|
(click)="onCancelUpdate()"
|
||||||
|
mat-icon-button
|
||||||
|
>
|
||||||
<mat-icon>close</mat-icon>
|
<mat-icon>close</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button *ngIf="editId === countdown.id" mat-button class="on-transition-fade" (click)="onSaveButton(countdown)"
|
<button
|
||||||
mat-icon-button>
|
*ngIf="editId === countdown.id"
|
||||||
|
mat-button
|
||||||
|
class="on-transition-fade"
|
||||||
|
(click)="onSaveButton(countdown)"
|
||||||
|
mat-icon-button
|
||||||
|
>
|
||||||
<mat-icon>save</mat-icon>
|
<mat-icon>save</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button mat-button class='on-transition-fade' (click)=onDeleteButton(countdown) mat-icon-button>
|
<button mat-button class="on-transition-fade" (click)="onDeleteButton(countdown)" mat-icon-button>
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</mat-action-row>
|
</mat-action-row>
|
||||||
|
@ -50,8 +50,9 @@ export class CountdownListComponent extends BaseViewComponent implements OnInit
|
|||||||
super(titleService, translate, matSnackBar);
|
super(titleService, translate, matSnackBar);
|
||||||
|
|
||||||
const form = {
|
const form = {
|
||||||
description: ['', Validators.required],
|
description: [''],
|
||||||
default_time: ['', Validators.required]
|
default_time: ['', Validators.required],
|
||||||
|
title: ['', Validators.required]
|
||||||
};
|
};
|
||||||
this.createForm = this.formBuilder.group(form);
|
this.createForm = this.formBuilder.group(form);
|
||||||
this.updateForm = this.formBuilder.group(form);
|
this.updateForm = this.formBuilder.group(form);
|
||||||
@ -77,6 +78,7 @@ export class CountdownListComponent extends BaseViewComponent implements OnInit
|
|||||||
this.createForm.reset();
|
this.createForm.reset();
|
||||||
this.createForm.setValue({
|
this.createForm.setValue({
|
||||||
description: '',
|
description: '',
|
||||||
|
title: '',
|
||||||
default_time: '1:00 m'
|
default_time: '1:00 m'
|
||||||
});
|
});
|
||||||
this.countdownToCreate = new Countdown();
|
this.countdownToCreate = new Countdown();
|
||||||
@ -95,6 +97,7 @@ export class CountdownListComponent extends BaseViewComponent implements OnInit
|
|||||||
|
|
||||||
const newValues: Partial<Countdown> = {
|
const newValues: Partial<Countdown> = {
|
||||||
description: this.createForm.value.description,
|
description: this.createForm.value.description,
|
||||||
|
title: this.createForm.value.title,
|
||||||
default_time: default_time
|
default_time: default_time
|
||||||
};
|
};
|
||||||
newValues.countdown_time = default_time;
|
newValues.countdown_time = default_time;
|
||||||
@ -114,6 +117,7 @@ export class CountdownListComponent extends BaseViewComponent implements OnInit
|
|||||||
|
|
||||||
this.updateForm.setValue({
|
this.updateForm.setValue({
|
||||||
description: countdown.description,
|
description: countdown.description,
|
||||||
|
title: this.translate.instant(countdown.title),
|
||||||
default_time: this.durationService.durationToString(countdown.default_time, 'm')
|
default_time: this.durationService.durationToString(countdown.default_time, 'm')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -129,6 +133,7 @@ export class CountdownListComponent extends BaseViewComponent implements OnInit
|
|||||||
default_time = 60;
|
default_time = 60;
|
||||||
}
|
}
|
||||||
const newValues: Partial<Countdown> = {
|
const newValues: Partial<Countdown> = {
|
||||||
|
title: this.updateForm.value.title,
|
||||||
description: this.updateForm.value.description,
|
description: this.updateForm.value.description,
|
||||||
default_time: default_time
|
default_time: default_time
|
||||||
};
|
};
|
||||||
@ -147,7 +152,7 @@ export class CountdownListComponent extends BaseViewComponent implements OnInit
|
|||||||
* @param countdown The countdown to delete
|
* @param countdown The countdown to delete
|
||||||
*/
|
*/
|
||||||
public async onDeleteButton(countdown: ViewCountdown): Promise<void> {
|
public async onDeleteButton(countdown: ViewCountdown): Promise<void> {
|
||||||
const content = this.translate.instant('Delete countdown') + ` ${countdown.description}?`;
|
const content = this.translate.instant('Delete countdown') + ` ${this.translate.instant(countdown.title)}?`;
|
||||||
if (await this.promptService.open('Are you sure?', content)) {
|
if (await this.promptService.open('Are you sure?', content)) {
|
||||||
this.repo.delete(countdown).then(() => (this.openId = this.editId = null), this.raiseError);
|
this.repo.delete(countdown).then(() => (this.openId = this.editId = null), this.raiseError);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
</a>
|
</a>
|
||||||
<!-- Controls under the projector preview -->
|
<!-- Controls under the projector preview -->
|
||||||
<div class="control-group projector-controls">
|
<div class="control-group projector-controls">
|
||||||
|
|
||||||
<!-- scale up -->
|
<!-- scale up -->
|
||||||
<button type="button" mat-icon-button (click)="scale(scrollScaleDirection.Up)">
|
<button type="button" mat-icon-button (click)="scale(scrollScaleDirection.Up)">
|
||||||
<mat-icon>zoom_in</mat-icon>
|
<mat-icon>zoom_in</mat-icon>
|
||||||
@ -44,7 +43,6 @@
|
|||||||
</button>
|
</button>
|
||||||
<!-- scroll indicator -->
|
<!-- scroll indicator -->
|
||||||
<div class="button-size" [ngClass]="projector.scroll != 0 ? 'warn' : ''">{{ projector.scroll }}</div>
|
<div class="button-size" [ngClass]="projector.scroll != 0 ? 'warn' : ''">{{ projector.scroll }}</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="column-right" *osPerms="'core.can_manage_projector'">
|
<div class="column-right" *osPerms="'core.can_manage_projector'">
|
||||||
@ -73,7 +71,10 @@
|
|||||||
<div>
|
<div>
|
||||||
<div *ngIf="projector.non_stable_elements.length">
|
<div *ngIf="projector.non_stable_elements.length">
|
||||||
<mat-list>
|
<mat-list>
|
||||||
<mat-list-item *ngFor="let element of projector.non_stable_elements" class="currentElement backgroundColorAccent">
|
<mat-list-item
|
||||||
|
*ngFor="let element of projector.non_stable_elements"
|
||||||
|
class="currentElement backgroundColorAccent"
|
||||||
|
>
|
||||||
<button type="button" mat-icon-button (click)="unprojectCurrent(element)">
|
<button type="button" mat-icon-button (click)="unprojectCurrent(element)">
|
||||||
<mat-icon>videocam</mat-icon>
|
<mat-icon>videocam</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
@ -96,7 +97,6 @@
|
|||||||
<mat-expansion-panel-header>
|
<mat-expansion-panel-header>
|
||||||
<span translate>Queue</span>
|
<span translate>Queue</span>
|
||||||
</mat-expansion-panel-header>
|
</mat-expansion-panel-header>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
cdkDropList
|
cdkDropList
|
||||||
class="drop-list"
|
class="drop-list"
|
||||||
@ -161,7 +161,7 @@
|
|||||||
<button type="button" mat-icon-button (click)="project(countdown)">
|
<button type="button" mat-icon-button (click)="project(countdown)">
|
||||||
<mat-icon>videocam</mat-icon>
|
<mat-icon>videocam</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
{{ countdown.description }}
|
{{ countdown.getTitle() | translate }}
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
</mat-list>
|
</mat-list>
|
||||||
<mat-action-row>
|
<mat-action-row>
|
||||||
|
@ -29,7 +29,11 @@ export class ViewCountdown extends BaseProjectableViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get description(): string {
|
public get description(): string {
|
||||||
return this.countdown.description;
|
return this.countdown.description || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public get title(): string {
|
||||||
|
return this.countdown.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,8 +46,12 @@ export class ViewCountdown extends BaseProjectableViewModel {
|
|||||||
this._countdown = countdown;
|
this._countdown = countdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns a title for the countdown, consisting of the title and additional
|
||||||
|
* text info that may be displayed on the projector
|
||||||
|
*/
|
||||||
public getTitle = () => {
|
public getTitle = () => {
|
||||||
return this.description;
|
return this.description ? `${this.title} (${this.description})` : this.title;
|
||||||
};
|
};
|
||||||
|
|
||||||
public updateDependencies(update: BaseViewModel): void {}
|
public updateDependencies(update: BaseViewModel): void {}
|
||||||
|
@ -423,6 +423,7 @@ class Speaker(RESTModelMixin, models.Model):
|
|||||||
pk=1,
|
pk=1,
|
||||||
defaults={
|
defaults={
|
||||||
"default_time": config["projector_default_countdown"],
|
"default_time": config["projector_default_countdown"],
|
||||||
|
"title": "Default countdown",
|
||||||
"countdown_time": config["projector_default_countdown"],
|
"countdown_time": config["projector_default_countdown"],
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
15
openslides/core/migrations/0019_countdown_title_1.py
Normal file
15
openslides/core/migrations/0019_countdown_title_1.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Generated by Django 2.1.5 on 2019-02-27 11:17
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def delete_old_countdowns(apps, schema_editor):
|
||||||
|
Countdowns = apps.get_model("core", "countdown")
|
||||||
|
Countdowns.objects.all().delete()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [("core", "0018_auto_20190222_1209")]
|
||||||
|
|
||||||
|
operations = [migrations.RunPython(delete_old_countdowns)]
|
16
openslides/core/migrations/0019_countdown_title_2.py
Normal file
16
openslides/core/migrations/0019_countdown_title_2.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Generated by Django 2.1.5 on 2019-02-27 11:46
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [("core", "0019_countdown_title_1")]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="countdown",
|
||||||
|
name="title",
|
||||||
|
field=models.CharField(max_length=256, unique=True),
|
||||||
|
)
|
||||||
|
]
|
@ -232,6 +232,8 @@ class Countdown(RESTModelMixin, models.Model):
|
|||||||
|
|
||||||
access_permissions = CountdownAccessPermissions()
|
access_permissions = CountdownAccessPermissions()
|
||||||
|
|
||||||
|
title = models.CharField(max_length=256, unique=True, default="")
|
||||||
|
|
||||||
description = models.CharField(max_length=256, blank=True)
|
description = models.CharField(max_length=256, blank=True)
|
||||||
|
|
||||||
running = models.BooleanField(default=False)
|
running = models.BooleanField(default=False)
|
||||||
|
@ -165,7 +165,15 @@ class CountdownSerializer(ModelSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Countdown
|
model = Countdown
|
||||||
fields = ("id", "description", "default_time", "countdown_time", "running")
|
fields = (
|
||||||
|
"id",
|
||||||
|
"title",
|
||||||
|
"description",
|
||||||
|
"default_time",
|
||||||
|
"countdown_time",
|
||||||
|
"running",
|
||||||
|
)
|
||||||
|
unique_together = ("title",)
|
||||||
|
|
||||||
|
|
||||||
class HistorySerializer(ModelSerializer):
|
class HistorySerializer(ModelSerializer):
|
||||||
|
Loading…
Reference in New Issue
Block a user