Schedule publish refactor + a lot code clean

This commit is contained in:
Patrick Haßel 2022-10-25 13:50:55 +02:00
parent 2dbb1bc42f
commit db79d17f7d
44 changed files with 470 additions and 627 deletions

View File

@ -1,7 +1,7 @@
import {Injectable} from '@angular/core';
import {NO_OP} from "./api.service";
import {Page} from "./Page";
import {Error, FromJson, IEntity, Next} from "./types";
import {FromJson, IEntity, Next} from "./types";
import {environment} from "../../environments/environment";
import {HttpClient} from "@angular/common/http";
import {map} from "rxjs/operators";
@ -19,40 +19,40 @@ export class AbstractRepositoryService<Entity extends IEntity, Creator, Filter>
// nothing
}
create(dto: Creator, next: Next<Entity> = NO_OP, error: Error = NO_OP) {
this._post(['create'], dto, this.fromJson, next, error);
create(dto: Creator, next: Next<Entity> = NO_OP) {
this._post(['create'], dto, this.fromJson, next);
}
set(entity: Entity, key: string, value: any, next: Next<Entity> = NO_OP, error: Error = NO_OP) {
this._put(['put', entity.id, key], value, this.fromJson, next, error);
set(entity: Entity, key: string, value: any, next: Next<Entity> = NO_OP) {
this._put(['put', entity.id, key], value, this.fromJson, next);
}
get(id: number, next: Next<Entity> = NO_OP, error: Error = NO_OP) {
this._get(['get', id], this.fromJson, next, error);
get(id: number, next: Next<Entity> = NO_OP) {
this._get(['get', id], this.fromJson, next);
}
filter(filter: Filter, next: Next<Page<Entity>> = NO_OP, error: Error = NO_OP) {
this._post(['filter'], filter, Page.fromJsonGenerator(this.fromJson), next, error);
filter(filter: Filter, next: Next<Page<Entity>> = NO_OP) {
this._post(['filter'], filter, Page.fromJsonGenerator(this.fromJson), next);
}
delete(id: number, next: Next<Entity> = NO_OP, error: Error = NO_OP) {
this._delete(['delete', id], this.fromJson, next, error);
delete(id: number, next: Next<Entity> = NO_OP) {
this._delete(['delete', id], this.fromJson, next);
}
private _get<T>(path: any[], fromJson: FromJson<T>, next: Next<T>, error: Error): void {
this.http.get<any>(this._url(path)).pipe(map(fromJson)).subscribe(next, error);
private _get<T>(path: any[], fromJson: FromJson<T>, next: Next<T>): void {
this.http.get<any>(this._url(path)).pipe(map(fromJson)).subscribe(next);
}
private _put<T>(path: any[], data: any, fromJson: FromJson<T>, next: Next<T>, error: Error): void {
this.http.put<any>(this._url(path), data).pipe(map(fromJson)).subscribe(next, error);
private _put<T>(path: any[], data: any, fromJson: FromJson<T>, next: Next<T>): void {
this.http.put<any>(this._url(path), data).pipe(map(fromJson)).subscribe(next);
}
private _post<T>(path: any[], data: any, fromJson: FromJson<T>, next: Next<T>, error: Error): void {
this.http.post<any>(this._url(path), data).pipe(map(fromJson)).subscribe(next, error);
private _post<T>(path: any[], data: any, fromJson: FromJson<T>, next: Next<T>): void {
this.http.post<any>(this._url(path), data).pipe(map(fromJson)).subscribe(next);
}
private _delete<T>(path: any[], fromJson: FromJson<T>, next: Next<T>, error: Error): void {
this.http.delete<any>(this._url(path)).pipe(map(fromJson)).subscribe(next, error);
private _delete<T>(path: any[], fromJson: FromJson<T>, next: Next<T>): void {
this.http.delete<any>(this._url(path)).pipe(map(fromJson)).subscribe(next);
}
private _url(path: any[]): string {

View File

@ -16,13 +16,6 @@ export function NO_COMPARE<T>(a: T, b: T): number {
return 0;
}
function errorInterceptor(errorHandler: (error: any) => void): ((error: any) => void) {
return error => {
console.error(error);
errorHandler(error);
};
}
@Injectable({
providedIn: 'root',
})
@ -50,36 +43,36 @@ export class ApiService {
this.updateSubject.pipe(filter(update => update.type === type), map(update => Update.convert(update, fromJson))).subscribe(next);
}
getReturnItem<T>(path: string, fromJson: (json: any) => T, next: (item: T) => void = NO_OP, error: (error: any) => void = NO_OP) {
this.http.get<any>(this.restUrl(path)).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
getReturnItem<T>(path: string, fromJson: (json: any) => T, next: (item: T) => void = NO_OP) {
this.http.get<any>(this.restUrl(path)).pipe(map(fromJson)).subscribe(next);
}
getList<T>(path: string, fromJson: (json: any) => T, compare: (a: T, b: T) => number = NO_COMPARE, next: (list: T[]) => void = NO_OP, error: (error: any) => void = NO_OP) {
this.http.get<any[]>(this.restUrl(path)).pipe(map(list => list.map(fromJson).sort(compare))).subscribe(next, errorInterceptor(error));
getList<T>(path: string, fromJson: (json: any) => T, compare: (a: T, b: T) => number = NO_COMPARE, next: (list: T[]) => void = NO_OP) {
this.http.get<any[]>(this.restUrl(path)).pipe(map(list => list.map(fromJson).sort(compare))).subscribe(next);
}
postReturnNone<T>(path: string, data: any, next: (_: void) => void = NO_OP, error: (error: any) => void = NO_OP) {
this.http.post<any>(this.restUrl(path), data).subscribe(next, errorInterceptor(error));
postReturnNone<T>(path: string, data: any, next: (_: void) => void = NO_OP) {
this.http.post<any>(this.restUrl(path), data).subscribe(next);
}
postReturnItem<T>(path: string, data: any, fromJson: (json: any) => T, next: (item: T) => void = NO_OP, error: (error: any) => void = NO_OP) {
this.http.post<any>(this.restUrl(path), data).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
postReturnItem<T>(path: string, data: any, fromJson: (json: any) => T, next: (item: T) => void = NO_OP) {
this.http.post<any>(this.restUrl(path), data).pipe(map(fromJson)).subscribe(next);
}
putReturnItem<T>(path: string, data: any, fromJson: (json: any) => T, next: (item: T) => void = NO_OP, error: (error: any) => void = NO_OP) {
this.http.put<any>(this.restUrl(path), data).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
putReturnItem<T>(path: string, data: any, fromJson: (json: any) => T, next: (item: T) => void = NO_OP) {
this.http.put<any>(this.restUrl(path), data).pipe(map(fromJson)).subscribe(next);
}
postReturnPage<T>(path: string, data: any, fromJson: (json: any) => T, next: (page: Page<T>) => void = NO_OP, error: (error: any) => void = NO_OP) {
this.http.post<any>(this.restUrl(path), data).pipe(map(Page.fromJsonGenerator(fromJson))).subscribe(next, errorInterceptor(error));
postReturnPage<T>(path: string, data: any, fromJson: (json: any) => T, next: (page: Page<T>) => void = NO_OP) {
this.http.post<any>(this.restUrl(path), data).pipe(map(Page.fromJsonGenerator(fromJson))).subscribe(next);
}
deleteReturnItem<T>(path: string, fromJson: (json: any) => T, next: (item: T) => void = NO_OP, error: (error: any) => void = NO_OP) {
this.http.delete<any>(this.restUrl(path)).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
deleteReturnItem<T>(path: string, fromJson: (json: any) => T, next: (item: T) => void = NO_OP) {
this.http.delete<any>(this.restUrl(path)).pipe(map(fromJson)).subscribe(next);
}
postReturnList<T>(path: string, data: any, fromJson: (json: any) => T, next: (list: T[]) => void = NO_OP, error: (error: any) => void = NO_OP) {
this.http.post<any>(this.restUrl(path), data).pipe(map(list => list.map(fromJson))).subscribe(next, errorInterceptor(error));
postReturnList<T>(path: string, data: any, fromJson: (json: any) => T, next: (list: T[]) => void = NO_OP) {
this.http.post<any>(this.restUrl(path), data).pipe(map(list => list.map(fromJson))).subscribe(next);
}
delete(path: string, next: Next<void>): void {

View File

@ -16,8 +16,8 @@ export class AreaService implements ISearchService {
// nothing
}
findAll(next: (list: Area[]) => void, compare: (a: Area, b: Area) => number = NO_COMPARE, error: (error: any) => void = NO_OP): void {
this.api.getList("area/findAll", Area.fromJson, compare, next, error);
findAll(next: (list: Area[]) => void, compare: (a: Area, b: Area) => number = NO_COMPARE): void {
this.api.getList("area/findAll", Area.fromJson, compare, next);
}
subscribe(next: (area: Update<Area>) => void): void {
@ -25,15 +25,15 @@ export class AreaService implements ISearchService {
}
searchById(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
this.api.getReturnItem("area/searchById/" + id, SearchResult.fromJson, next, error);
this.api.getReturnItem("area/searchById/" + id, SearchResult.fromJson, next);
}
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.postReturnList("area/searchLike", term, SearchResult.fromJson, next, error);
search(term: string, next: (results: SearchResult[]) => void = NO_OP): void {
this.api.postReturnList("area/searchLike", term, SearchResult.fromJson, next);
}
set(area: Area, key: string, value: any, next: (item: Area) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.postReturnItem("area/set/" + area.id + "/" + key, value, Area.fromJson, next, error);
set(area: Area, key: string, value: any, next: (item: Area) => void = NO_OP): void {
this.api.postReturnItem("area/set/" + area.id + "/" + key, value, Area.fromJson, next);
}
}

View File

@ -30,8 +30,8 @@ export class BulkService implements ISearchService {
// nothing
}
findAll(next: (list: Bulk[]) => void, compare: (a: Bulk, b: Bulk) => number = NO_COMPARE, error: (error: any) => void = NO_OP): void {
this.api.getList("bulk/findAll", Bulk.fromJson, compare, next, error);
findAll(next: (list: Bulk[]) => void, compare: (a: Bulk, b: Bulk) => number = NO_COMPARE): void {
this.api.getList("bulk/findAll", Bulk.fromJson, compare, next);
}
subscribe(next: (bulk: Update<Bulk>) => void): void {
@ -39,31 +39,31 @@ export class BulkService implements ISearchService {
}
getById(id: number, next: (results: Bulk) => void, error?: (error: any) => void): void {
this.api.getReturnItem("bulk/getById/" + id, Bulk.fromJson, next, error);
this.api.getReturnItem("bulk/getById/" + id, Bulk.fromJson, next);
}
searchById(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
this.api.getReturnItem("bulk/searchById/" + id, SearchResult.fromJson, next, error);
this.api.getReturnItem("bulk/searchById/" + id, SearchResult.fromJson, next);
}
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.postReturnList("bulk/searchLike", term, SearchResult.fromJson, next, error);
search(term: string, next: (results: SearchResult[]) => void = NO_OP): void {
this.api.postReturnList("bulk/searchLike", term, SearchResult.fromJson, next);
}
set(bulk: Bulk, key: string, value: any, next: (item: Bulk) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.postReturnItem("bulk/set/" + bulk.id + "/" + key, value, Bulk.fromJson, next, error);
set(bulk: Bulk, key: string, value: any, next: (item: Bulk) => void = NO_OP): void {
this.api.postReturnItem("bulk/set/" + bulk.id + "/" + key, value, Bulk.fromJson, next);
}
create(next: (item: Bulk) => void, error: (error: any) => void = NO_OP): void {
this.api.postReturnItem("bulk/create/", new BulkCreate("Neu", true), Bulk.fromJson, next, error);
create(next: (item: Bulk) => void): void {
this.api.postReturnItem("bulk/create/", new BulkCreate("Neu", true), Bulk.fromJson, next);
}
delete(bulk: Bulk, next: () => void, error: (error: any) => void = NO_OP): void {
this.api.getReturnItem("bulk/delete/" + bulk.id, _ => _, next, error);
delete(bulk: Bulk, next: () => void): void {
this.api.getReturnItem("bulk/delete/" + bulk.id, _ => _, next);
}
setEntry(entry: BulkEntry, key: string, value: any, next: (result: BulkEntry) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.putReturnItem("BulkEntry/" + entry.id + "/set/" + key, value, next, error);
setEntry(entry: BulkEntry, key: string, value: any, next: (result: BulkEntry) => void = NO_OP): void {
this.api.putReturnItem("BulkEntry/" + entry.id + "/set/" + key, value, next);
}
deleteEntry(entry: BulkEntry, next: Next<void>): void {

View File

@ -16,8 +16,8 @@ export class ChannelService implements ISearchService {
// nothing
}
findAll(next: (list: Channel[]) => void, compare: (a: Channel, b: Channel) => number = NO_COMPARE, error: (error: any) => void = NO_OP): void {
this.api.getList("channel/findAll", Channel.fromJson, compare, next, error);
findAll(next: (list: Channel[]) => void, compare: (a: Channel, b: Channel) => number = NO_COMPARE): void {
this.api.getList("channel/findAll", Channel.fromJson, compare, next);
}
subscribe(next: (channel: Update<Channel>) => void): void {
@ -25,15 +25,15 @@ export class ChannelService implements ISearchService {
}
searchById(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
this.api.getReturnItem("channel/searchById/" + id, SearchResult.fromJson, next, error);
this.api.getReturnItem("channel/searchById/" + id, SearchResult.fromJson, next);
}
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.postReturnList("channel/searchLike", term, SearchResult.fromJson, next, error);
search(term: string, next: (results: SearchResult[]) => void = NO_OP): void {
this.api.postReturnList("channel/searchLike", term, SearchResult.fromJson, next);
}
set(channel: Channel, key: string, value: any, next: (item: Channel) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.postReturnItem("channel/set/" + channel.id + "/" + key, value, Channel.fromJson, next, error);
set(channel: Channel, key: string, value: any, next: (item: Channel) => void = NO_OP): void {
this.api.postReturnItem("channel/set/" + channel.id + "/" + key, value, Channel.fromJson, next);
}
}

View File

@ -20,24 +20,24 @@ export class DeviceService {
this.api.subscribe("DeviceDto", Device.fromJson, next);
}
findAll(next: (list: Device[]) => void, compare: (a: Device, b: Device) => number = NO_COMPARE, error: (error: any) => void = NO_OP): void {
this.api.getList("device/findAll", Device.fromJson, compare, next, error);
findAll(next: (list: Device[]) => void, compare: (a: Device, b: Device) => number = NO_COMPARE): void {
this.api.getList("device/findAll", Device.fromJson, compare, next);
}
set(device: Device, key: string, value: any, next: (item: Device) => void, error: (error: any) => void = NO_OP): void {
this.api.postReturnItem("device/set/" + device.id + "/" + key, value, Device.fromJson, next, error);
set(device: Device, key: string, value: any, next: (item: Device) => void): void {
this.api.postReturnItem("device/set/" + device.id + "/" + key, value, Device.fromJson, next);
}
setDeviceSwitch(device: Device, key: string, value: any, next: (item: Device) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.postReturnItem("device/set/" + device.id + "/DeviceSwitch/" + key, value, Device.fromJson, next, error);
setDeviceSwitch(device: Device, key: string, value: any, next: (item: Device) => void = NO_OP): void {
this.api.postReturnItem("device/set/" + device.id + "/DeviceSwitch/" + key, value, Device.fromJson, next);
}
setDeviceStateScene(device: Device, key: string, value: any, next: (item: Device) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.postReturnItem("device/set/" + device.id + "/DeviceStateScene/" + key, value, Device.fromJson, next, error);
setDeviceStateScene(device: Device, key: string, value: any, next: (item: Device) => void = NO_OP): void {
this.api.postReturnItem("device/set/" + device.id + "/DeviceStateScene/" + key, value, Device.fromJson, next);
}
setDeviceShutter(device: Device, key: string, value: any, next: (item: Device) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.postReturnItem("device/set/" + device.id + "/DeviceShutter/" + key, value, Device.fromJson, next, error);
setDeviceShutter(device: Device, key: string, value: any, next: (item: Device) => void = NO_OP): void {
this.api.postReturnItem("device/set/" + device.id + "/DeviceShutter/" + key, value, Device.fromJson, next);
}
setSwitchState(d: Device, value: boolean): void {
@ -64,16 +64,16 @@ export class DeviceService {
this.propertyService.set(device.positionProperty, "value", value);
}
getById(id: number, next: (item: Device) => void, error: (error: any) => void = NO_OP): void {
this.api.getReturnItem("device/searchById/" + id, Device.fromJson, next, error);
getById(id: number, next: (item: Device) => void): void {
this.api.getReturnItem("device/searchById/" + id, Device.fromJson, next);
}
create(type: string, next: (item: Device) => void, error: (error: any) => void = NO_OP): void {
this.api.postReturnItem("device/create/", type, Device.fromJson, next, error);
create(type: string, next: (item: Device) => void): void {
this.api.postReturnItem("device/create/", type, Device.fromJson, next);
}
delete(device: Device, next: () => void, error: (error: any) => void = NO_OP): void {
this.api.getReturnItem("device/delete/" + device.id, _ => _, next, error);
delete(device: Device, next: () => void): void {
this.api.getReturnItem("device/delete/" + device.id, _ => _, next);
}
}

View File

@ -17,8 +17,8 @@ export class PropertyService implements ISearchService {
// nothing
}
findAll(next: (list: Property[]) => void, compare: (a: Property, b: Property) => number = NO_COMPARE, error: (error: any) => void = NO_OP): void {
this.api.getList("property/findAll", Property.fromJson, compare, next, error);
findAll(next: (list: Property[]) => void, compare: (a: Property, b: Property) => number = NO_COMPARE): void {
this.api.getList("property/findAll", Property.fromJson, compare, next);
}
subscribe(next: (property: Update<Property>) => void): void {
@ -26,19 +26,19 @@ export class PropertyService implements ISearchService {
}
searchById(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
this.api.getReturnItem("property/searchById/" + id, SearchResult.fromJson, next, error);
this.api.getReturnItem("property/searchById/" + id, SearchResult.fromJson, next);
}
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.postReturnList("property/searchLike", term, SearchResult.fromJson, next, error);
search(term: string, next: (results: SearchResult[]) => void = NO_OP): void {
this.api.postReturnList("property/searchLike", term, SearchResult.fromJson, next);
}
set(property: Property, key: string, value: any, next: (item: Property) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.postReturnItem("property/set/" + property.id + "/" + key, value, Property.fromJson, next, error);
set(property: Property, key: string, value: any, next: (item: Property) => void = NO_OP): void {
this.api.postReturnItem("property/set/" + property.id + "/" + key, value, Property.fromJson, next);
}
create(next: (item: Property) => void, error: (error: any) => void = NO_OP): void {
this.api.getReturnItem("property/create/", Property.fromJson, next, error);
create(next: (item: Property) => void): void {
this.api.getReturnItem("property/create/", Property.fromJson, next);
}
delete(property: Property, next: Next<void>): void {

View File

@ -16,8 +16,8 @@ export class RoomService implements ISearchService {
// nothing
}
findAll(next: (list: Room[]) => void, compare: (a: Room, b: Room) => number = NO_COMPARE, error: (error: any) => void = NO_OP): void {
this.api.getList("room/findAll", Room.fromJson, compare, next, error);
findAll(next: (list: Room[]) => void, compare: (a: Room, b: Room) => number = NO_COMPARE): void {
this.api.getList("room/findAll", Room.fromJson, compare, next);
}
subscribe(next: (room: Update<Room>) => void): void {
@ -25,15 +25,15 @@ export class RoomService implements ISearchService {
}
searchById(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
this.api.getReturnItem("room/searchById/" + id, SearchResult.fromJson, next, error);
this.api.getReturnItem("room/searchById/" + id, SearchResult.fromJson, next);
}
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.postReturnList("room/searchLike", term, SearchResult.fromJson, next, error);
search(term: string, next: (results: SearchResult[]) => void = NO_OP): void {
this.api.postReturnList("room/searchLike", term, SearchResult.fromJson, next);
}
set(room: Room, key: string, value: any, next: (item: Room) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.postReturnItem("room/set/" + room.id + "/" + key, value, Room.fromJson, next, error);
set(room: Room, key: string, value: any, next: (item: Room) => void = NO_OP): void {
this.api.postReturnItem("room/set/" + room.id + "/" + key, value, Room.fromJson, next);
}
}

View File

@ -16,8 +16,8 @@ export class SceneService implements ISearchService {
// nothing
}
findAll(next: (list: Scene[]) => void, compare: (a: Scene, b: Scene) => number = NO_COMPARE, error: (error: any) => void = NO_OP): void {
this.api.getList("scene/findAll", Scene.fromJson, compare, next, error);
findAll(next: (list: Scene[]) => void, compare: (a: Scene, b: Scene) => number = NO_COMPARE): void {
this.api.getList("scene/findAll", Scene.fromJson, compare, next);
}
subscribe(next: (scene: Update<Scene>) => void): void {
@ -25,15 +25,15 @@ export class SceneService implements ISearchService {
}
searchById(id: number, next: (results: SearchResult) => void, error: (error: any) => void): void {
this.api.getReturnItem("scene/searchById/" + id, SearchResult.fromJson, next, error);
this.api.getReturnItem("scene/searchById/" + id, SearchResult.fromJson, next);
}
search(term: string, next: (results: SearchResult[]) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.postReturnList("scene/searchLike", term, SearchResult.fromJson, next, error);
search(term: string, next: (results: SearchResult[]) => void = NO_OP): void {
this.api.postReturnList("scene/searchLike", term, SearchResult.fromJson, next);
}
set(scene: Scene, key: string, value: any, next: (item: Scene) => void = NO_OP, error: (error: any) => void = NO_OP): void {
this.api.postReturnItem("scene/set/" + scene.id + "/" + key, value, Scene.fromJson, next, error);
set(scene: Scene, key: string, value: any, next: (item: Scene) => void = NO_OP): void {
this.api.postReturnItem("scene/set/" + scene.id + "/" + key, value, Scene.fromJson, next);
}
}

View File

@ -2,6 +2,7 @@ import {Injectable} from '@angular/core';
import {ScheduleEntry} from "./ScheduleEntry";
import {ApiService, NO_OP} from "../../api.service";
import {Schedule} from "../Schedule";
import {Next} from "../../types";
@Injectable({
providedIn: 'root'
@ -14,20 +15,16 @@ export class ScheduleEntryService {
// nothing
}
findAll(next: (list: ScheduleEntry[]) => void, compare: (a: ScheduleEntry, b: ScheduleEntry) => number, error: (error: any) => void = NO_OP): void {
this.api.getList("scheduleEntry/findAll", ScheduleEntry.fromJson, compare, next, error);
create(schedule: Schedule, next: Next<ScheduleEntry> = NO_OP): void {
this.api.getReturnItem("schedule/entry/create/" + schedule.id, ScheduleEntry.fromJson, next);
}
set(entry: ScheduleEntry, key: string, value: any, next: (item: ScheduleEntry) => void, error: (error: any) => void = NO_OP): void {
this.api.postReturnItem("schedule/entry/set/" + entry.id + "/" + key, value, ScheduleEntry.fromJson, next, error);
set(entry: ScheduleEntry, key: string, value: any, next: Next<ScheduleEntry> = NO_OP): void {
this.api.postReturnItem("schedule/entry/set/" + entry.id + "/" + key, value, ScheduleEntry.fromJson, next);
}
create(schedule: Schedule, next: (item: ScheduleEntry) => void, error: (error: any) => void = NO_OP): void {
this.api.getReturnItem("schedule/entry/create/" + schedule.id, ScheduleEntry.fromJson, next, error);
}
delete(entry: ScheduleEntry, next: () => void, error: (error: any) => void = NO_OP): void {
this.api.getReturnItem("schedule/entry/delete/" + entry.id, _ => _, next, error);
delete(entry: ScheduleEntry, next: Next<ScheduleEntry> = NO_OP): void {
this.api.getReturnItem("schedule/entry/delete/" + entry.id, _ => _, next);
}
}

View File

@ -15,28 +15,28 @@ export class ScheduleService {
// nothing
}
findAll(next: (list: Schedule[]) => void, compare: (a: Schedule, b: Schedule) => number, error: (error: any) => void = NO_OP): void {
this.api.getList("schedule/findAll", Schedule.fromJson, compare, next, error);
}
set(schedule: Schedule, key: string, value: any, next: (item: Schedule) => void, error: (error: any) => void = NO_OP): void {
this.api.postReturnItem("schedule/set/" + schedule.id + "/" + key, value, Schedule.fromJson, next, error);
}
getById(id: number, next: (item: Schedule) => void, error: (error: any) => void = NO_OP): void {
this.api.getReturnItem("schedule/searchById/" + id, Schedule.fromJson, next, error);
}
create(next: (item: Schedule) => void, error: (error: any) => void = NO_OP): void {
this.api.getReturnItem("schedule/create/", Schedule.fromJson, next, error);
}
delete(schedule: Schedule, next: () => void, error: (error: any) => void = NO_OP): void {
this.api.getReturnItem("schedule/delete/" + schedule.id, _ => _, next, error);
}
subscribe(next: Next<Update<Schedule>>): void {
this.api.subscribe("ScheduleDto", Schedule.fromJson, next);
}
findAll(next: Next<Schedule[]>, compare?: (a: Schedule, b: Schedule) => number): void {
this.api.getList("schedule/findAll", Schedule.fromJson, compare, next);
}
getById(id: number, next: (item: Schedule) => void): void {
this.api.getReturnItem("schedule/searchById/" + id, Schedule.fromJson, next);
}
create(next: Next<Schedule> = NO_OP): void {
this.api.getReturnItem("schedule/create/", Schedule.fromJson, next);
}
set(schedule: Schedule, key: string, value: any, next: Next<Schedule> = NO_OP): void {
this.api.postReturnItem("schedule/set/" + schedule.id + "/" + key, value, Schedule.fromJson, next);
}
delete(schedule: Schedule, next: Next<Schedule> = NO_OP): void {
this.api.getReturnItem("schedule/delete/" + schedule.id, _ => _, next);
}
}

View File

@ -1,20 +1,17 @@
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";
import {DeviceAllListComponent} from "./pages/device-all-list/device-all-list.component";
import {DeviceComponent} from "./pages/device/device.component";
import {PropertyListComponent} from "./pages/property-list/property-list.component";
import {ScheduleListComponent} from "./pages/schedule/list/schedule-list.component";
import {ScheduleEditorComponent} from "./pages/schedule/editor/schedule-editor.component";
import {DeviceListComponent} from "./pages/device/list/device-list.component";
import {DeviceEditorComponent} from "./pages/device/editor/device-editor.component";
import {PropertyListComponent} from "./pages/property/list/property-list.component";
import {ChannelListComponent} from "./pages/channel-list/channel-list.component";
import {AreaListComponent} from "./pages/mobile/device-tree/area-list/area-list.component";
import {RoomListComponent} from "./pages/mobile/device-tree/room-list/room-list.component";
import {DeviceListComponent} from "./pages/mobile/device-tree/device-list/device-list.component";
import {BulkListComponent} from "./pages/bulk/bulk-list/bulk-list.component";
import {BulkComponent} from "./pages/bulk/bulk/bulk.component";
const routes: Routes = [
{path: 'Device', component: DeviceComponent},
{path: 'DeviceAllList', component: DeviceAllListComponent},
{path: 'Device', component: DeviceEditorComponent},
{path: 'DeviceList', component: DeviceListComponent},
// {path: 'Channel', component: ChannelComponent},
{path: 'ChannelList', component: ChannelListComponent},
@ -22,16 +19,12 @@ const routes: Routes = [
// {path: 'Property', component: PropertyComponent},
{path: 'PropertyList', component: PropertyListComponent},
{path: 'Schedule', component: ScheduleComponent},
{path: 'Schedule', component: ScheduleEditorComponent},
{path: 'ScheduleList', component: ScheduleListComponent},
{path: 'Bulk', component: BulkComponent},
{path: 'BulkList', component: BulkListComponent},
{path: 'AreaList', component: AreaListComponent},
{path: 'RoomList', component: RoomListComponent},
{path: 'DeviceList', component: DeviceListComponent},
{path: '**', redirectTo: '/ScheduleList'},
];

View File

@ -3,7 +3,7 @@
<div class="item" routerLink="/ScheduleList" routerLinkActive="itemActive">
Zeitpläne
</div>
<div class="item" routerLink="/DeviceAllList" routerLinkActive="itemActive">
<div class="item" routerLink="/DeviceList" routerLinkActive="itemActive">
Geräte
</div>

View File

@ -1,5 +1,4 @@
import {Component} from '@angular/core';
import {DataService} from "./data.service";
@Component({
selector: 'app-root',
@ -10,7 +9,7 @@ export class AppComponent {
title = 'angular';
constructor(
readonly dataService: DataService,
// nothing
) {
// nothing
}

View File

@ -6,18 +6,15 @@ import {AppComponent} from './app.component';
import {HttpClientModule} from "@angular/common/http";
import {FormsModule} from "@angular/forms";
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 {NumberComponent} from './shared/number/number.component';
import {ScheduleComponent} from "./pages/schedule/schedule.component";
import {ScheduleEditorComponent} from "./pages/schedule/editor/schedule-editor.component";
import {SearchComponent} from './shared/search/search.component';
import {DeviceAllListComponent} from './pages/device-all-list/device-all-list.component';
import {DeviceComponent} from './pages/device/device.component';
import {PropertyListComponent} from './pages/property-list/property-list.component';
import {DeviceListComponent} from './pages/device/list/device-list.component';
import {DeviceEditorComponent} from './pages/device/editor/device-editor.component';
import {PropertyListComponent} from './pages/property/list/property-list.component';
import {ChannelListComponent} from './pages/channel-list/channel-list.component';
import {AreaListComponent} from './pages/mobile/device-tree/area-list/area-list.component';
import {RoomListComponent} from './pages/mobile/device-tree/room-list/room-list.component';
import {DeviceListComponent} from './pages/mobile/device-tree/device-list/device-list.component';
import {BulkListComponent} from './pages/bulk/bulk-list/bulk-list.component';
import {BulkComponent} from './pages/bulk/bulk/bulk.component';
@ -25,16 +22,14 @@ import {BulkComponent} from './pages/bulk/bulk/bulk.component';
declarations: [
AppComponent,
EditFieldComponent,
ScheduleComponent,
ScheduleEditorComponent,
ScheduleListComponent,
NumberComponent,
SearchComponent,
DeviceAllListComponent,
DeviceComponent,
DeviceListComponent,
DeviceEditorComponent,
PropertyListComponent,
ChannelListComponent,
AreaListComponent,
RoomListComponent,
DeviceListComponent,
BulkListComponent,
BulkComponent,

View File

@ -1,22 +0,0 @@
import {Injectable} from '@angular/core';
import {Device} from "./api/device/Device";
@Injectable({
providedIn: 'root'
})
export class DataService {
private _device?: Device;
get device(): Device | undefined {
return this._device;
}
set device(device: Device | undefined) {
this._device = device;
}
constructor() {
}
}

View File

@ -1,16 +1,15 @@
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, Router} from "@angular/router";
import {DataService} from "../../data.service";
import {PropertyService} from "../../api/property/property.service";
import {Device, DeviceShutter, DeviceStateScene, DeviceSwitch} from "../../api/device/Device";
import {DeviceService} from "../../api/device/device.service";
import {PropertyService} from "../../../api/property/property.service";
import {Device, DeviceShutter, DeviceStateScene, DeviceSwitch} from "../../../api/device/Device";
import {DeviceService} from "../../../api/device/device.service";
@Component({
selector: 'app-device',
templateUrl: './device.component.html',
styleUrls: ['./device.component.less']
selector: 'app-device-editor',
templateUrl: './device-editor.component.html',
styleUrls: ['./device-editor.component.less']
})
export class DeviceComponent implements OnInit {
export class DeviceEditorComponent implements OnInit {
device!: Device;
@ -24,14 +23,12 @@ export class DeviceComponent implements OnInit {
readonly router: Router,
readonly activatedRoute: ActivatedRoute,
readonly deviceService: DeviceService,
readonly dataService: DataService,
readonly propertyService: PropertyService,
) {
// nothing
}
ngOnInit(): void {
this.dataService.device = undefined;
this.activatedRoute.params.subscribe(params => this.deviceService.getById(params['id'], device => this.setDevice(device)));
}
@ -48,7 +45,6 @@ export class DeviceComponent implements OnInit {
this.deviceShutter = device as DeviceShutter;
break;
}
this.dataService.device = device;
}
set(key: string, value: any): void {
@ -57,7 +53,7 @@ export class DeviceComponent implements OnInit {
delete(): void {
if (confirm(this.getDeviceTypeTitle() + " \"" + this.device.title + "\" wirklich löschen?")) {
this.deviceService.delete(this.device, () => this.router.navigate(["/DeviceAllList"]));
this.deviceService.delete(this.device, () => this.router.navigate(["/DeviceList"]));
}
}

View File

@ -17,8 +17,8 @@
<fa-icon [icon]="faEdit"></fa-icon>
</div>
<div class="controls">
<img alt="An" class="control" src="assets/switch-on.svg" (click)="deviceService.setSwitchState(device, true)"/>
<img alt="Aus" class="control" src="assets/switch-off.svg" (click)="deviceService.setSwitchState(device, false)"/>
<img alt="An" class="control" src="../../../../assets/switch-on.svg" (click)="deviceService.setSwitchState(device, true)"/>
<img alt="Aus" class="control" src="../../../../assets/switch-off.svg" (click)="deviceService.setSwitchState(device, false)"/>
</div>
</div>

View File

@ -1,17 +1,17 @@
import {Component, OnInit} from '@angular/core';
import {DeviceService} from "../../api/device/device.service";
import {PropertyService} from "../../api/property/property.service";
import {Device, DeviceShutter, DeviceStateScene, DeviceSwitch} from "../../api/device/Device";
import {DeviceService} from "../../../api/device/device.service";
import {PropertyService} from "../../../api/property/property.service";
import {Device, DeviceShutter, DeviceStateScene, DeviceSwitch} from "../../../api/device/Device";
import {faEdit} from '@fortawesome/free-regular-svg-icons';
import {Scene} from "../../api/scene/Scene";
import {SceneService} from "../../api/scene/scene.service";
import {Scene} from "../../../api/scene/Scene";
import {SceneService} from "../../../api/scene/scene.service";
@Component({
selector: 'app-device-all-list',
templateUrl: './device-all-list.component.html',
styleUrls: ['./device-all-list.component.less']
selector: 'app-device-list',
templateUrl: './device-list.component.html',
styleUrls: ['./device-list.component.less']
})
export class DeviceAllListComponent implements OnInit {
export class DeviceListComponent implements OnInit {
readonly Device = Device;

View File

@ -1,17 +0,0 @@
<div class="list">
<div class="entry">
Haus
</div>
<div class="entry area" *ngFor="let area of areas" [routerLink]="['/RoomList', {id: area.id}]">
{{area.title}}
<fa-icon class="icon" [icon]="faArrowAltCircleRight"></fa-icon>
</div>
<div class="entry device" *ngFor="let device of devices">
{{device.title}}
<fa-icon class="icon" [icon]="faPlayCircle"></fa-icon>
</div>
</div>

View File

@ -1,28 +0,0 @@
import {Component, OnInit} from '@angular/core';
import {Area} from "../../../../api/area/Area";
import {Device} from "../../../../api/device/Device";
import {faArrowAltCircleRight, faPlayCircle} from '@fortawesome/free-regular-svg-icons';
import {STUB_AREAS, STUB_DEVICES} from "../../../../api/STUB";
@Component({
selector: 'app-area-list',
templateUrl: './area-list.component.html',
styleUrls: ['../device-tree.less']
})
export class AreaListComponent implements OnInit {
readonly faArrowAltCircleRight = faArrowAltCircleRight;
readonly faPlayCircle = faPlayCircle;
areas: Area[] = STUB_AREAS.sort(Area.comparePosition);
devices: Device[] = STUB_DEVICES.filter(d => d.areaId === null && d.roomId === null).sort(Device.comparePosition);
constructor() {
}
ngOnInit(): void {
}
}

View File

@ -1,24 +0,0 @@
<div class="list devices" *ngIf="room !== undefined">
<div class="entry back" [routerLink]="['/RoomList', {id: room.areaId}]">
<fa-icon [icon]="faArrowAltCircleLeft"></fa-icon>
|
{{room.title}}
</div>
<div class="entry device {{device.type}}" *ngFor="let device of devices">
{{device.title}}
<ng-container *ngIf="device.type === 'DeviceSwitch'">
<fa-icon class="icon" [icon]="faTimesCircle"></fa-icon>
<fa-icon class="icon" [icon]="faCheckCircle"></fa-icon>
</ng-container>
<ng-container *ngIf="device.type === 'DeviceStateScene'">
<fa-icon class="icon" [icon]="faPlayCircle"></fa-icon>
</ng-container>
</div>
</div>

View File

@ -1,50 +0,0 @@
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from "@angular/router";
import {Device} from "../../../../api/device/Device";
import {faArrowAltCircleLeft, faArrowAltCircleRight, faCheckCircle, faPlayCircle, faTimesCircle} from '@fortawesome/free-regular-svg-icons';
import {STUB_DEVICES, STUB_ROOMS} from "../../../../api/STUB";
import {Room} from "../../../../api/room/Room";
@Component({
selector: 'app-device-list',
templateUrl: './device-list.component.html',
styleUrls: ['../device-tree.less']
})
export class DeviceListComponent implements OnInit {
readonly faArrowAltCircleLeft = faArrowAltCircleLeft;
readonly faArrowAltCircleRight = faArrowAltCircleRight;
readonly faPlayCircle = faPlayCircle;
readonly faCheckCircle = faCheckCircle;
readonly faTimesCircle = faTimesCircle;
room?: Room;
devices: Device[] = [];
constructor(
readonly route: ActivatedRoute,
) {
this.route.paramMap.subscribe(params => {
const roomIdStr: string | null = params.get("roomId");
if (roomIdStr != null) {
const roomId: number = parseInt(roomIdStr);
this.room = STUB_ROOMS.find(Room.filterById(roomId));
if (this.room) {
this.devices = STUB_DEVICES.filter(Device.filterByAreaIdAndRoomId(this.room.areaId, this.room.id)).sort(Device.comparePosition);
} else {
this.devices = [];
}
}
})
}
ngOnInit(): void {
}
}

View File

@ -1,34 +0,0 @@
.list {
font-size: 10vmin;
.entry {
padding: 3vmin;
border-bottom: 1px solid black;
.icon {
float: right;
margin-left: 3vmin;
}
}
.area {
background-color: lightsteelblue;
}
.area:active {
background-color: cornflowerblue;
}
.device {
background-color: lightcyan;
}
.DeviceSwitch {
background-color: gray;
}
.device:active {
background-color: darkcyan;
}
}

View File

@ -1,15 +0,0 @@
<div class="list rooms" *ngIf="area !== undefined">
<div class="entry back" [routerLink]="['/AreaList']">
<fa-icon [icon]="faArrowAltCircleLeft"></fa-icon>
|
{{area.title}}
</div>
<div class="entry room" *ngFor="let room of rooms" [routerLink]="['/DeviceList', {roomId: room.id}]">
{{room.title}}
<fa-icon class="icon" [icon]="faArrowAltCircleRight"></fa-icon>
</div>
<div class="entry device" *ngFor="let device of devices">
{{device.title}}
<fa-icon class="icon" [icon]="faPlayCircle"></fa-icon>
</div>
</div>

View File

@ -1,46 +0,0 @@
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from "@angular/router";
import {Room} from "../../../../api/room/Room";
import {Device} from "../../../../api/device/Device";
import {faArrowAltCircleLeft, faArrowAltCircleRight, faPlayCircle} from '@fortawesome/free-regular-svg-icons';
import {STUB_AREAS, STUB_DEVICES, STUB_ROOMS} from "../../../../api/STUB";
import {Area} from "../../../../api/area/Area";
@Component({
selector: 'app-room-list',
templateUrl: './room-list.component.html',
styleUrls: ['../device-tree.less']
})
export class RoomListComponent implements OnInit {
readonly faArrowAltCircleLeft = faArrowAltCircleLeft;
readonly faArrowAltCircleRight = faArrowAltCircleRight;
readonly faPlayCircle = faPlayCircle;
area?: Area;
rooms: Room[] = [];
devices: Device[] = [];
constructor(
readonly route: ActivatedRoute,
) {
this.route.paramMap.subscribe(params => {
const areaIdStr: string | null = params.get("id");
if (areaIdStr != null) {
const areaId: number = parseInt(areaIdStr);
this.area = STUB_AREAS.find(Area.filterById(areaId));
this.rooms = STUB_ROOMS.filter(Room.filterByAreaId(areaId)).sort(Room.comparePosition);
this.devices = STUB_DEVICES.filter(Device.filterByAreaIdAndRoomId(areaId, null)).sort(Device.comparePosition);
}
})
}
ngOnInit(): void {
}
}

View File

@ -1,9 +1,9 @@
import {Component, OnInit} from '@angular/core';
import {Property} from "../../api/property/Property";
import {PropertyService} from "../../api/property/property.service";
import {Scene} from "../../api/scene/Scene";
import {SceneService} from "../../api/scene/scene.service";
import {ChannelService} from "../../api/channel/channel.service";
import {Property} from "../../../api/property/Property";
import {PropertyService} from "../../../api/property/property.service";
import {Scene} from "../../../api/scene/Scene";
import {SceneService} from "../../../api/scene/scene.service";
import {ChannelService} from "../../../api/channel/channel.service";
import {faTimesCircle} from "@fortawesome/free-regular-svg-icons";
@Component({

View File

@ -0,0 +1,81 @@
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 {faCheckCircle, faCircle, faTimesCircle} from '@fortawesome/free-regular-svg-icons';
import {ActivatedRoute, Router} from "@angular/router";
import {PropertyService} from "../../../api/property/property.service";
import {Scene} from "../../../api/scene/Scene";
import {SceneService} from "../../../api/scene/scene.service";
import {BulkService} from "../../../api/bulk/BulkService";
import {Update} from "../../../api/Update";
import {NO_OP} from "../../../api/api.service";
@Component({
selector: 'app-schedule-editor',
templateUrl: './schedule-editor.component.html',
styleUrls: ['./schedule-editor.component.less']
})
export class ScheduleEditorComponent implements OnInit {
readonly faCheckCircle = faCheckCircle;
readonly faCircle = faCircle;
readonly faTimes = faTimesCircle;
readonly Schedule = Schedule;
schedule!: Schedule;
scenes: Scene[] = [];
constructor(
readonly router: Router,
readonly activatedRoute: ActivatedRoute,
readonly scheduleService: ScheduleService,
readonly scheduleEntryService: ScheduleEntryService,
readonly propertyService: PropertyService,
readonly bulkService: BulkService,
readonly sceneService: SceneService,
) {
// nothing
}
ngOnInit(): void {
this.scheduleService.subscribe(update => this.update(update));
this.sceneService.findAll(scenes => this.scenes = scenes);
this.activatedRoute.params.subscribe(params => this.scheduleService.getById(params['id'], schedule => this.schedule = schedule));
}
private update(update: Update<Schedule>): void {
if (!this.schedule || this.schedule.id !== update.payload.id) {
return;
}
if (!update.existing) {
this.router.navigate(['/ScheduleList']);
return;
}
this.schedule = update.payload;
}
create(): void {
this.scheduleEntryService.create(this.schedule, NO_OP);
}
delete(entry: ScheduleEntry): void {
if (confirm("Eintrag \"" + entry.nextClearTimestamp?.timeString + " +/-" + entry.fuzzySeconds + "\" wirklich löschen?")) {
this.scheduleEntryService.delete(entry, NO_OP);
}
}
set(entry: ScheduleEntry | null, key: string, value: any): void {
if (entry) {
this.scheduleEntryService.set(entry, key, value, NO_OP);
} else {
this.scheduleService.set(this.schedule, key, value, NO_OP);
}
}
}

View File

@ -1,7 +1,9 @@
import {Component, OnInit} from '@angular/core';
import {ScheduleService} from "../../api/schedule/schedule.service";
import {Schedule} from "../../api/schedule/Schedule";
import {ScheduleService} from "../../../api/schedule/schedule.service";
import {Schedule} from "../../../api/schedule/Schedule";
import {faCheckCircle, faCircle, faTimesCircle} from '@fortawesome/free-regular-svg-icons';
import {NO_OP} from "../../../api/api.service";
import {Update} from "../../../api/Update";
@Component({
selector: 'app-schedule-list',
@ -27,19 +29,22 @@ export class ScheduleListComponent implements OnInit {
}
ngOnInit(): void {
this.scheduleService.subscribe(update => this.update(update));
this.scheduleService.findAll(schedules => this.schedules = schedules, Schedule.compareName);
}
set(schedule: Schedule, key: string, value: any): void {
this.scheduleService.set(schedule, key, value, schedule => this.addOrReplace(schedule));
this.scheduleService.set(schedule, key, value, NO_OP);
}
private addOrReplace(schedule: Schedule): void {
const index: number = this.schedules.findIndex(s => s.id === schedule.id);
private update(update: Update<Schedule>): void {
const index: number = this.schedules.findIndex(s => s.id === update.payload.id);
if (index < 0) {
this.schedules.push(schedule);
this.schedules.push(update.payload);
} else if (update.existing) {
this.schedules[index] = update.payload;
} else {
this.schedules[index] = schedule;
this.schedules.splice(index, 1);
}
this.schedules = this.schedules.sort(Schedule.compareName)
}
@ -49,12 +54,12 @@ export class ScheduleListComponent implements OnInit {
}
create(): void {
this.scheduleService.create(schedule => this.addOrReplace(schedule));
this.scheduleService.create(NO_OP);
}
delete(schedule: Schedule): void {
if (confirm("Zeitplan \"" + schedule.title + "\" wirklich löschen?")) {
this.scheduleService.delete(schedule, () => this.remove(schedule));
this.scheduleService.delete(schedule, NO_OP);
}
}

View File

@ -1,83 +0,0 @@
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 {faCheckCircle, faCircle, faTimesCircle} from '@fortawesome/free-regular-svg-icons';
import {ActivatedRoute} from "@angular/router";
import {PropertyService} from "../../api/property/property.service";
import {Scene} from "../../api/scene/Scene";
import {SceneService} from "../../api/scene/scene.service";
import {BulkService} from "../../api/bulk/BulkService";
@Component({
selector: 'app-schedule',
templateUrl: './schedule.component.html',
styleUrls: ['./schedule.component.less']
})
export class ScheduleComponent implements OnInit {
readonly faCheckCircle = faCheckCircle;
readonly faCircle = faCircle;
readonly faTimes = faTimesCircle;
readonly Schedule = Schedule;
schedule!: Schedule;
scenes: Scene[] = [];
constructor(
readonly activatedRoute: ActivatedRoute,
readonly scheduleService: ScheduleService,
readonly scheduleEntryService: ScheduleEntryService,
readonly propertyService: PropertyService,
readonly bulkService: BulkService,
readonly sceneService: SceneService,
) {
// nothing
}
ngOnInit(): void {
this.sceneService.findAll(scenes => this.scenes = scenes);
this.activatedRoute.params.subscribe(params => this.scheduleService.getById(params['id'], schedule => this.setSchedule(schedule)));
}
private setSchedule(schedule: Schedule): void {
this.schedule = schedule;
}
set(entry: ScheduleEntry | null, key: string, value: any): void {
if (entry) {
this.scheduleEntryService.set(entry, key, value, entry => this.addOrReplace(entry));
} else {
this.scheduleService.set(this.schedule, key, value, schedule => this.setSchedule(schedule));
}
}
private addOrReplace(entry: ScheduleEntry): void {
const index: number = this.schedule.entries.findIndex(s => s.id === entry.id);
if (index < 0) {
this.schedule.entries.push(entry);
} else {
this.schedule.entries[index] = entry;
}
}
private remove(entry: ScheduleEntry): void {
this.schedule.entries.splice(this.schedule.entries.findIndex(e => e.id === entry.id), 1);
}
create(): void {
this.scheduleEntryService.create(this.schedule, entry => this.addOrReplace(entry));
}
delete(entry: ScheduleEntry): void {
if (confirm("Eintrag \"" + entry.nextClearTimestamp?.timeString + " +/-" + entry.fuzzySeconds + "\" wirklich löschen?")) {
this.scheduleEntryService.delete(entry, () => this.remove(entry));
}
}
}

View File

@ -1,7 +1,5 @@
package de.ph87.homeautomation.schedule;
import de.ph87.homeautomation.property.Property;
import de.ph87.homeautomation.schedule.entry.ScheduleEntry;
import de.ph87.homeautomation.web.NotFoundException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -32,16 +30,8 @@ public class ScheduleReader {
return findAll().stream().map(scheduleMapper::toDto).toList();
}
public Schedule getByEntry(final ScheduleEntry entry) {
return scheduleRepository.getByEntriesContaining(entry);
}
public ScheduleDto getDtoById(final long id) {
return scheduleMapper.toDto(getById(id));
}
public List<Schedule> findAllByProperty(final Property property) {
return scheduleRepository.findDistinctByEntries_Property(property);
}
}

View File

@ -29,6 +29,8 @@ public class ScheduleEntry {
@ManyToOne
private Schedule schedule;
private int position;
private boolean enabled = false;
private boolean monday = true;
@ -79,6 +81,7 @@ public class ScheduleEntry {
public ScheduleEntry(final Schedule schedule) {
this.schedule = schedule;
this.position = schedule.getEntries().size();
}
public void setNextClearTimestamp(final ZonedDateTime next) {

View File

@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.*;
@RequiredArgsConstructor
public class ScheduleEntryController {
private final ScheduleEntryWriteService scheduleEntryWriteService;
private final ScheduleEntryWriter scheduleEntryWriter;
private final BulkReader bulkReader;
@ -18,97 +18,102 @@ public class ScheduleEntryController {
@GetMapping("create/{scheduleId}")
public ScheduleEntryDto create(@PathVariable final long scheduleId) {
return scheduleEntryWriteService.create(scheduleId);
return scheduleEntryWriter.create(scheduleId);
}
@GetMapping("delete/{id}")
public void delete(@PathVariable final long id) {
scheduleEntryWriteService.delete(id);
scheduleEntryWriter.delete(id);
}
@PostMapping("set/{id}/position")
public ScheduleEntryDto setPosition(@PathVariable final long id, @RequestBody final int value) {
return scheduleEntryWriter.setPosition(id, value);
}
@PostMapping("set/{id}/enabled")
public ScheduleEntryDto setEnabled(@PathVariable final long id, @RequestBody final boolean value) {
return scheduleEntryWriteService.set(id, ScheduleEntry::setEnabled, value);
return scheduleEntryWriter.setEnabled(id, value);
}
@PostMapping("set/{id}/monday")
public ScheduleEntryDto setMonday(@PathVariable final long id, @RequestBody final boolean value) {
return scheduleEntryWriteService.set(id, ScheduleEntry::setMonday, value);
return scheduleEntryWriter.setMonday(id, value);
}
@PostMapping("set/{id}/tuesday")
public ScheduleEntryDto setTuesday(@PathVariable final long id, @RequestBody final boolean value) {
return scheduleEntryWriteService.set(id, ScheduleEntry::setTuesday, value);
return scheduleEntryWriter.setTuesday(id, value);
}
@PostMapping("set/{id}/wednesday")
public ScheduleEntryDto setWednesday(@PathVariable final long id, @RequestBody final boolean value) {
return scheduleEntryWriteService.set(id, ScheduleEntry::setWednesday, value);
return scheduleEntryWriter.setWednesday(id, value);
}
@PostMapping("set/{id}/thursday")
public ScheduleEntryDto setThursday(@PathVariable final long id, @RequestBody final boolean value) {
return scheduleEntryWriteService.set(id, ScheduleEntry::setThursday, value);
return scheduleEntryWriter.setThursday(id, value);
}
@PostMapping("set/{id}/friday")
public ScheduleEntryDto setFriday(@PathVariable final long id, @RequestBody final boolean value) {
return scheduleEntryWriteService.set(id, ScheduleEntry::setFriday, value);
return scheduleEntryWriter.setFriday(id, value);
}
@PostMapping("set/{id}/saturday")
public ScheduleEntryDto setSaturday(@PathVariable final long id, @RequestBody final boolean value) {
return scheduleEntryWriteService.set(id, ScheduleEntry::setSaturday, value);
return scheduleEntryWriter.setSaturday(id, value);
}
@PostMapping("set/{id}/sunday")
public ScheduleEntryDto setSunday(@PathVariable final long id, @RequestBody final boolean value) {
return scheduleEntryWriteService.set(id, ScheduleEntry::setSunday, value);
return scheduleEntryWriter.setSunday(id, value);
}
@PostMapping("set/{id}/type")
public ScheduleEntryDto setType(@PathVariable final long id, @RequestBody final String value) {
return scheduleEntryWriteService.set(id, ScheduleEntry::setType, ScheduleEntryType.valueOf(value));
return scheduleEntryWriter.setType(id, ScheduleEntryType.valueOf(value));
}
@PostMapping("set/{id}/zenith")
public ScheduleEntryDto setZenith(@PathVariable final long id, @RequestBody final String value) {
return scheduleEntryWriteService.set(id, ScheduleEntry::setZenith, Double.parseDouble(value));
return scheduleEntryWriter.setZenith(id, Double.parseDouble(value));
}
@PostMapping("set/{id}/hour")
public ScheduleEntryDto setHour(@PathVariable final long id, @RequestBody final int value) {
return scheduleEntryWriteService.set(id, ScheduleEntry::setHour, value);
return scheduleEntryWriter.setHour(id, value);
}
@PostMapping("set/{id}/minute")
public ScheduleEntryDto setMinute(@PathVariable final long id, @RequestBody final int value) {
return scheduleEntryWriteService.set(id, ScheduleEntry::setMinute, value);
return scheduleEntryWriter.setMinute(id, value);
}
@PostMapping("set/{id}/second")
public ScheduleEntryDto setSecond(@PathVariable final long id, @RequestBody final int value) {
return scheduleEntryWriteService.set(id, ScheduleEntry::setSecond, value);
return scheduleEntryWriter.setSecond(id, value);
}
@PostMapping("set/{id}/fuzzySeconds")
public ScheduleEntryDto setFuzzySeconds(@PathVariable final long id, @RequestBody final int value) {
return scheduleEntryWriteService.set(id, ScheduleEntry::setFuzzySeconds, value);
return scheduleEntryWriter.setFuzzySeconds(id, value);
}
@PostMapping("set/{id}/property")
public ScheduleEntryDto setProperty(@PathVariable final long id, @RequestBody(required = false) final Long propertyId) {
return scheduleEntryWriteService.set(id, entry -> entry.setProperty(propertyId == null ? null : propertyReader.getById(propertyId)));
return scheduleEntryWriter.setProperty(id, propertyId);
}
@PostMapping("set/{id}/value")
public ScheduleEntryDto setValue(@PathVariable final long id, @RequestBody final double value) {
return scheduleEntryWriteService.set(id, ScheduleEntry::setValue, value);
return scheduleEntryWriter.setValue(id, value);
}
@PostMapping("set/{id}/bulk")
public ScheduleEntryDto setBulk(@PathVariable final long id, @RequestBody(required = false) final Long bulkId) {
return scheduleEntryWriteService.set(id, entry -> entry.setBulk(bulkId == null ? null : bulkReader.getById(bulkId)));
return scheduleEntryWriter.setBulk(id, bulkId);
}
}

View File

@ -1,71 +0,0 @@
package de.ph87.homeautomation.schedule.entry;
import de.ph87.homeautomation.schedule.Schedule;
import de.ph87.homeautomation.schedule.ScheduleCalculator;
import de.ph87.homeautomation.schedule.ScheduleReader;
import de.ph87.homeautomation.web.WebSocketService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.ZonedDateTime;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class ScheduleEntryWriteService {
private final ScheduleEntryReader scheduleEntryReader;
private final ScheduleReader scheduleReader;
private final ScheduleCalculator scheduleCalculationService;
private final ScheduleEntryMapper scheduleEntryMapper;
private final ScheduleEntryRepository scheduleEntryRepository;
private final WebSocketService webSocketService;
@Deprecated(since = "Use alternative 'set' instead.", forRemoval = true)
public <T> ScheduleEntryDto set(final long id, final BiConsumer<ScheduleEntry, T> setter, final T value) {
final ScheduleEntry entry = scheduleEntryReader.getById(id);
setter.accept(entry, value);
final Schedule schedule = scheduleReader.getByEntry(entry);
scheduleCalculationService.calculateSchedule(schedule, ZonedDateTime.now());
return publish(entry, true);
}
public ScheduleEntryDto set(final long id, final Consumer<ScheduleEntry> setter) {
final ScheduleEntry entry = scheduleEntryReader.getById(id);
setter.accept(entry);
final Schedule schedule = scheduleReader.getByEntry(entry);
scheduleCalculationService.calculateSchedule(schedule, ZonedDateTime.now());
return publish(entry, true);
}
public ScheduleEntryDto create(final long scheduleId) {
final Schedule schedule = scheduleReader.getById(scheduleId);
final ScheduleEntry entry = scheduleEntryRepository.save(new ScheduleEntry(schedule));
schedule.getEntries().add(entry);
return publish(entry, true);
}
public void delete(final long id) {
final ScheduleEntry entry = scheduleEntryReader.getById(id);
scheduleReader.getByEntry(entry).getEntries().remove(entry);
scheduleEntryRepository.delete(entry);
publish(entry, false);
}
private ScheduleEntryDto publish(final ScheduleEntry entry, final boolean existing) {
final ScheduleEntryDto dto = scheduleEntryMapper.toDto(entry);
webSocketService.send(ScheduleEntryDto.class, dto, existing);
return dto;
}
}

View File

@ -0,0 +1,176 @@
package de.ph87.homeautomation.schedule.entry;
import de.ph87.homeautomation.bulk.BulkReader;
import de.ph87.homeautomation.property.PropertyReader;
import de.ph87.homeautomation.schedule.Schedule;
import de.ph87.homeautomation.schedule.ScheduleCalculator;
import de.ph87.homeautomation.schedule.ScheduleMapper;
import de.ph87.homeautomation.schedule.ScheduleReader;
import de.ph87.homeautomation.web.BadRequestException;
import de.ph87.homeautomation.web.WebSocketService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.ZonedDateTime;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import static java.lang.Integer.signum;
import static java.lang.Math.max;
import static java.lang.Math.min;
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class ScheduleEntryWriter {
private final ScheduleEntryReader scheduleEntryReader;
private final ScheduleReader scheduleReader;
private final ScheduleCalculator scheduleCalculationService;
private final ScheduleEntryMapper scheduleEntryMapper;
private final ScheduleEntryRepository scheduleEntryRepository;
private final WebSocketService webSocketService;
private final ScheduleMapper scheduleMapper;
private final PropertyReader propertyReader;
private final BulkReader bulkReader;
public ScheduleEntryDto create(final long scheduleId) {
final Schedule schedule = scheduleReader.getById(scheduleId);
final ScheduleEntry entry = scheduleEntryRepository.save(new ScheduleEntry(schedule));
schedule.getEntries().add(entry);
return publish(entry, true, true);
}
private <T> ScheduleEntryDto setValue(final long id, final BiConsumer<ScheduleEntry, T> setter, final T value) {
return modify(id, entry -> setter.accept(entry, value));
}
private ScheduleEntryDto modify(final long id, final Consumer<ScheduleEntry> setter) {
final ScheduleEntry entry = scheduleEntryReader.getById(id);
setter.accept(entry);
scheduleCalculationService.calculateSchedule(entry.getSchedule(), ZonedDateTime.now());
return publish(entry, true, true);
}
public void delete(final long id) {
final ScheduleEntry entry = scheduleEntryReader.getById(id);
setPosition(entry, entry.getSchedule().getEntries().size() - 1);
entry.getSchedule().getEntries().remove(entry);
scheduleEntryRepository.delete(entry);
publish(entry, false, true);
}
public ScheduleEntryDto setPosition(final long id, final int newPosition) {
return modify(id, entry -> {
if (newPosition < 0 || newPosition >= entry.getSchedule().getEntries().size()) {
throw new BadRequestException("Position must be between 0 and %d (including).", entry.getSchedule().getEntries().size() - 1);
}
setPosition(entry, newPosition);
});
}
public ScheduleEntryDto setEnabled(final long id, final boolean value) {
return setValue(id, ScheduleEntry::setEnabled, value);
}
public ScheduleEntryDto setMonday(final long id, final boolean value) {
return setValue(id, ScheduleEntry::setMonday, value);
}
public ScheduleEntryDto setTuesday(final long id, final boolean value) {
return setValue(id, ScheduleEntry::setTuesday, value);
}
public ScheduleEntryDto setWednesday(final long id, final boolean value) {
return setValue(id, ScheduleEntry::setWednesday, value);
}
public ScheduleEntryDto setThursday(final long id, final boolean value) {
return setValue(id, ScheduleEntry::setThursday, value);
}
public ScheduleEntryDto setFriday(final long id, final boolean value) {
return setValue(id, ScheduleEntry::setFriday, value);
}
public ScheduleEntryDto setSaturday(final long id, final boolean value) {
return setValue(id, ScheduleEntry::setSaturday, value);
}
public ScheduleEntryDto setSunday(final long id, final boolean value) {
return setValue(id, ScheduleEntry::setSunday, value);
}
public ScheduleEntryDto setType(final long id, final ScheduleEntryType value) {
return setValue(id, ScheduleEntry::setType, value);
}
public ScheduleEntryDto setZenith(final long id, final double value) {
return setValue(id, ScheduleEntry::setZenith, value);
}
public ScheduleEntryDto setHour(final long id, final int value) {
return setValue(id, ScheduleEntry::setHour, value);
}
public ScheduleEntryDto setMinute(final long id, final int value) {
return setValue(id, ScheduleEntry::setMinute, value);
}
public ScheduleEntryDto setSecond(final long id, final int value) {
return setValue(id, ScheduleEntry::setSecond, value);
}
public ScheduleEntryDto setFuzzySeconds(final long id, final int value) {
return setValue(id, ScheduleEntry::setFuzzySeconds, value);
}
public ScheduleEntryDto setValue(final long id, final double value) {
return setValue(id, ScheduleEntry::setValue, value);
}
public ScheduleEntryDto setProperty(final long id, final Long propertyId) {
return setValue(id, ScheduleEntry::setProperty, propertyId == null ? null : propertyReader.getById(propertyId));
}
public ScheduleEntryDto setBulk(final long id, final Long bulkId) {
return setValue(id, ScheduleEntry::setBulk, bulkId == null ? null : bulkReader.getById(bulkId));
}
private void setPosition(final ScheduleEntry entry, final int newPosition) {
if (newPosition == entry.getPosition()) {
return;
}
final int min = min(entry.getPosition(), newPosition);
final int max = max(entry.getPosition(), newPosition);
final int diff = signum(entry.getPosition() - newPosition);
for (final ScheduleEntry e : entry.getSchedule().getEntries()) {
if (e.getPosition() >= min && e.getPosition() <= max) {
e.setPosition(e.getPosition() + diff);
publish(e, true, false);
}
}
entry.setPosition(newPosition);
}
private ScheduleEntryDto publish(final ScheduleEntry entry, final boolean existing, final boolean publishSchedule) {
final ScheduleEntryDto dto = scheduleEntryMapper.toDto(entry);
webSocketService.send(ScheduleEntryDto.class, dto, existing);
if (publishSchedule) {
scheduleMapper.publish(entry.getSchedule(), true);
}
return dto;
}
}