UI: grouping by device.type + sorting by name

This commit is contained in:
Patrick Haßel 2023-06-19 09:30:15 +02:00
parent 5078d1e3bf
commit 59309b6a92
8 changed files with 55 additions and 21 deletions

View File

@ -62,6 +62,10 @@ export abstract class Device {
return a.position - b.position; return a.position - b.position;
} }
public static compareTitle(a: Device, b: Device): number {
return a.title.localeCompare(b.title);
}
abstract updateProperty(property: Property): void; abstract updateProperty(property: Property): void;
static filterByAreaIdAndRoomId(areaId: number | null, roomId: number | null): (_: Device) => boolean { static filterByAreaIdAndRoomId(areaId: number | null, roomId: number | null): (_: Device) => boolean {

View File

@ -24,7 +24,7 @@ export class DeviceService {
this.api.getList("device/findAll", Device.fromJson, compare, next); this.api.getList("device/findAll", Device.fromJson, compare, next);
} }
set(device: Device, key: string, value: any, next: (item: Device) => void): void { set(device: Device, key: string, value: any, next?: (item: Device) => void): void {
this.api.postReturnItem("device/set/" + device.id + "/" + key, value, Device.fromJson, next); this.api.postReturnItem("device/set/" + device.id + "/" + key, value, Device.fromJson, next);
} }

View File

@ -3,9 +3,16 @@
<div class="item" routerLink="/ScheduleList" routerLinkActive="itemActive"> <div class="item" routerLink="/ScheduleList" routerLinkActive="itemActive">
Zeitpläne Zeitpläne
</div> </div>
<div class="item" routerLink="/DeviceList" routerLinkActive="itemActive">
<div class="item" [routerLink]="['/DeviceList', {'type': 'DeviceSwitch'}]" [class.itemActive]="isRouteActive('/DeviceList', 'DeviceSwitch')">
Geräte Geräte
</div> </div>
<div class="item" [routerLink]="['/DeviceList', {'type': 'DeviceShutter'}]" [class.itemActive]="isRouteActive('/DeviceList', 'DeviceShutter')">
Rollläden
</div>
<div class="item" [routerLink]="['/DeviceList', {'type': 'DeviceStateScene'}]" [class.itemActive]="isRouteActive('/DeviceList', 'DeviceStateScene')">
Gruppen
</div>
<div class="item" routerLink="/BulkList" routerLinkActive="itemActive"> <div class="item" routerLink="/BulkList" routerLinkActive="itemActive">
Massenausführungen Massenausführungen

View File

@ -1,4 +1,5 @@
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {Params, Router, UrlSegment} from "@angular/router";
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
@ -8,10 +9,27 @@ import {Component} from '@angular/core';
export class AppComponent { export class AppComponent {
title = 'angular'; title = 'angular';
private url: UrlSegment[];
private params: Params;
constructor( constructor(
// nothing readonly router: Router,
) { ) {
// nothing // nothing
} }
isRouteActive(base: string, type: string): boolean {
const parts = this.router.url.split(';');
if (parts[0] === base) {
for (let i = 1; i < parts.length; i++) {
const param = parts[i].split('=');
if (param[0] === 'type' && param[1] === type) {
return true;
}
}
}
return false;
}
} }

View File

@ -53,7 +53,7 @@ export class DeviceEditorComponent implements OnInit {
delete(): void { delete(): void {
if (confirm(this.getDeviceTypeTitle() + " \"" + this.device.title + "\" wirklich löschen?")) { if (confirm(this.getDeviceTypeTitle() + " \"" + this.device.title + "\" wirklich löschen?")) {
this.deviceService.delete(this.device, () => this.router.navigate(["/DeviceList"])); this.deviceService.delete(this.device, () => this.router.navigate(["/DeviceList", {type: this.device.type}]));
} }
} }

View File

@ -1,17 +1,13 @@
<div class="config"> <div class="config">
<select [(ngModel)]="createType">
<option ngValue="DeviceSwitch">Schalter</option>
<option ngValue="DeviceShutter">Rollladen</option>
</select>
<button (click)="create()">+ Hinzufügen</button> <button (click)="create()">+ Hinzufügen</button>
</div> </div>
<ng-container *ngFor="let device of devices.sort(Device.comparePosition); trackBy: Device.trackBy"> <ng-container *ngFor="let device of devices; trackBy: Device.trackBy">
<ng-container [ngSwitch]="device.type"> <ng-container [ngSwitch]="device.type">
<div class="device" *ngSwitchCase="'DeviceSwitch'" [ngClass]="getSwitchClassList(device)"> <div class="device" *ngSwitchCase="'DeviceSwitch'" [ngClass]="getSwitchClassList(device)">
<div class="title"> <div class="title">
{{device.title}} <app-text [initial]="device.title" (valueChange)="set(device, 'title', $event)"></app-text>
</div> </div>
<div class="edit" [routerLink]="['/Device', {id: device.id}]"> <div class="edit" [routerLink]="['/Device', {id: device.id}]">
<fa-icon [icon]="faEdit"></fa-icon> <fa-icon [icon]="faEdit"></fa-icon>
@ -24,7 +20,7 @@
<div class="device" *ngSwitchCase="'DeviceStateScene'" [ngClass]="getStateSceneClassList(device)"> <div class="device" *ngSwitchCase="'DeviceStateScene'" [ngClass]="getStateSceneClassList(device)">
<div class="title"> <div class="title">
{{device.title}} <app-text [initial]="device.title" (valueChange)="set(device, 'title', $event)"></app-text>
</div> </div>
<div class="edit" [routerLink]="['/Device', {id: device.id}]"> <div class="edit" [routerLink]="['/Device', {id: device.id}]">
<fa-icon [icon]="faEdit"></fa-icon> <fa-icon [icon]="faEdit"></fa-icon>
@ -38,7 +34,7 @@
<div class="device" *ngSwitchCase="'DeviceShutter'" [ngClass]="getShutterClassList(device)"> <div class="device" *ngSwitchCase="'DeviceShutter'" [ngClass]="getShutterClassList(device)">
<div class="title"> <div class="title">
{{device.title}} <app-text [initial]="device.title" (valueChange)="set(device, 'title', $event)"></app-text>
</div> </div>
<div class="edit" [routerLink]="['/Device', {id: device.id}]"> <div class="edit" [routerLink]="['/Device', {id: device.id}]">
<fa-icon [icon]="faEdit"></fa-icon> <fa-icon [icon]="faEdit"></fa-icon>

View File

@ -5,6 +5,7 @@ import {Device, DeviceShutter, DeviceStateScene, DeviceSwitch} from "../../../ap
import {faEdit} from '@fortawesome/free-regular-svg-icons'; import {faEdit} from '@fortawesome/free-regular-svg-icons';
import {Scene} from "../../../api/scene/Scene"; import {Scene} from "../../../api/scene/Scene";
import {SceneService} from "../../../api/scene/scene.service"; import {SceneService} from "../../../api/scene/scene.service";
import {ActivatedRoute} from "@angular/router";
@Component({ @Component({
selector: 'app-device-list', selector: 'app-device-list',
@ -19,30 +20,34 @@ export class DeviceListComponent implements OnInit {
devices: Device[] = []; devices: Device[] = [];
scenes: Scene[] = []; typeFilter: string;
createType: string = "DeviceSwitch"; scenes: Scene[] = [];
constructor( constructor(
readonly deviceService: DeviceService, readonly deviceService: DeviceService,
readonly sceneService: SceneService, readonly sceneService: SceneService,
readonly propertyService: PropertyService, readonly propertyService: PropertyService,
readonly activatedRoute: ActivatedRoute,
) { ) {
// nothing // nothing
} }
ngOnInit(): void { ngOnInit(): void {
this.propertyService.subscribe(update => this.devices.forEach(d => d.updateProperty(update.payload))); this.activatedRoute.params.subscribe(params => {
this.typeFilter = params['type'];
this.propertyService.subscribe(update => this.devices.forEach(d => d.updateProperty(update.payload)));
this.deviceService.subscribe(update => this.updateDevice(update.payload, update.existing)); this.deviceService.subscribe(update => this.updateDevice(update.payload, update.existing));
this.deviceService.findAll(devices => this.devices = devices); this.deviceService.findAll(devices => this.devices = devices.filter(d => !this.typeFilter || this.typeFilter == d.type).sort(Device.compareTitle));
this.sceneService.subscribe(update => this.updateScene(update.payload, update.existing)); this.sceneService.subscribe(update => this.updateScene(update.payload, update.existing));
this.sceneService.findAll(scenes => this.scenes = scenes); this.sceneService.findAll(scenes => this.scenes = scenes);
});
} }
create(): void { create(): void {
this.deviceService.create(this.createType, device => this.updateDevice(device, true)); this.deviceService.create(this.typeFilter, device => this.updateDevice(device, true));
} }
private updateDevice(device: Device, existing: boolean): void { private updateDevice(device: Device, existing: boolean): void {
@ -101,4 +106,8 @@ export class DeviceListComponent implements OnInit {
return device.sceneNumbers.map(sceneNumber => this.scenes.find(scene => scene.number === sceneNumber)).filter(scene => scene !== undefined).map(s => s as Scene); return device.sceneNumbers.map(sceneNumber => this.scenes.find(scene => scene.number === sceneNumber)).filter(scene => scene !== undefined).map(s => s as Scene);
} }
set(device: Device, key: string, value: any): void {
this.deviceService.set(device, key, value);
}
} }

View File

@ -4,7 +4,7 @@
import {getBaseUrl} from "./UrlHelper"; import {getBaseUrl} from "./UrlHelper";
const PROD: boolean = false; const PROD: boolean = true;
export const environment = { export const environment = {
production: false, production: false,