UI: splitted Schedule into list- and single-view

This commit is contained in:
Patrick Haßel 2021-10-28 23:18:23 +02:00
parent 255d03da4e
commit ed2d5172bf
16 changed files with 358 additions and 183 deletions

View File

@ -2,43 +2,5 @@
// https://karma-runner.github.io/1.0/config/configuration-file.html // https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) { module.exports = function (config) {
config.set({ 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
});
}; };

View File

@ -21,4 +21,8 @@ export class ScheduleService {
this.api.postReturnItem("schedule/set/" + schedule.id + "/" + key, value, Schedule.fromJson, next, errorHandler); 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);
}
} }

View File

@ -1,8 +1,10 @@
import {NgModule} from '@angular/core'; import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router'; import {RouterModule, Routes} from '@angular/router';
import {ScheduleListComponent} from "./pages/schedule-list/schedule-list.component"; import {ScheduleListComponent} from "./pages/schedule-list/schedule-list.component";
import {ScheduleComponent} from "./pages/schedule/schedule.component";
const routes: Routes = [ const routes: Routes = [
{path: 'Schedule', component: ScheduleComponent},
{path: 'ScheduleList', component: ScheduleListComponent}, {path: 'ScheduleList', component: ScheduleListComponent},
{path: '**', redirectTo: '/ScheduleList'}, {path: '**', redirectTo: '/ScheduleList'},
]; ];

View File

@ -1,7 +1,13 @@
<div class="menubar"> <div class="menubar">
<div class="item" routerLink="/ScheduleList" routerLinkActive="itemActive"> <div class="item" routerLink="/ScheduleList" routerLinkActive="itemActive">
Zeitplan Zeitplan
</div> </div>
<div class="item breadcrumb" [routerLink]="['/Schedule', {id: dataService.schedule.id}]" routerLinkActive="itemActive" *ngIf="dataService.schedule">
{{dataService.schedule.name}}
</div>
</div> </div>
<div class="content"> <div class="content">

View File

@ -7,6 +7,10 @@
border-right: 1px solid black; border-right: 1px solid black;
} }
.breadcrumb {
background-color: lightgray;
}
.itemActive { .itemActive {
background-color: lightblue; background-color: lightblue;
} }

View File

@ -9,11 +9,13 @@ import {EditFieldComponent} from './shared/edit-field/edit-field.component';
import {ScheduleListComponent} from './pages/schedule-list/schedule-list.component'; import {ScheduleListComponent} from './pages/schedule-list/schedule-list.component';
import {FontAwesomeModule} from '@fortawesome/angular-fontawesome'; import {FontAwesomeModule} from '@fortawesome/angular-fontawesome';
import {NumberComponent} from './shared/number/number.component'; import {NumberComponent} from './shared/number/number.component';
import {ScheduleComponent} from "./pages/schedule/schedule.component";
@NgModule({ @NgModule({
declarations: [ declarations: [
AppComponent, AppComponent,
EditFieldComponent, EditFieldComponent,
ScheduleComponent,
ScheduleListComponent, ScheduleListComponent,
NumberComponent, NumberComponent,
], ],

View File

@ -1,10 +1,21 @@
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {Schedule} from "./api/schedule/Schedule";
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class DataService { export class DataService {
private _schedule?: Schedule;
get schedule(): Schedule | undefined {
return this._schedule;
}
set schedule(schedule: Schedule | undefined) {
this._schedule = schedule;
}
constructor() { constructor() {
} }

View File

@ -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> <table>
<ng-container *ngFor="let schedule of schedules; let first = first; trackBy: Schedule.trackBy"> <tr>
<tr *ngIf="!first" class="blank"> <th>&nbsp;</th>
<td colspan="21">&nbsp;</td> <th>Bezeichnung</th>
</tr> </tr>
<tr class="header"> <tr *ngFor="let schedule of schedules; trackBy: Schedule.trackBy">
<ng-container *ngTemplateOutlet="boolean;context:{schedule: schedule, value: schedule.enabled, key:'enabled'}"></ng-container> <td class="boolean" (click)="set(schedule, 'enabled', !schedule.enabled)" [class.true]="schedule.enabled" [class.false]="!schedule.enabled">
<td colspan="20">{{schedule.name}}</td> <fa-icon *ngIf="schedule.enabled" [icon]="faCheck"></fa-icon>
</tr> <fa-icon *ngIf="!schedule.enabled" [icon]="faTimes"></fa-icon>
<tr [class.disabled]="!schedule.enabled"> </td>
<th>&nbsp;</th> <td [routerLink]="['/Schedule', {id: schedule.id}]">
<th>Mo</th> {{schedule.name}}
<th>Di</th> </td>
<th>Mi</th> </tr>
<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 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>
</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>
[&nbsp;90°]
</option>
<option value="93">[&nbsp;93°]</option>
<option value="96">Bürgerliche Dämmerung [&nbsp;96°]</option>
<option value="99">[&nbsp;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(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">:&nbsp;</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">:&nbsp;</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> </table>

View File

@ -1,8 +1,6 @@
import {Component, OnInit} from '@angular/core'; import {Component, OnInit} from '@angular/core';
import {ScheduleService} from "../../api/schedule/schedule.service"; import {ScheduleService} from "../../api/schedule/schedule.service";
import {Schedule} from "../../api/schedule/Schedule"; 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 {faCheck, faTimes} from '@fortawesome/free-solid-svg-icons';
@Component({ @Component({
@ -20,7 +18,6 @@ export class ScheduleListComponent implements OnInit {
constructor( constructor(
readonly scheduleService: ScheduleService, readonly scheduleService: ScheduleService,
readonly scheduleEntryService: ScheduleEntryService,
) { ) {
// nothing // nothing
} }
@ -29,12 +26,8 @@ export class ScheduleListComponent implements OnInit {
this.scheduleService.findAll(schedules => this.schedules = schedules, Schedule.compareName); this.scheduleService.findAll(schedules => this.schedules = schedules, Schedule.compareName);
} }
set(schedule: Schedule, entry: ScheduleEntry, key: string, value: any): void { set(schedule: Schedule, key: string, value: any): void {
if (entry) { this.scheduleService.set(schedule, key, value, schedule => this.updateSchedule(schedule));
this.scheduleEntryService.set(entry, key, value, entry => this.updateEntry(schedule, entry));
} else {
this.scheduleService.set(schedule, key, value, schedule => this.updateSchedule(schedule));
}
} }
private updateSchedule(schedule: Schedule): void { private updateSchedule(schedule: Schedule): void {
@ -47,14 +40,4 @@ export class ScheduleListComponent implements OnInit {
this.schedules = this.schedules.sort(Schedule.compareName) 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)
}
} }

View 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>&nbsp;</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>
[&nbsp;90°]
</option>
<option value="93">[&nbsp;93°]</option>
<option value="96">Bürgerliche Dämmerung [&nbsp;96°]</option>
<option value="99">[&nbsp;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">:&nbsp;</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">:&nbsp;</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>

View File

@ -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;
}
}

View File

@ -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();
});
});

View File

@ -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)
}
}

View File

@ -20,6 +20,11 @@ public class ScheduleController {
return scheduleReadService.findAllDtos(); return scheduleReadService.findAllDtos();
} }
@GetMapping("findById/{id}")
public ScheduleDto findById(@PathVariable final long id) {
return scheduleReadService.getDtoById(id);
}
@GetMapping("findAllNext") @GetMapping("findAllNext")
public List<ScheduleNextExecutionDto> findAllNext() { public List<ScheduleNextExecutionDto> findAllNext() {
return scheduleReadService.findAllNextExecutionDtos(); return scheduleReadService.findAllNextExecutionDtos();
@ -27,7 +32,12 @@ public class ScheduleController {
@PostMapping("set/{id}/enabled") @PostMapping("set/{id}/enabled")
public ScheduleDto setEnabled(@PathVariable final long id, @RequestBody final boolean 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);
} }
} }

View File

@ -50,4 +50,8 @@ public class ScheduleReadService {
return scheduleRepository.getByEntriesContaining(entry); return scheduleRepository.getByEntriesContaining(entry);
} }
public ScheduleDto getDtoById(final long id) {
return scheduleMapper.toDto(get(id));
}
} }

View File

@ -6,6 +6,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.function.BiConsumer;
@Slf4j @Slf4j
@Service @Service
@ -19,9 +20,9 @@ public class ScheduleWriteService {
private final ScheduleMapper scheduleMapper; 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); final Schedule schedule = scheduleReadService.get(id);
schedule.setEnabled(enabled); setter.accept(schedule, value);
scheduleCalculationService.calculateSchedule(schedule, ZonedDateTime.now()); scheduleCalculationService.calculateSchedule(schedule, ZonedDateTime.now());
return scheduleMapper.toDto(schedule); return scheduleMapper.toDto(schedule);
} }