UI: splitted Schedule into list- and single-view
This commit is contained in:
parent
255d03da4e
commit
ed2d5172bf
@ -2,43 +2,5 @@
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage'),
|
||||
require('@angular-devkit/build-angular/plugins/karma')
|
||||
],
|
||||
client: {
|
||||
jasmine: {
|
||||
// you can add configuration options for Jasmine here
|
||||
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
|
||||
// for example, you can disable the random execution with `random: false`
|
||||
// or set a specific seed with `seed: 4321`
|
||||
},
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
jasmineHtmlReporter: {
|
||||
suppressAll: true // removes the duplicated traces
|
||||
},
|
||||
coverageReporter: {
|
||||
dir: require('path').join(__dirname, './coverage/angular'),
|
||||
subdir: '.',
|
||||
reporters: [
|
||||
{type: 'html'},
|
||||
{type: 'text-summary'}
|
||||
]
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false,
|
||||
restartOnFileChange: true
|
||||
});
|
||||
config.set();
|
||||
};
|
||||
|
||||
@ -21,4 +21,8 @@ export class ScheduleService {
|
||||
this.api.postReturnItem("schedule/set/" + schedule.id + "/" + key, value, Schedule.fromJson, next, errorHandler);
|
||||
}
|
||||
|
||||
findById(id: number, next: (item: Schedule) => void, errorHandler: (error: any) => void = NO_OP): void {
|
||||
this.api.getItem("schedule/findById/" + id, Schedule.fromJson, next, errorHandler);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import {NgModule} from '@angular/core';
|
||||
import {RouterModule, Routes} from '@angular/router';
|
||||
import {ScheduleListComponent} from "./pages/schedule-list/schedule-list.component";
|
||||
import {ScheduleComponent} from "./pages/schedule/schedule.component";
|
||||
|
||||
const routes: Routes = [
|
||||
{path: 'Schedule', component: ScheduleComponent},
|
||||
{path: 'ScheduleList', component: ScheduleListComponent},
|
||||
{path: '**', redirectTo: '/ScheduleList'},
|
||||
];
|
||||
|
||||
@ -1,7 +1,13 @@
|
||||
<div class="menubar">
|
||||
|
||||
<div class="item" routerLink="/ScheduleList" routerLinkActive="itemActive">
|
||||
Zeitplan
|
||||
</div>
|
||||
|
||||
<div class="item breadcrumb" [routerLink]="['/Schedule', {id: dataService.schedule.id}]" routerLinkActive="itemActive" *ngIf="dataService.schedule">
|
||||
{{dataService.schedule.name}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
|
||||
@ -7,6 +7,10 @@
|
||||
border-right: 1px solid black;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
background-color: lightgray;
|
||||
}
|
||||
|
||||
.itemActive {
|
||||
background-color: lightblue;
|
||||
}
|
||||
|
||||
@ -9,11 +9,13 @@ import {EditFieldComponent} from './shared/edit-field/edit-field.component';
|
||||
import {ScheduleListComponent} from './pages/schedule-list/schedule-list.component';
|
||||
import {FontAwesomeModule} from '@fortawesome/angular-fontawesome';
|
||||
import {NumberComponent} from './shared/number/number.component';
|
||||
import {ScheduleComponent} from "./pages/schedule/schedule.component";
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
EditFieldComponent,
|
||||
ScheduleComponent,
|
||||
ScheduleListComponent,
|
||||
NumberComponent,
|
||||
],
|
||||
|
||||
@ -1,10 +1,21 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {Schedule} from "./api/schedule/Schedule";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DataService {
|
||||
|
||||
private _schedule?: Schedule;
|
||||
|
||||
get schedule(): Schedule | undefined {
|
||||
return this._schedule;
|
||||
}
|
||||
|
||||
set schedule(schedule: Schedule | undefined) {
|
||||
this._schedule = schedule;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
|
||||
@ -1,124 +1,15 @@
|
||||
<ng-template #boolean let-schedule="schedule" let-entry="entry" let-value="value" let-key="key">
|
||||
<td class="boolean" (click)="set(schedule, entry, key, !value)" [class.true]="value" [class.false]="!value">
|
||||
<fa-icon *ngIf="value" [icon]="faCheck"></fa-icon>
|
||||
<fa-icon *ngIf="!value" [icon]="faTimes"></fa-icon>
|
||||
</td>
|
||||
</ng-template>
|
||||
|
||||
<table>
|
||||
<ng-container *ngFor="let schedule of schedules; let first = first; trackBy: Schedule.trackBy">
|
||||
<tr *ngIf="!first" class="blank">
|
||||
<td colspan="21"> </td>
|
||||
</tr>
|
||||
<tr class="header">
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{schedule: schedule, value: schedule.enabled, key:'enabled'}"></ng-container>
|
||||
<td colspan="20">{{schedule.name}}</td>
|
||||
</tr>
|
||||
<tr [class.disabled]="!schedule.enabled">
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th>Mo</th>
|
||||
<th>Di</th>
|
||||
<th>Mi</th>
|
||||
<th>Do</th>
|
||||
<th>Fr</th>
|
||||
<th>Sa</th>
|
||||
<th>So</th>
|
||||
<th>Typ</th>
|
||||
<th>Sonnenstand</th>
|
||||
<th colspan="3">Uhrzeit</th>
|
||||
<th>Unschärfe</th>
|
||||
<th colspan="6">Nächste Ausführung</th>
|
||||
<th>Bezeichnung</th>
|
||||
</tr>
|
||||
<tr *ngFor="let entry of schedule.entries" [class.disabled]="entry.nextClearTimestamp === null">
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{schedule: schedule, entry: entry, value: entry.enabled, key:'enabled'}"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{schedule: schedule, entry: entry, value: entry.monday, key:'monday'}"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{schedule: schedule, entry: entry, value: entry.tuesday, key:'tuesday'}"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{schedule: schedule, entry: entry, value: entry.wednesday, key:'wednesday'}"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{schedule: schedule, entry: entry, value: entry.thursday, key:'thursday'}"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{schedule: schedule, entry: entry, value: entry.friday, key:'friday'}"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{schedule: schedule, entry: entry, value: entry.saturday, key:'saturday'}"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{schedule: schedule, entry: entry, value: entry.sunday, key:'sunday'}"></ng-container>
|
||||
|
||||
<td>
|
||||
<select [(ngModel)]="entry.type" (ngModelChange)="set(schedule, entry, 'type', entry.type)">
|
||||
<option value="TIME">Uhrzeit</option>
|
||||
<option value="SUNRISE">Sonnenaufgang</option>
|
||||
<option value="SUNSET">Sonnenuntergang</option>
|
||||
</select>
|
||||
<tr *ngFor="let schedule of schedules; trackBy: Schedule.trackBy">
|
||||
<td class="boolean" (click)="set(schedule, 'enabled', !schedule.enabled)" [class.true]="schedule.enabled" [class.false]="!schedule.enabled">
|
||||
<fa-icon *ngIf="schedule.enabled" [icon]="faCheck"></fa-icon>
|
||||
<fa-icon *ngIf="!schedule.enabled" [icon]="faTimes"></fa-icon>
|
||||
</td>
|
||||
|
||||
<ng-container *ngIf="entry.type === 'SUNRISE' || entry.type === 'SUNSET'">
|
||||
<td>
|
||||
<select class="number" [(ngModel)]="entry.zenith" (ngModelChange)="set(schedule, entry, 'zenith', entry.zenith)">
|
||||
<option value="90.8333">
|
||||
<ng-container *ngIf="entry.type === 'SUNRISE'">Sonnenaufgang</ng-container>
|
||||
<ng-container *ngIf="entry.type === 'SUNSET'">Sonnenuntergang</ng-container>
|
||||
[ 90°]
|
||||
</option>
|
||||
<option value="93">[ 93°]</option>
|
||||
<option value="96">Bürgerliche Dämmerung [ 96°]</option>
|
||||
<option value="99">[ 99°]</option>
|
||||
<option value="102">Nautische Dämmerung [102°]</option>
|
||||
<option value="105">[105°]</option>
|
||||
<option value="108">Astronomische Dämmerung [108°]</option>
|
||||
</select>
|
||||
<td [routerLink]="['/Schedule', {id: schedule.id}]">
|
||||
{{schedule.name}}
|
||||
</td>
|
||||
</ng-container>
|
||||
<td *ngIf="entry.type !== 'SUNRISE' && entry.type !== 'SUNSET'" class="empty"></td>
|
||||
|
||||
<ng-container *ngIf="entry.type === 'TIME'">
|
||||
<td class="first">
|
||||
<select class="number" [(ngModel)]="entry.hour" (ngModelChange)="set(schedule, entry, 'hour', entry.hour)">
|
||||
<option *ngFor="let _ of [].constructor(60); let value = index" [ngValue]="value">{{value}}</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class="middle">:</td>
|
||||
<td class="last">
|
||||
<select class="number" [(ngModel)]="entry.minute" (ngModelChange)="set(schedule, entry, 'minute', entry.minute)">
|
||||
<option *ngFor="let _ of [].constructor(60); let value = index" [ngValue]="value">{{value | number:'2.0'}}</option>
|
||||
</select>
|
||||
</td>
|
||||
</ng-container>
|
||||
<td *ngIf="entry.type !== 'TIME'" colspan="3" class="empty"></td>
|
||||
|
||||
<td>
|
||||
<select class="number" [(ngModel)]="entry.fuzzySeconds" (ngModelChange)="set(schedule, entry, 'fuzzySeconds', entry.fuzzySeconds)">
|
||||
<option [ngValue]="0">Keine</option>
|
||||
<option [ngValue]="60">1 Minute</option>
|
||||
<option [ngValue]="300">5 Minuten</option>
|
||||
<option [ngValue]="600">10 Minuten</option>
|
||||
<option [ngValue]="1800">30 Minuten</option>
|
||||
<option [ngValue]="3600">1 Stunde</option>
|
||||
<option [ngValue]="7200">2 Stunden</option>
|
||||
<option [ngValue]="10800">3 Stunden</option>
|
||||
<option [ngValue]="21600">6 Stunden</option>
|
||||
<option [ngValue]="43200">12 Stunden</option>
|
||||
<option [ngValue]="86400">1 Tag</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<ng-container *ngIf="entry.nextClearTimestamp">
|
||||
<td class="number first" [class.empty]="entry.fuzzySeconds > 0">{{entry.nextClearTimestamp.dayName}}</td>
|
||||
<td class="number middle" [class.empty]="entry.fuzzySeconds > 0">: </td>
|
||||
<td class="number last" [class.empty]="entry.fuzzySeconds > 0">{{entry.nextClearTimestamp.timeString}}</td>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!entry.nextClearTimestamp">
|
||||
<td class="empty first"></td>
|
||||
<td class="empty middle"></td>
|
||||
<td class="empty last"></td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="entry.nextFuzzyTimestamp && entry.fuzzySeconds > 0">
|
||||
<td class="number first">{{entry.nextFuzzyTimestamp.dayName}}</td>
|
||||
<td class="number middle">: </td>
|
||||
<td class="number last">{{entry.nextFuzzyTimestamp.timeString}}</td>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!entry.nextFuzzyTimestamp || entry.fuzzySeconds <= 0">
|
||||
<td class="empty first"></td>
|
||||
<td class="empty middle"></td>
|
||||
<td class="empty last"></td>
|
||||
</ng-container>
|
||||
|
||||
</tr>
|
||||
</ng-container>
|
||||
</table>
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {ScheduleService} from "../../api/schedule/schedule.service";
|
||||
import {Schedule} from "../../api/schedule/Schedule";
|
||||
import {ScheduleEntry} from "../../api/schedule/entry/ScheduleEntry";
|
||||
import {ScheduleEntryService} from "../../api/schedule/entry/schedule-entry.service";
|
||||
import {faCheck, faTimes} from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
@Component({
|
||||
@ -20,7 +18,6 @@ export class ScheduleListComponent implements OnInit {
|
||||
|
||||
constructor(
|
||||
readonly scheduleService: ScheduleService,
|
||||
readonly scheduleEntryService: ScheduleEntryService,
|
||||
) {
|
||||
// nothing
|
||||
}
|
||||
@ -29,13 +26,9 @@ export class ScheduleListComponent implements OnInit {
|
||||
this.scheduleService.findAll(schedules => this.schedules = schedules, Schedule.compareName);
|
||||
}
|
||||
|
||||
set(schedule: Schedule, entry: ScheduleEntry, key: string, value: any): void {
|
||||
if (entry) {
|
||||
this.scheduleEntryService.set(entry, key, value, entry => this.updateEntry(schedule, entry));
|
||||
} else {
|
||||
set(schedule: Schedule, key: string, value: any): void {
|
||||
this.scheduleService.set(schedule, key, value, schedule => this.updateSchedule(schedule));
|
||||
}
|
||||
}
|
||||
|
||||
private updateSchedule(schedule: Schedule): void {
|
||||
const index: number = this.schedules.findIndex(s => s.id === schedule.id);
|
||||
@ -47,14 +40,4 @@ export class ScheduleListComponent implements OnInit {
|
||||
this.schedules = this.schedules.sort(Schedule.compareName)
|
||||
}
|
||||
|
||||
private updateEntry(schedule: Schedule, entry: ScheduleEntry): void {
|
||||
const index: number = schedule.entries.findIndex(s => s.id === entry.id);
|
||||
if (index < 0) {
|
||||
schedule.entries.push(entry);
|
||||
} else {
|
||||
schedule.entries[index] = entry;
|
||||
}
|
||||
schedule.entries = schedule.entries.sort(ScheduleEntry.compareId)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
125
src/main/angular/src/app/pages/schedule/schedule.component.html
Normal file
125
src/main/angular/src/app/pages/schedule/schedule.component.html
Normal file
@ -0,0 +1,125 @@
|
||||
<ng-container *ngIf="dataService.schedule">
|
||||
|
||||
<ng-template #boolean let-entry="entry" let-value="value" let-key="key">
|
||||
<td class="boolean" (click)="set(entry, key, !value)" [class.true]="value" [class.false]="!value">
|
||||
<fa-icon *ngIf="value" [icon]="faCheck"></fa-icon>
|
||||
<fa-icon *ngIf="!value" [icon]="faTimes"></fa-icon>
|
||||
</td>
|
||||
</ng-template>
|
||||
|
||||
<table>
|
||||
<tr class="header">
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{schedule: dataService.schedule, value: dataService.schedule.enabled, key:'enabled'}"></ng-container>
|
||||
<td colspan="20">
|
||||
<app-edit-field [initial]="dataService.schedule.name" (valueChange)="set(null, 'name', $event)"></app-edit-field>
|
||||
</td>
|
||||
</tr>
|
||||
<tr [class.disabled]="!dataService.schedule.enabled">
|
||||
<th> </th>
|
||||
<th>Mo</th>
|
||||
<th>Di</th>
|
||||
<th>Mi</th>
|
||||
<th>Do</th>
|
||||
<th>Fr</th>
|
||||
<th>Sa</th>
|
||||
<th>So</th>
|
||||
<th>Typ</th>
|
||||
<th>Sonnenstand</th>
|
||||
<th colspan="3">Uhrzeit</th>
|
||||
<th>Unschärfe</th>
|
||||
<th colspan="6">Nächste Ausführung</th>
|
||||
</tr>
|
||||
<tr *ngFor="let entry of dataService.schedule.entries" [class.disabled]="entry.nextClearTimestamp === null">
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{entry: entry, value: entry.enabled, key:'enabled'}"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{entry: entry, value: entry.monday, key:'monday'}"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{entry: entry, value: entry.tuesday, key:'tuesday'}"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{entry: entry, value: entry.wednesday, key:'wednesday'}"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{entry: entry, value: entry.thursday, key:'thursday'}"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{entry: entry, value: entry.friday, key:'friday'}"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{entry: entry, value: entry.saturday, key:'saturday'}"></ng-container>
|
||||
<ng-container *ngTemplateOutlet="boolean;context:{entry: entry, value: entry.sunday, key:'sunday'}"></ng-container>
|
||||
|
||||
<td>
|
||||
<select [(ngModel)]="entry.type" (ngModelChange)="set(entry, 'type', entry.type)">
|
||||
<option value="TIME">Uhrzeit</option>
|
||||
<option value="SUNRISE">Sonnenaufgang</option>
|
||||
<option value="SUNSET">Sonnenuntergang</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<ng-container *ngIf="entry.type === 'SUNRISE' || entry.type === 'SUNSET'">
|
||||
<td>
|
||||
<select class="number" [(ngModel)]="entry.zenith" (ngModelChange)="set(entry, 'zenith', entry.zenith)">
|
||||
<option value="90.8333">
|
||||
<ng-container *ngIf="entry.type === 'SUNRISE'">Sonnenaufgang</ng-container>
|
||||
<ng-container *ngIf="entry.type === 'SUNSET'">Sonnenuntergang</ng-container>
|
||||
[ 90°]
|
||||
</option>
|
||||
<option value="93">[ 93°]</option>
|
||||
<option value="96">Bürgerliche Dämmerung [ 96°]</option>
|
||||
<option value="99">[ 99°]</option>
|
||||
<option value="102">Nautische Dämmerung [102°]</option>
|
||||
<option value="105">[105°]</option>
|
||||
<option value="108">Astronomische Dämmerung [108°]</option>
|
||||
</select>
|
||||
</td>
|
||||
</ng-container>
|
||||
<td *ngIf="entry.type !== 'SUNRISE' && entry.type !== 'SUNSET'" class="empty"></td>
|
||||
|
||||
<ng-container *ngIf="entry.type === 'TIME'">
|
||||
<td class="first">
|
||||
<select class="number" [(ngModel)]="entry.hour" (ngModelChange)="set(entry, 'hour', entry.hour)">
|
||||
<option *ngFor="let _ of [].constructor(60); let value = index" [ngValue]="value">{{value}}</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class="middle">:</td>
|
||||
<td class="last">
|
||||
<select class="number" [(ngModel)]="entry.minute" (ngModelChange)="set(entry, 'minute', entry.minute)">
|
||||
<option *ngFor="let _ of [].constructor(60); let value = index" [ngValue]="value">{{value | number:'2.0'}}</option>
|
||||
</select>
|
||||
</td>
|
||||
</ng-container>
|
||||
<td *ngIf="entry.type !== 'TIME'" colspan="3" class="empty"></td>
|
||||
|
||||
<td>
|
||||
<select class="number" [(ngModel)]="entry.fuzzySeconds" (ngModelChange)="set(entry, 'fuzzySeconds', entry.fuzzySeconds)">
|
||||
<option [ngValue]="0">Keine</option>
|
||||
<option [ngValue]="60">1 Minute</option>
|
||||
<option [ngValue]="300">5 Minuten</option>
|
||||
<option [ngValue]="600">10 Minuten</option>
|
||||
<option [ngValue]="1800">30 Minuten</option>
|
||||
<option [ngValue]="3600">1 Stunde</option>
|
||||
<option [ngValue]="7200">2 Stunden</option>
|
||||
<option [ngValue]="10800">3 Stunden</option>
|
||||
<option [ngValue]="21600">6 Stunden</option>
|
||||
<option [ngValue]="43200">12 Stunden</option>
|
||||
<option [ngValue]="86400">1 Tag</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<ng-container *ngIf="entry.nextClearTimestamp">
|
||||
<td class="number first" [class.empty]="entry.fuzzySeconds > 0">{{entry.nextClearTimestamp.dayName}}</td>
|
||||
<td class="number middle" [class.empty]="entry.fuzzySeconds > 0">: </td>
|
||||
<td class="number last" [class.empty]="entry.fuzzySeconds > 0">{{entry.nextClearTimestamp.timeString}}</td>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!entry.nextClearTimestamp">
|
||||
<td class="empty first"></td>
|
||||
<td class="empty middle"></td>
|
||||
<td class="empty last"></td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="entry.nextFuzzyTimestamp && entry.fuzzySeconds > 0">
|
||||
<td class="number first">{{entry.nextFuzzyTimestamp.dayName}}</td>
|
||||
<td class="number middle">: </td>
|
||||
<td class="number last">{{entry.nextFuzzyTimestamp.timeString}}</td>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!entry.nextFuzzyTimestamp || entry.fuzzySeconds <= 0">
|
||||
<td class="empty first"></td>
|
||||
<td class="empty middle"></td>
|
||||
<td class="empty last"></td>
|
||||
</ng-container>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</ng-container>
|
||||
@ -0,0 +1,83 @@
|
||||
select {
|
||||
background-color: transparent;
|
||||
border-width: 0;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: lightblue;
|
||||
}
|
||||
|
||||
tr.blank {
|
||||
|
||||
th, td {
|
||||
border: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tr.header {
|
||||
|
||||
th:not(:first-child), td:not(:first-child) {
|
||||
border: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.empty {
|
||||
text-align: center;
|
||||
color: gray;
|
||||
background-color: #DDDDDD;
|
||||
}
|
||||
|
||||
.boolean {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.true {
|
||||
background-color: palegreen;
|
||||
}
|
||||
|
||||
.false {
|
||||
background-color: indianred;
|
||||
}
|
||||
|
||||
.number {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.full {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.first {
|
||||
border-right-width: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.minute {
|
||||
border-right-width: 0;
|
||||
border-left-width: 0;
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.last {
|
||||
border-left-width: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.middle {
|
||||
border-right-width: 0;
|
||||
border-left-width: 0;
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
* {
|
||||
background-color: gray;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {ScheduleComponent} from './schedule.component';
|
||||
|
||||
describe('ScheduleComponent', () => {
|
||||
let component: ScheduleComponent;
|
||||
let fixture: ComponentFixture<ScheduleComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ScheduleComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ScheduleComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,62 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {ScheduleService} from "../../api/schedule/schedule.service";
|
||||
import {Schedule} from "../../api/schedule/Schedule";
|
||||
import {ScheduleEntry} from "../../api/schedule/entry/ScheduleEntry";
|
||||
import {ScheduleEntryService} from "../../api/schedule/entry/schedule-entry.service";
|
||||
import {faCheck, faTimes} from '@fortawesome/free-solid-svg-icons';
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {DataService} from "../../data.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-schedule',
|
||||
templateUrl: './schedule.component.html',
|
||||
styleUrls: ['./schedule.component.less']
|
||||
})
|
||||
export class ScheduleComponent implements OnInit {
|
||||
|
||||
readonly faCheck = faCheck;
|
||||
readonly faTimes = faTimes;
|
||||
readonly Schedule = Schedule;
|
||||
|
||||
constructor(
|
||||
readonly activatedRoute: ActivatedRoute,
|
||||
readonly scheduleService: ScheduleService,
|
||||
readonly scheduleEntryService: ScheduleEntryService,
|
||||
readonly dataService: DataService,
|
||||
) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.dataService.schedule = undefined;
|
||||
this.activatedRoute.params.subscribe(params => this.scheduleService.findById(params.id, schedule => this.setSchedule(schedule)));
|
||||
}
|
||||
|
||||
private setSchedule(schedule: Schedule): void {
|
||||
this.dataService.schedule = schedule;
|
||||
}
|
||||
|
||||
set(entry: ScheduleEntry | null, key: string, value: any): void {
|
||||
if (entry) {
|
||||
this.scheduleEntryService.set(entry, key, value, entry => this.updateEntry(entry));
|
||||
} else {
|
||||
if (this.dataService.schedule) {
|
||||
this.scheduleService.set(this.dataService.schedule, key, value, schedule => this.dataService.schedule = schedule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private updateEntry(entry: ScheduleEntry): void {
|
||||
if (!this.dataService.schedule) {
|
||||
return;
|
||||
}
|
||||
const index: number = this.dataService.schedule.entries.findIndex(s => s.id === entry.id);
|
||||
if (index < 0) {
|
||||
this.dataService.schedule.entries.push(entry);
|
||||
} else {
|
||||
this.dataService.schedule.entries[index] = entry;
|
||||
}
|
||||
this.dataService.schedule.entries = this.dataService.schedule.entries.sort(ScheduleEntry.compareId)
|
||||
}
|
||||
|
||||
}
|
||||
@ -20,6 +20,11 @@ public class ScheduleController {
|
||||
return scheduleReadService.findAllDtos();
|
||||
}
|
||||
|
||||
@GetMapping("findById/{id}")
|
||||
public ScheduleDto findById(@PathVariable final long id) {
|
||||
return scheduleReadService.getDtoById(id);
|
||||
}
|
||||
|
||||
@GetMapping("findAllNext")
|
||||
public List<ScheduleNextExecutionDto> findAllNext() {
|
||||
return scheduleReadService.findAllNextExecutionDtos();
|
||||
@ -27,7 +32,12 @@ public class ScheduleController {
|
||||
|
||||
@PostMapping("set/{id}/enabled")
|
||||
public ScheduleDto setEnabled(@PathVariable final long id, @RequestBody final boolean enabled) {
|
||||
return scheduleWriteService.setEnabled(id, enabled);
|
||||
return scheduleWriteService.set(id, Schedule::setEnabled, enabled);
|
||||
}
|
||||
|
||||
@PostMapping("set/{id}/name")
|
||||
public ScheduleDto setName(@PathVariable final long id, @RequestBody final String name) {
|
||||
return scheduleWriteService.set(id, Schedule::setName, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -50,4 +50,8 @@ public class ScheduleReadService {
|
||||
return scheduleRepository.getByEntriesContaining(entry);
|
||||
}
|
||||
|
||||
public ScheduleDto getDtoById(final long id) {
|
||||
return scheduleMapper.toDto(get(id));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ -19,9 +20,9 @@ public class ScheduleWriteService {
|
||||
|
||||
private final ScheduleMapper scheduleMapper;
|
||||
|
||||
public ScheduleDto setEnabled(final long id, final boolean enabled) {
|
||||
public <T> ScheduleDto set(final long id, final BiConsumer<Schedule, T> setter, final T value) {
|
||||
final Schedule schedule = scheduleReadService.get(id);
|
||||
schedule.setEnabled(enabled);
|
||||
setter.accept(schedule, value);
|
||||
scheduleCalculationService.calculateSchedule(schedule, ZonedDateTime.now());
|
||||
return scheduleMapper.toDto(schedule);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user