diff --git a/src/main/angular/karma.conf.js b/src/main/angular/karma.conf.js
index 069d9fd..e77e607 100644
--- a/src/main/angular/karma.conf.js
+++ b/src/main/angular/karma.conf.js
@@ -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();
};
diff --git a/src/main/angular/src/app/api/schedule/schedule.service.ts b/src/main/angular/src/app/api/schedule/schedule.service.ts
index f25751d..0cbaaac 100644
--- a/src/main/angular/src/app/api/schedule/schedule.service.ts
+++ b/src/main/angular/src/app/api/schedule/schedule.service.ts
@@ -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);
+ }
+
}
diff --git a/src/main/angular/src/app/app-routing.module.ts b/src/main/angular/src/app/app-routing.module.ts
index f85a9aa..bf7d9c3 100644
--- a/src/main/angular/src/app/app-routing.module.ts
+++ b/src/main/angular/src/app/app-routing.module.ts
@@ -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'},
];
diff --git a/src/main/angular/src/app/app.component.html b/src/main/angular/src/app/app.component.html
index c2c6df5..a8b1f0d 100644
--- a/src/main/angular/src/app/app.component.html
+++ b/src/main/angular/src/app/app.component.html
@@ -1,7 +1,13 @@
diff --git a/src/main/angular/src/app/app.component.less b/src/main/angular/src/app/app.component.less
index 432091f..f4bbbdb 100644
--- a/src/main/angular/src/app/app.component.less
+++ b/src/main/angular/src/app/app.component.less
@@ -7,6 +7,10 @@
border-right: 1px solid black;
}
+ .breadcrumb {
+ background-color: lightgray;
+ }
+
.itemActive {
background-color: lightblue;
}
diff --git a/src/main/angular/src/app/app.module.ts b/src/main/angular/src/app/app.module.ts
index 3094896..b9a730f 100644
--- a/src/main/angular/src/app/app.module.ts
+++ b/src/main/angular/src/app/app.module.ts
@@ -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,
],
diff --git a/src/main/angular/src/app/data.service.ts b/src/main/angular/src/app/data.service.ts
index 4e43f91..b02899d 100644
--- a/src/main/angular/src/app/data.service.ts
+++ b/src/main/angular/src/app/data.service.ts
@@ -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() {
}
diff --git a/src/main/angular/src/app/pages/schedule-list/schedule-list.component.html b/src/main/angular/src/app/pages/schedule-list/schedule-list.component.html
index 8948903..0e7db62 100644
--- a/src/main/angular/src/app/pages/schedule-list/schedule-list.component.html
+++ b/src/main/angular/src/app/pages/schedule-list/schedule-list.component.html
@@ -1,124 +1,15 @@
-
-
-
-
- |
-
-
-
-
- | |
-
-
-
- | |
- Mo |
- Di |
- Mi |
- Do |
- Fr |
- Sa |
- So |
- Typ |
- Sonnenstand |
- Uhrzeit |
- Unschärfe |
- Nächste Ausführung |
-
-
-
-
-
-
-
-
-
-
-
- |
-
- |
-
-
-
-
- |
-
- |
-
-
-
-
- |
- : |
-
-
- |
-
- |
-
-
-
- |
-
-
- 0">{{entry.nextClearTimestamp.dayName}} |
- 0">: |
- 0">{{entry.nextClearTimestamp.timeString}} |
-
-
- |
- |
- |
-
-
- 0">
- {{entry.nextFuzzyTimestamp.dayName}} |
- : |
- {{entry.nextFuzzyTimestamp.timeString}} |
-
-
- |
- |
- |
-
-
-
-
+
+ | |
+ Bezeichnung |
+
+
+ |
+
+
+ |
+
+ {{schedule.name}}
+ |
+
diff --git a/src/main/angular/src/app/pages/schedule-list/schedule-list.component.ts b/src/main/angular/src/app/pages/schedule-list/schedule-list.component.ts
index 7f59fac..a1cf64c 100644
--- a/src/main/angular/src/app/pages/schedule-list/schedule-list.component.ts
+++ b/src/main/angular/src/app/pages/schedule-list/schedule-list.component.ts
@@ -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,12 +26,8 @@ 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 {
- this.scheduleService.set(schedule, key, value, schedule => this.updateSchedule(schedule));
- }
+ set(schedule: Schedule, key: string, value: any): void {
+ this.scheduleService.set(schedule, key, value, schedule => this.updateSchedule(schedule));
}
private updateSchedule(schedule: Schedule): void {
@@ -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)
- }
-
}
diff --git a/src/main/angular/src/app/pages/schedule/schedule.component.html b/src/main/angular/src/app/pages/schedule/schedule.component.html
new file mode 100644
index 0000000..04976b6
--- /dev/null
+++ b/src/main/angular/src/app/pages/schedule/schedule.component.html
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+ |
+
+
+
+
+
+ | |
+ Mo |
+ Di |
+ Mi |
+ Do |
+ Fr |
+ Sa |
+ So |
+ Typ |
+ Sonnenstand |
+ Uhrzeit |
+ Unschärfe |
+ Nächste Ausführung |
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+ |
+
+
+
+
+ |
+
+ |
+
+
+
+
+ |
+ : |
+
+
+ |
+
+ |
+
+
+
+ |
+
+
+ 0">{{entry.nextClearTimestamp.dayName}} |
+ 0">: |
+ 0">{{entry.nextClearTimestamp.timeString}} |
+
+
+ |
+ |
+ |
+
+
+ 0">
+ {{entry.nextFuzzyTimestamp.dayName}} |
+ : |
+ {{entry.nextFuzzyTimestamp.timeString}} |
+
+
+ |
+ |
+ |
+
+
+
+
+
+
diff --git a/src/main/angular/src/app/pages/schedule/schedule.component.less b/src/main/angular/src/app/pages/schedule/schedule.component.less
new file mode 100644
index 0000000..da84fc9
--- /dev/null
+++ b/src/main/angular/src/app/pages/schedule/schedule.component.less
@@ -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;
+ }
+}
diff --git a/src/main/angular/src/app/pages/schedule/schedule.component.spec.ts b/src/main/angular/src/app/pages/schedule/schedule.component.spec.ts
new file mode 100644
index 0000000..c841428
--- /dev/null
+++ b/src/main/angular/src/app/pages/schedule/schedule.component.spec.ts
@@ -0,0 +1,25 @@
+import {ComponentFixture, TestBed} from '@angular/core/testing';
+
+import {ScheduleComponent} from './schedule.component';
+
+describe('ScheduleComponent', () => {
+ let component: ScheduleComponent;
+ let fixture: ComponentFixture
;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ScheduleComponent]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ScheduleComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/main/angular/src/app/pages/schedule/schedule.component.ts b/src/main/angular/src/app/pages/schedule/schedule.component.ts
new file mode 100644
index 0000000..7d7ad82
--- /dev/null
+++ b/src/main/angular/src/app/pages/schedule/schedule.component.ts
@@ -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)
+ }
+
+}
diff --git a/src/main/java/de/ph87/homeautomation/schedule/ScheduleController.java b/src/main/java/de/ph87/homeautomation/schedule/ScheduleController.java
index 62e5a84..0648337 100644
--- a/src/main/java/de/ph87/homeautomation/schedule/ScheduleController.java
+++ b/src/main/java/de/ph87/homeautomation/schedule/ScheduleController.java
@@ -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 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);
}
}
diff --git a/src/main/java/de/ph87/homeautomation/schedule/ScheduleReadService.java b/src/main/java/de/ph87/homeautomation/schedule/ScheduleReadService.java
index f1df13f..105c33a 100644
--- a/src/main/java/de/ph87/homeautomation/schedule/ScheduleReadService.java
+++ b/src/main/java/de/ph87/homeautomation/schedule/ScheduleReadService.java
@@ -50,4 +50,8 @@ public class ScheduleReadService {
return scheduleRepository.getByEntriesContaining(entry);
}
+ public ScheduleDto getDtoById(final long id) {
+ return scheduleMapper.toDto(get(id));
+ }
+
}
diff --git a/src/main/java/de/ph87/homeautomation/schedule/ScheduleWriteService.java b/src/main/java/de/ph87/homeautomation/schedule/ScheduleWriteService.java
index 0460532..1dffbfc 100644
--- a/src/main/java/de/ph87/homeautomation/schedule/ScheduleWriteService.java
+++ b/src/main/java/de/ph87/homeautomation/schedule/ScheduleWriteService.java
@@ -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 ScheduleDto set(final long id, final BiConsumer 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);
}