Rename: Taggable -> Thing

This commit is contained in:
Patrick Haßel 2024-11-28 15:21:09 +01:00
parent b6f3db79e4
commit 8133080e9c
33 changed files with 178 additions and 213 deletions

View File

@ -1,18 +1,19 @@
import {Property} from "../Property/Property"; import {Property} from "../Property/Property";
import {orNull, validateString} from "../api/validators"; import {orNull, validateString} from "../api/validators";
import {Area} from '../Area/Area'; import {Area} from '../Area/Area';
import {Thing} from '../Thing/Thing';
export class Device { export class Device extends Thing {
constructor( constructor(
readonly area: Area, area: Area,
readonly uuid: string, uuid: string,
readonly name: string, name: string,
readonly slug: string, slug: string,
readonly statePropertyId: string, readonly statePropertyId: string,
readonly stateProperty: Property | null, readonly stateProperty: Property | null,
) { ) {
// super(area, uuid, name, slug);
} }
static fromJson(json: any): Device { static fromJson(json: any): Device {
@ -26,30 +27,4 @@ export class Device {
); );
} }
get nameOrArea(): string {
if (this.name === '') {
return this.area.name;
}
return this.name;
}
get nameWithArea(): string {
if (this.name === '') {
return this.area.name;
}
return this.area.name + ' ' + this.name;
}
static trackBy(index: number, device: Device) {
return device.uuid;
}
static compareByAreaThenName(a: Device, b: Device): number {
const area = Area.compareByName(a.area, b.area);
if (area !== 0) {
return area;
}
return a.name.localeCompare(b.name);
}
} }

View File

@ -2,18 +2,19 @@ import {Property} from "../Property/Property";
import {orNull, validateString} from "../api/validators"; import {orNull, validateString} from "../api/validators";
import {Area} from '../Area/Area'; import {Area} from '../Area/Area';
import {Thing} from '../Thing/Thing';
export class Shutter { export class Shutter extends Thing {
constructor( constructor(
readonly area: Area, area: Area,
readonly uuid: string, uuid: string,
readonly name: string, name: string,
readonly slug: string, slug: string,
readonly positionPropertyId: string, readonly positionPropertyId: string,
readonly positionProperty: Property | null, readonly positionProperty: Property | null,
) { ) {
// super(area, uuid, name, slug);
} }
static fromJson(json: any): Shutter { static fromJson(json: any): Shutter {
@ -27,30 +28,4 @@ export class Shutter {
); );
} }
get nameOrArea(): string {
if (this.name === '') {
return this.area.name;
}
return this.name;
}
get nameWithArea(): string {
if (this.name === '') {
return this.area.name;
}
return this.area.name + ' ' + this.name;
}
static trackBy(index: number, shutter: Shutter) {
return shutter.uuid;
}
static compareByAreaThenName(a: Shutter, b: Shutter): number {
const area = Area.compareByName(a.area, b.area);
if (area !== 0) {
return area;
}
return a.name.localeCompare(b.name);
}
} }

View File

@ -1,5 +0,0 @@
<div class="tileContainer taggableList">
<app-taggable-tile [now]="now" [taggable]="taggable" *ngFor="let taggable of list"></app-taggable-tile>
</div>

View File

@ -0,0 +1,41 @@
import {Area} from '../Area/Area';
export abstract class Thing {
protected constructor(
readonly area: Area,
readonly uuid: string,
readonly name: string,
readonly slug: string,
) {
//
}
get nameOrArea(): string {
if (this.name === '') {
return this.area.name;
}
return this.name;
}
get nameWithArea(): string {
if (this.name === '') {
return this.area.name;
}
return this.area.name + ' ' + this.name;
}
static trackBy(index: number, thing: Thing) {
return thing.uuid;
}
static compareByAreaThenName(a: Thing, b: Thing): number {
const area = Area.compareByName(a.area, b.area);
if (area !== 0) {
return area;
}
return a.name.localeCompare(b.name);
}
}

View File

@ -1,4 +1,4 @@
export class TaggableFilter { export class ThingFilter {
tag: string = ""; tag: string = "";

View File

@ -3,6 +3,6 @@
<app-search [(search)]="filter.search" (doSearch)="liveList.refresh()"></app-search> <app-search [(search)]="filter.search" (doSearch)="liveList.refresh()"></app-search>
</div> </div>
<div class="flexBoxRest verticalScroll"> <div class="flexBoxRest verticalScroll">
<app-taggable-list [list]="liveList.list"></app-taggable-list> <app-thing-list [list]="liveList.list"></app-thing-list>
</div> </div>
</div> </div>

View File

@ -1,46 +1,46 @@
import {Component, OnDestroy, OnInit} from '@angular/core'; import {Component, OnDestroy, OnInit} from '@angular/core';
import {TaggableListComponent} from '../taggable-list/taggable-list.component'; import {ThingListComponent} from '../thing-list/thing-list.component';
import {Taggable} from '../Taggable'; import {Thing} from '../Thing';
import {TaggableService} from '../taggable.service'; import {ThingService} from '../thing.service';
import {FormsModule} from '@angular/forms'; import {FormsModule} from '@angular/forms';
import {Subscription} from 'rxjs'; import {Subscription} from 'rxjs';
import {TaggableFilter} from '../TaggableFilter'; import {ThingFilter} from '../ThingFilter';
import {ActivatedRoute} from '@angular/router'; import {ActivatedRoute} from '@angular/router';
import {CrudLiveList} from '../../api/CrudLiveList'; import {CrudLiveList} from '../../api/CrudLiveList';
import {SearchComponent} from '../../shared/search/search.component'; import {SearchComponent} from '../../shared/search/search.component';
@Component({ @Component({
selector: 'app-taggable-list-page', selector: 'app-thing-list-page',
standalone: true, standalone: true,
imports: [ imports: [
TaggableListComponent, ThingListComponent,
FormsModule, FormsModule,
SearchComponent SearchComponent
], ],
templateUrl: './taggable-list-page.component.html', templateUrl: './thing-list-page.component.html',
styleUrl: './taggable-list-page.component.less' styleUrl: './thing-list-page.component.less'
}) })
export class TaggableListPageComponent implements OnInit, OnDestroy { export class ThingListPageComponent implements OnInit, OnDestroy {
private readonly subs: Subscription[] = []; private readonly subs: Subscription[] = [];
protected readonly filter: TaggableFilter = new TaggableFilter(); protected readonly filter: ThingFilter = new ThingFilter();
protected readonly liveList: CrudLiveList<Taggable>; protected readonly liveList: CrudLiveList<Thing>;
private tagSet: boolean = false; private tagSet: boolean = false;
constructor( constructor(
protected readonly taggableService: TaggableService, protected readonly thingService: ThingService,
protected readonly activatedRoute: ActivatedRoute, protected readonly activatedRoute: ActivatedRoute,
) { ) {
this.subs.push(this.liveList = new CrudLiveList( this.subs.push(this.liveList = new CrudLiveList(
this.taggableService, this.thingService,
false, false,
undefined, undefined,
next => { next => {
if (this.tagSet) { if (this.tagSet) {
this.taggableService.filter(this.filter, next); this.thingService.filter(this.filter, next);
} else { } else {
next([]); next([]);
} }
@ -53,7 +53,6 @@ export class TaggableListPageComponent implements OnInit, OnDestroy {
this.tagSet = 'tag' in params; this.tagSet = 'tag' in params;
if (this.tagSet) { if (this.tagSet) {
this.filter.tag = params['tag'] || ''; this.filter.tag = params['tag'] || '';
console.log(this.filter.tag);
this.liveList.refresh(); this.liveList.refresh();
} else { } else {
this.liveList.clear(); this.liveList.clear();

View File

@ -0,0 +1,5 @@
<div class="tileContainer">
<app-thing-tile [now]="now" [thing]="thing" *ngFor="let thing of sorted()"></app-thing-tile>
</div>

View File

@ -1,27 +1,27 @@
import {Component, Input, OnDestroy, OnInit} from '@angular/core'; import {Component, Input, OnDestroy, OnInit} from '@angular/core';
import {NgForOf} from '@angular/common'; import {NgForOf} from '@angular/common';
import {Subscription, timer} from 'rxjs'; import {Subscription, timer} from 'rxjs';
import {TaggableTileComponent} from '../taggable-tile/taggable-tile.component'; import {ThingTileComponent} from '../thing-tile/thing-tile.component';
import {Taggable} from '../Taggable'; import {Thing} from '../Thing';
@Component({ @Component({
selector: 'app-taggable-list', selector: 'app-thing-list',
standalone: true, standalone: true,
imports: [ imports: [
NgForOf, NgForOf,
TaggableTileComponent ThingTileComponent
], ],
templateUrl: './taggable-list.component.html', templateUrl: './thing-list.component.html',
styleUrl: './taggable-list.component.less' styleUrl: './thing-list.component.less'
}) })
export class TaggableListComponent implements OnInit, OnDestroy { export class ThingListComponent implements OnInit, OnDestroy {
private readonly subs: Subscription[] = []; private readonly subs: Subscription[] = [];
protected now: Date = new Date(); protected now: Date = new Date();
@Input() @Input()
list: Taggable[] = []; list: Thing[] = [];
ngOnInit(): void { ngOnInit(): void {
this.now = new Date(); this.now = new Date();
@ -32,4 +32,8 @@ export class TaggableListComponent implements OnInit, OnDestroy {
this.subs.forEach(sub => sub.unsubscribe()); this.subs.forEach(sub => sub.unsubscribe());
} }
sorted(): Thing[] {
return this.list.sort(Thing.compareByAreaThenName);
}
} }

View File

@ -6,10 +6,10 @@ import {DeviceTileComponent} from '../../Device/device-tile/device-tile.componen
import {NgIf} from '@angular/common'; import {NgIf} from '@angular/common';
import {ShutterTileComponent} from '../../Shutter/shutter-tile/shutter-tile.component'; import {ShutterTileComponent} from '../../Shutter/shutter-tile/shutter-tile.component';
import {TunableTileComponent} from '../../Tunable/tunable-tile/tunable-tile.component'; import {TunableTileComponent} from '../../Tunable/tunable-tile/tunable-tile.component';
import {Taggable} from '../Taggable'; import {Thing} from '../Thing';
@Component({ @Component({
selector: 'app-taggable-tile', selector: 'app-thing-tile',
standalone: true, standalone: true,
imports: [ imports: [
DeviceTileComponent, DeviceTileComponent,
@ -17,39 +17,39 @@ import {Taggable} from '../Taggable';
ShutterTileComponent, ShutterTileComponent,
TunableTileComponent TunableTileComponent
], ],
templateUrl: './taggable-tile.component.html', templateUrl: './thing-tile.component.html',
styleUrl: './taggable-tile.component.less' styleUrl: './thing-tile.component.less'
}) })
export class TaggableTileComponent { export class ThingTileComponent {
@Input() @Input()
now!: Date; now!: Date;
@Input() @Input()
taggable!: Taggable; thing!: Thing;
asDevice(): Device { asDevice(): Device {
return this.taggable as Device; return this.thing as Device;
} }
isDevice(): boolean { isDevice(): boolean {
return this.taggable instanceof Device; return this.thing instanceof Device;
} }
asShutter(): Shutter { asShutter(): Shutter {
return this.taggable as Shutter; return this.thing as Shutter;
} }
isShutter(): boolean { isShutter(): boolean {
return this.taggable instanceof Shutter; return this.thing instanceof Shutter;
} }
asTunable(): Tunable { asTunable(): Tunable {
return this.taggable as Tunable; return this.thing as Tunable;
} }
isTunable(): boolean { isTunable(): boolean {
return this.taggable instanceof Tunable; return this.thing instanceof Tunable;
} }
} }

View File

@ -1,17 +1,18 @@
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {ApiService} from '../api/api.service'; import {ApiService} from '../api/api.service';
import {CrudService} from '../api/CrudService'; import {CrudService} from '../api/CrudService';
import {Taggable, taggableFromJson} from './Taggable'; import {Thing} from './Thing';
import {Next} from '../api/types'; import {Next} from '../api/types';
import {Subject, Subscription} from 'rxjs'; import {Subject, Subscription} from 'rxjs';
import {DeviceService} from '../Device/device.service'; import {DeviceService} from '../Device/device.service';
import {ShutterService} from '../Shutter/shutter.service'; import {ShutterService} from '../Shutter/shutter.service';
import {TunableService} from '../Tunable/tunable.service'; import {TunableService} from '../Tunable/tunable.service';
import {thingFromJson} from './thingFromJson';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class TaggableService extends CrudService<Taggable> { export class ThingService extends CrudService<Thing> {
constructor( constructor(
apiService: ApiService, apiService: ApiService,
@ -19,11 +20,11 @@ export class TaggableService extends CrudService<Taggable> {
protected readonly shutterService: ShutterService, protected readonly shutterService: ShutterService,
protected readonly tunableService: TunableService, protected readonly tunableService: TunableService,
) { ) {
super(apiService, ['Taggable'], taggableFromJson); super(apiService, ['Thing'], thingFromJson);
} }
override subscribe(next: Next<Taggable>): Subscription { override subscribe(next: Next<Thing>): Subscription {
const subject = new Subject<Taggable>(); const subject = new Subject<Thing>();
this.deviceService.subscribe(next => subject.next(next)); this.deviceService.subscribe(next => subject.next(next));
this.shutterService.subscribe(next => subject.next(next)); this.shutterService.subscribe(next => subject.next(next));
this.tunableService.subscribe(next => subject.next(next)); this.tunableService.subscribe(next => subject.next(next));

View File

@ -1,11 +1,10 @@
import {validateAndRemoveDtoSuffix} from "../api/validators";
import {Device} from "../Device/Device"; import {Device} from "../Device/Device";
import {Shutter} from "../Shutter/Shutter"; import {Shutter} from "../Shutter/Shutter";
import {Tunable} from "../Tunable/Tunable"; import {Tunable} from "../Tunable/Tunable";
import {validateAndRemoveDtoSuffix} from "../api/validators"; import {Thing} from "./Thing";
export type Taggable = Device | Shutter | Tunable; export function thingFromJson(json: any): Thing {
export function taggableFromJson(json: any): Taggable {
const _type_ = validateAndRemoveDtoSuffix(json._type_); const _type_ = validateAndRemoveDtoSuffix(json._type_);
switch (_type_) { switch (_type_) {
case 'Device': case 'Device':

View File

@ -1,14 +1,15 @@
import {Property} from "../Property/Property"; import {Property} from "../Property/Property";
import {orNull, validateString} from "../api/validators"; import {orNull, validateString} from "../api/validators";
import {Area} from '../Area/Area'; import {Area} from '../Area/Area';
import {Thing} from '../Thing/Thing';
export class Tunable { export class Tunable extends Thing {
constructor( constructor(
readonly area: Area, area: Area,
readonly uuid: string, uuid: string,
readonly name: string, name: string,
readonly slug: string, slug: string,
readonly statePropertyId: string, readonly statePropertyId: string,
readonly stateProperty: Property | null, readonly stateProperty: Property | null,
readonly brightnessPropertyId: string, readonly brightnessPropertyId: string,
@ -16,7 +17,7 @@ export class Tunable {
readonly coldnessPropertyId: string, readonly coldnessPropertyId: string,
readonly coldnessProperty: Property | null, readonly coldnessProperty: Property | null,
) { ) {
// super(area, uuid, name, slug);
} }
static fromJson(json: any): Tunable { static fromJson(json: any): Tunable {
@ -34,30 +35,4 @@ export class Tunable {
); );
} }
get nameOrArea(): string {
if (this.name === '') {
return this.area.name;
}
return this.name;
}
get nameWithArea(): string {
if (this.name === '') {
return this.area.name;
}
return this.area.name + ' ' + this.name;
}
static trackBy(index: number, tunable: Tunable) {
return tunable.uuid;
}
static compareByAreaThenName(a: Tunable, b: Tunable): number {
const area = Area.compareByName(a.area, b.area);
if (area !== 0) {
return area;
}
return a.name.localeCompare(b.name);
}
} }

View File

@ -2,7 +2,7 @@ import {CrudService} from "./CrudService";
import {Subscription} from "rxjs"; import {Subscription} from "rxjs";
import {Next} from './types'; import {Next} from './types';
export interface UUID { interface UUID {
uuid: string; uuid: string;

View File

@ -1,9 +1,9 @@
<div class="flexBox"> <div class="flexBox">
<div class="flexBoxFixed menu"> <div class="flexBoxFixed menu">
<div class="item itemLeft" routerLink="Dashboard" routerLinkActive="active">Dash</div> <div class="item itemLeft" routerLink="Dashboard" routerLinkActive="active">Dash</div>
<div class="item itemLeft" routerLink="TaggableList/device" routerLinkActive="active">Geräte</div> <div class="item itemLeft" routerLink="ThingList/device" routerLinkActive="active">Geräte</div>
<div class="item itemLeft" routerLink="TaggableList/light" routerLinkActive="active">Licht</div> <div class="item itemLeft" routerLink="ThingList/light" routerLinkActive="active">Licht</div>
<div class="item itemLeft" routerLink="TaggableList/shutter" routerLinkActive="active">Rollladen</div> <div class="item itemLeft" routerLink="ThingList/shutter" routerLinkActive="active">Rollladen</div>
<div class="item itemRight" routerLink="GroupList" routerLinkActive="active">KNX</div> <div class="item itemRight" routerLink="GroupList" routerLinkActive="active">KNX</div>
</div> </div>
<div class="flexBoxRest"> <div class="flexBoxRest">

View File

@ -1,12 +1,12 @@
import {Routes} from '@angular/router'; import {Routes} from '@angular/router';
import {KnxGroupListPageComponent} from './Group/knx-group-list-page/knx-group-list-page.component'; import {KnxGroupListPageComponent} from './Group/knx-group-list-page/knx-group-list-page.component';
import {DashboardComponent} from './dashboard/dashboard.component'; import {DashboardComponent} from './dashboard/dashboard.component';
import {TaggableListPageComponent} from './Taggable/taggable-list-page/taggable-list-page.component'; import {ThingListPageComponent} from './Thing/thing-list-page/thing-list-page.component';
export const routes: Routes = [ export const routes: Routes = [
{path: 'Dashboard', component: DashboardComponent}, {path: 'Dashboard', component: DashboardComponent},
{path: 'GroupList', component: KnxGroupListPageComponent}, {path: 'GroupList', component: KnxGroupListPageComponent},
{path: 'TaggableList', component: TaggableListPageComponent}, {path: 'ThingList', component: ThingListPageComponent},
{path: 'TaggableList/:tag', component: TaggableListPageComponent}, {path: 'ThingList/:tag', component: ThingListPageComponent},
{path: '**', redirectTo: 'Dashboard'}, {path: '**', redirectTo: 'Dashboard'},
]; ];

View File

@ -1,7 +1,7 @@
package de.ph87.home.device; package de.ph87.home.device;
import de.ph87.home.area.Area; import de.ph87.home.area.Area;
import de.ph87.home.tag.taggable.ITaggable; import de.ph87.home.thing.IThing;
import de.ph87.home.tag.Tag; import de.ph87.home.tag.Tag;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.*; import lombok.*;
@ -16,7 +16,7 @@ import static de.ph87.home.common.ListHelpers.merge;
@Getter @Getter
@ToString @ToString
@NoArgsConstructor @NoArgsConstructor
public class Device implements ITaggable { public class Device implements IThing {
@Id @Id
@NonNull @NonNull

View File

@ -8,9 +8,9 @@ import de.ph87.home.property.*;
import de.ph87.home.search.SearchableDto; import de.ph87.home.search.SearchableDto;
import de.ph87.home.tag.Tag; import de.ph87.home.tag.Tag;
import de.ph87.home.tag.TagReader; import de.ph87.home.tag.TagReader;
import de.ph87.home.tag.TaggableDto; import de.ph87.home.thing.ThingDto;
import de.ph87.home.tag.taggable.ITaggableService; import de.ph87.home.thing.IThingService;
import de.ph87.home.tag.taggable.TaggableFilter; import de.ph87.home.thing.ThingFilter;
import jakarta.annotation.Nullable; import jakarta.annotation.Nullable;
import lombok.NonNull; import lombok.NonNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -28,7 +28,7 @@ import static de.ph87.home.common.crud.SearchHelper.search;
@Service @Service
@Transactional @Transactional
@RequiredArgsConstructor @RequiredArgsConstructor
public class DeviceService implements ITaggableService<DeviceDto> { public class DeviceService implements IThingService<DeviceDto> {
private final PropertyService propertyService; private final PropertyService propertyService;
@ -104,12 +104,12 @@ public class DeviceService implements ITaggableService<DeviceDto> {
} }
@Override @Override
public List<TaggableDto<DeviceDto>> findTaggables(final @NonNull TaggableFilter filter) { public List<ThingDto<DeviceDto>> filter(final @NonNull ThingFilter filter) {
return deviceRepository.findAll().stream() return deviceRepository.findAll().stream()
.filter(device -> search(filter.getSearch(), device.getSearchableValues())) .filter(device -> search(filter.getSearch(), device.getSearchableValues()))
.filter(device -> device.tagListAnyMatch(filter.getTag())) .filter(device -> device.tagListAnyMatch(filter.getTag()))
.map(this::toDto) .map(this::toDto)
.map(TaggableDto::new) .map(ThingDto::new)
.toList(); .toList();
} }

View File

@ -1,7 +1,7 @@
package de.ph87.home.shutter; package de.ph87.home.shutter;
import de.ph87.home.area.Area; import de.ph87.home.area.Area;
import de.ph87.home.tag.taggable.ITaggable; import de.ph87.home.thing.IThing;
import de.ph87.home.tag.Tag; import de.ph87.home.tag.Tag;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.*; import lombok.*;
@ -16,7 +16,7 @@ import static de.ph87.home.common.ListHelpers.merge;
@Getter @Getter
@ToString @ToString
@NoArgsConstructor @NoArgsConstructor
public class Shutter implements ITaggable { public class Shutter implements IThing {
@Id @Id
@NonNull @NonNull

View File

@ -8,9 +8,9 @@ import de.ph87.home.property.*;
import de.ph87.home.search.SearchableDto; import de.ph87.home.search.SearchableDto;
import de.ph87.home.tag.Tag; import de.ph87.home.tag.Tag;
import de.ph87.home.tag.TagReader; import de.ph87.home.tag.TagReader;
import de.ph87.home.tag.TaggableDto; import de.ph87.home.thing.ThingDto;
import de.ph87.home.tag.taggable.ITaggableService; import de.ph87.home.thing.IThingService;
import de.ph87.home.tag.taggable.TaggableFilter; import de.ph87.home.thing.ThingFilter;
import jakarta.annotation.Nullable; import jakarta.annotation.Nullable;
import lombok.NonNull; import lombok.NonNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -28,7 +28,7 @@ import static de.ph87.home.common.crud.SearchHelper.search;
@Service @Service
@Transactional @Transactional
@RequiredArgsConstructor @RequiredArgsConstructor
public class ShutterService implements ITaggableService<ShutterDto> { public class ShutterService implements IThingService<ShutterDto> {
private final AreaService areaService; private final AreaService areaService;
@ -110,12 +110,12 @@ public class ShutterService implements ITaggableService<ShutterDto> {
} }
@Override @Override
public List<TaggableDto<ShutterDto>> findTaggables(final @NonNull TaggableFilter filter) { public List<ThingDto<ShutterDto>> filter(final @NonNull ThingFilter filter) {
return shutterRepository.findAll().stream() return shutterRepository.findAll().stream()
.filter(shutter -> shutter.tagListAnyMatch(filter.getTag())) .filter(shutter -> shutter.tagListAnyMatch(filter.getTag()))
.filter(device -> search(filter.getSearch(), device.getSearchableValues())) .filter(device -> search(filter.getSearch(), device.getSearchableValues()))
.map(this::toDto) .map(this::toDto)
.map(TaggableDto::new) .map(ThingDto::new)
.toList(); .toList();
} }

View File

@ -1,13 +0,0 @@
package de.ph87.home.tag.taggable;
import de.ph87.home.search.ISearchableService;
import de.ph87.home.tag.TaggableDto;
import lombok.NonNull;
import java.util.List;
public interface ITaggableService<T> extends ISearchableService<T> {
List<TaggableDto<T>> findTaggables(final @NonNull TaggableFilter filter);
}

View File

@ -1,4 +1,4 @@
package de.ph87.home.tag.taggable; package de.ph87.home.thing;
import de.ph87.home.search.ISearchable; import de.ph87.home.search.ISearchable;
import de.ph87.home.tag.Tag; import de.ph87.home.tag.Tag;
@ -6,7 +6,7 @@ import lombok.NonNull;
import java.util.List; import java.util.List;
public interface ITaggable extends ISearchable { public interface IThing extends ISearchable {
List<Tag> getTagList(); List<Tag> getTagList();

View File

@ -0,0 +1,12 @@
package de.ph87.home.thing;
import de.ph87.home.search.ISearchableService;
import lombok.NonNull;
import java.util.List;
public interface IThingService<T> extends ISearchableService<T> {
List<ThingDto<T>> filter(@NonNull final ThingFilter filter);
}

View File

@ -1,7 +1,5 @@
package de.ph87.home.tag.taggable; package de.ph87.home.thing;
import de.ph87.home.tag.TaggableDto;
import jakarta.annotation.Nullable;
import lombok.NonNull; import lombok.NonNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -13,14 +11,14 @@ import java.util.List;
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
@RequestMapping("Taggable") @RequestMapping("Thing")
public class TaggableController { public class ThingController {
private final TaggableService taggableService; private final ThingService thingService;
@PostMapping(value = "list") @PostMapping(value = "list")
public List<? extends TaggableDto<?>> list(@RequestBody @NonNull final TaggableFilter filter) { public List<? extends ThingDto<?>> list(@RequestBody @NonNull final ThingFilter filter) {
return taggableService.list(filter); return thingService.list(filter);
} }
} }

View File

@ -1,15 +1,15 @@
package de.ph87.home.tag; package de.ph87.home.thing;
import lombok.Data; import lombok.Data;
@Data @Data
public class TaggableDto<T> { public class ThingDto<T> {
private final String _type_; private final String _type_;
private final T payload; private final T payload;
public TaggableDto(final T payload) { public ThingDto(final T payload) {
this.payload = payload; this.payload = payload;
this._type_ = payload.getClass().getSimpleName(); this._type_ = payload.getClass().getSimpleName();
} }

View File

@ -1,10 +1,10 @@
package de.ph87.home.tag.taggable; package de.ph87.home.thing;
import lombok.Data; import lombok.Data;
import lombok.NonNull; import lombok.NonNull;
@Data @Data
public class TaggableFilter { public class ThingFilter {
@NonNull @NonNull
private final String tag; private final String tag;

View File

@ -1,7 +1,6 @@
package de.ph87.home.tag.taggable; package de.ph87.home.thing;
import de.ph87.home.common.ListHelpers; import de.ph87.home.common.ListHelpers;
import de.ph87.home.tag.TaggableDto;
import lombok.NonNull; import lombok.NonNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -15,14 +14,14 @@ import java.util.List;
@Service @Service
@Transactional @Transactional
@RequiredArgsConstructor @RequiredArgsConstructor
public class TaggableService { public class ThingService {
private final List<ITaggableService<?>> taggableServices; private final List<IThingService<?>> thingServices;
@NonNull @NonNull
public List<? extends TaggableDto<?>> list(@NonNull final TaggableFilter filter) { public List<? extends ThingDto<?>> list(@NonNull final ThingFilter filter) {
return taggableServices.stream() return thingServices.stream()
.map(iTaggableService -> iTaggableService.findTaggables(filter)) .map(iThingService -> iThingService.filter(filter))
.reduce(ListHelpers::merge) .reduce(ListHelpers::merge)
.orElse(new ArrayList<>()); .orElse(new ArrayList<>());
} }

View File

@ -1,7 +1,7 @@
package de.ph87.home.tunable; package de.ph87.home.tunable;
import de.ph87.home.area.Area; import de.ph87.home.area.Area;
import de.ph87.home.tag.taggable.ITaggable; import de.ph87.home.thing.IThing;
import de.ph87.home.tag.Tag; import de.ph87.home.tag.Tag;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.*; import lombok.*;
@ -16,7 +16,7 @@ import static de.ph87.home.common.ListHelpers.merge;
@Getter @Getter
@ToString @ToString
@NoArgsConstructor @NoArgsConstructor
public class Tunable implements ITaggable { public class Tunable implements IThing {
@Id @Id
@NonNull @NonNull

View File

@ -8,9 +8,9 @@ import de.ph87.home.property.*;
import de.ph87.home.search.SearchableDto; import de.ph87.home.search.SearchableDto;
import de.ph87.home.tag.Tag; import de.ph87.home.tag.Tag;
import de.ph87.home.tag.TagReader; import de.ph87.home.tag.TagReader;
import de.ph87.home.tag.TaggableDto; import de.ph87.home.thing.ThingDto;
import de.ph87.home.tag.taggable.ITaggableService; import de.ph87.home.thing.IThingService;
import de.ph87.home.tag.taggable.TaggableFilter; import de.ph87.home.thing.ThingFilter;
import jakarta.annotation.Nullable; import jakarta.annotation.Nullable;
import lombok.NonNull; import lombok.NonNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -28,7 +28,7 @@ import static de.ph87.home.common.crud.SearchHelper.search;
@Service @Service
@Transactional @Transactional
@RequiredArgsConstructor @RequiredArgsConstructor
public class TunableService implements ITaggableService<TunableDto> { public class TunableService implements IThingService<TunableDto> {
private final PropertyService propertyService; private final PropertyService propertyService;
@ -132,12 +132,12 @@ public class TunableService implements ITaggableService<TunableDto> {
} }
@Override @Override
public List<TaggableDto<TunableDto>> findTaggables(final @NonNull TaggableFilter filter) { public List<ThingDto<TunableDto>> filter(final @NonNull ThingFilter filter) {
return tunableRepository.findAll().stream() return tunableRepository.findAll().stream()
.filter(tunable -> tunable.tagListAnyMatch(filter.getTag())) .filter(tunable -> tunable.tagListAnyMatch(filter.getTag()))
.filter(device -> search(filter.getSearch(), device.getSearchableValues())) .filter(device -> search(filter.getSearch(), device.getSearchableValues()))
.map(this::toDto) .map(this::toDto)
.map(TaggableDto::new) .map(ThingDto::new)
.toList(); .toList();
} }