Skip to content

Commit

Permalink
Improved UI grid editor (grid size according to remote capabilities a…
Browse files Browse the repository at this point in the history
…nd grid constraints, UI page renaming)
  • Loading branch information
albaintor committed Sep 25, 2024
1 parent dea5a94 commit b65aaba
Show file tree
Hide file tree
Showing 12 changed files with 191 additions and 24 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ucr-tool",
"version": "1.4.2",
"version": "1.4.3",
"scripts": {
"ng": "ng",
"start": "ng serve",
Expand Down
18 changes: 18 additions & 0 deletions server/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,24 @@ app.get('/api/remote/:address/cfg/entity/commands', async (req, res, next) => {
}
})

app.get('/api/remote/:address/cfg/device/screen_layout', async (req, res, next) => {
const address = req.params.address;
const configFile = getConfigFile();
const remoteEntry = configFile?.remotes?.find(remote => remote.address === address);
if (!remoteEntry)
{
res.status(404).json(address);
return;
}
const remote = new Remote(remoteEntry.address, remoteEntry.port, remoteEntry.user, remoteEntry.token, remoteEntry.api_key);
try {
res.status(200).json(await remote.getConfigScreenLayout());
} catch (error)
{
errorHandler(error, req, res, next);
}
})


app.get('/api/remote/:address/macros', async (req, res, next) => {
const address = req.params.address;
Expand Down
2 changes: 1 addition & 1 deletion server/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "server",
"type": "module",
"version": "1.4.2",
"version": "1.4.3",
"main": "app.js",
"scripts": {
"start": "node app.js"
Expand Down
15 changes: 15 additions & 0 deletions server/remote.js
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,21 @@ export class Remote
return JSON.parse(res.body);
}

async getConfigScreenLayout()
{
const limit = 100;
const options = {
...this.getOptions(),
searchParams: {
limit,
page: 1
}
}
const url = this.getURL() + '/api/cfg/device/screen_layout';
let res = await got.get(url, options);
return JSON.parse(res.body);
}

async getMacros()
{
const options = this.getOptions();
Expand Down
2 changes: 1 addition & 1 deletion src/app/activity-editor/activity-editor.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ export class ActivityEditorComponent implements OnInit, AfterViewInit {
this.server.setEntities(this.entities);
this.server.setActivities(this.activities);
this.remoteOperations = this.buildData();
this.cdr.detectChanges();
// this.cdr.detectChanges();
}
this.server.getRemoteModels().subscribe(remoteModels => {
this.remoteModels = remoteModels;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
ChangeDetectorRef,
Component,
EventEmitter,
Input,
Input, OnInit,
Output,
ViewEncapsulation
} from '@angular/core';
Expand All @@ -15,9 +15,16 @@ import {NgIf} from "@angular/common";
import {OrderListModule} from "primeng/orderlist";
import {MessageService, PrimeTemplate} from "primeng/api";
import {TooltipModule} from "primeng/tooltip";
import {Activity, Remote, UIPage} from "../../interfaces";
import {Activity, Remote, ScreenLayout, UIPage} from "../../interfaces";
import {ServerService} from "../../server.service";

export enum Operation {
ReorderPages,
AddPage,
DeletePage,
UpdatePage
}

@Component({
selector: 'app-activity-page-list',
standalone: true,
Expand All @@ -36,33 +43,57 @@ import {ServerService} from "../../server.service";
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None
})
export class ActivityPageListComponent {
export class ActivityPageListComponent implements OnInit {
remote: Remote | undefined;
private screenLayout: ScreenLayout | undefined;
@Input("remote") set _remote(value: Remote | undefined) {
this.remote = value;
if (value) {
this.server.getConfigScreenLayout(value).subscribe(screenLayout => {
this.screenLayout = screenLayout;
this.cdr.detectChanges();
})
}
}
@Input() activity: Activity | undefined;
@Input() editable = true;
@Output() onReorder = new EventEmitter<{activity:Activity, page:UIPage}>();
@Output() onReorder = new EventEmitter<{activity:Activity, page:UIPage, operation: Operation}>();
@Output() onSelectPage = new EventEmitter<{activity:Activity, page:UIPage}>();

protected readonly Helper = Helper;
protected readonly Helper = Helper;

constructor(private server:ServerService, private cdr:ChangeDetectorRef, private messageService: MessageService) { }

ngOnInit(): void {
if (this.remote)
this.server.getConfigScreenLayout(this.remote).subscribe(screenLayout => {
this.screenLayout = screenLayout;
this.cdr.detectChanges();
})
}

addPage($event: MouseEvent) {
if (!this.activity) return;
if (!this.activity.options) this.activity.options = {};
if (!this.activity.options.user_interface) this.activity.options.user_interface = { pages: []};
const newPage: UIPage = {name: "New page", items: [], grid: {width: 4, height: 6}};
if (this.screenLayout)
{
newPage.grid.width = this.screenLayout.grid.default.width;
newPage.grid.height = this.screenLayout.grid.default.height;
}
this.activity.options.user_interface.pages?.push(newPage);
const activity = this.activity;
this.activity = undefined;
this.cdr.detectChanges();
this.activity = activity;
this.cdr.detectChanges();
this.onReorder.emit({activity: this.activity!, page: newPage});
this.onReorder.emit({activity: this.activity!, page: newPage, operation: Operation.AddPage});
}

updatePages($event: UIPage) {
console.log("Reorder pages", $event);
this.onReorder.emit({activity: this.activity!, page: $event});
this.onReorder.emit({activity: this.activity!, page: $event, operation: Operation.UpdatePage});
}

selectPage(page: UIPage) {
Expand All @@ -71,6 +102,6 @@ export class ActivityPageListComponent {

deletePage(page: UIPage) {
this.activity?.options?.user_interface?.pages?.splice(this.activity?.options?.user_interface?.pages.indexOf(page), 1);
this.onReorder.emit({activity: this.activity!, page: page});
this.onReorder.emit({activity: this.activity!, page: page, operation: Operation.DeletePage});
}
}
5 changes: 5 additions & 0 deletions src/app/activity-viewer/activity-viewer.component.css
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,8 @@
svg * {
transition: all 2s;
}

.grid-size input
{
width: 35px !important;
}
31 changes: 29 additions & 2 deletions src/app/activity-viewer/activity-viewer.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,34 @@ <h3>Page "{{currentPage?.name}}"</h3>
<ng-container *ngIf="currentPage">
<br>
<div class="flex-grow-1 flex-column">
<p-paginator (onPageChange)="onPageChange($event)" [first]="firstPage" [rows]="1" [totalRecords]="activity?.options?.user_interface?.pages?.length"></p-paginator>
<div class="flex align-items-center justify-content-center">
<div class="flex-none" *ngIf="editMode">
<div class="flex-column">
<div class="flex align-items-center justify-content-center">
<b>Page name</b>
</div>
<input type="text" pInputText [(ngModel)]="currentPage.name" placeholder="Page name" style="min-width: 150px"/>
</div>
</div>
<div class="flex-grow-1">
<p-paginator (onPageChange)="onPageChange($event)" [first]="firstPage" [rows]="1" [totalRecords]="activity?.options?.user_interface?.pages?.length"></p-paginator>
</div>
<div class="flex-none" *ngIf="editMode">
<div class="flex-column">
<div class="flex align-items-center justify-content-center">
Grid size
</div>
<div class="flex align-items-center">
<p-inputNumber [(ngModel)]="currentPage.grid.width" [showButtons]="true" buttonLayout="horizontal" spinnerMode="horizontal" [step]="1" pTooltip="Grid width"
decrementButtonClass="p-button-danger" incrementButtonClass="p-button-success" incrementButtonIcon="pi pi-plus" (ngModelChange)="updateButtonsGrid()"
decrementButtonIcon="pi pi-minus" [min]="gridSizeMin.width" [max]="screenLayout?.grid!.max.width" styleClass="grid-size"></p-inputNumber>
<p-inputNumber [(ngModel)]="currentPage.grid.height" [showButtons]="true" buttonLayout="horizontal" spinnerMode="horizontal" [step]="1" pTooltip="Grid height"
decrementButtonClass="p-button-danger" incrementButtonClass="p-button-success" incrementButtonIcon="pi pi-plus" (ngModelChange)="updateButtonsGrid()"
decrementButtonIcon="pi pi-minus" [min]="gridSizeMin.height" [max]="screenLayout?.grid!.max.height" styleClass="grid-size"></p-inputNumber>
</div>
</div>
</div>
</div>
<div class="grid-container" *ngIf="toggleGrid"
[style]="{'grid-template-columns': 'auto '.repeat(currentPage.grid.width), 'width': gridPixelWidth+'px', 'height': gridPixelHeight+'px'}">
<grid-button [editable]="editMode" *ngFor="let item of gridCommands; let index=index" [source]="gridItemSource" [item]="item" [grid]="currentPage.grid" [style]="getGridItemSize(item)"
Expand Down Expand Up @@ -216,7 +243,7 @@ <h3>Page "{{currentPage?.name}}"</h3>
</div>
</ng-container>
<ng-container *ngIf="editMode">
<app-activity-page-list [activity]="activity" [editable]="editMode" (onReorder)="onReorderPages($event)" (onSelectPage)="selectPage($event)"/>
<app-activity-page-list [remote]="remote" [activity]="activity" [editable]="editMode" (onReorder)="onReorderPages($event)" (onSelectPage)="selectPage($event)"/>
</ng-container>
</div>
<app-button-editor [activity]="activity" [remote]="remote" [button]="selectedButton" (buttonChanged)="buttonChanged($event)"></app-button-editor>
Expand Down
45 changes: 39 additions & 6 deletions src/app/activity-viewer/activity-viewer.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
Command,
Remote,
Entity,
EntityCommand, RemoteVersion, RemoteModels, RemoteModel, RemoteData
EntityCommand, RemoteVersion, RemoteModels, RemoteModel, RemoteData, ScreenLayout
} from "../interfaces";
import {DialogModule} from "primeng/dialog";
import {ToastModule} from "primeng/toast";
Expand All @@ -41,8 +41,10 @@ import {ImageMapComponent, MapElement} from "../image-map/image-map.component";
import {DividerModule} from "primeng/divider";
import {ToolbarModule} from "primeng/toolbar";
import {DockModule} from "primeng/dock";
import {ActivityPageListComponent} from "./activity-page-list/activity-page-list.component";
import {ActivityPageListComponent, Operation} from "./activity-page-list/activity-page-list.component";
import {TagModule} from "primeng/tag";
import {InputNumber} from "primeng/inputnumber";
import {InputTextModule} from "primeng/inputtext";

enum DataFormat {
None,
Expand Down Expand Up @@ -82,7 +84,8 @@ export class AsPipe implements PipeTransform {
ToolbarModule,
DockModule,
ActivityPageListComponent,
TagModule
TagModule,
InputTextModule
],
templateUrl: './activity-viewer.component.html',
styleUrl: './activity-viewer.component.css',
Expand All @@ -94,6 +97,8 @@ export class ActivityViewerComponent implements AfterViewInit {
currentPage: UIPage | undefined;
configEntityCommands: EntityCommand[] | undefined;
mappedButtons: string[] | undefined;
gridSizeMin: { width: number; height: number } = {width: 1, height: 1};
screenLayout: ScreenLayout | undefined;
@Input('activity') set _activity(value: Activity | undefined) {
this.activity = value;
if (value) {
Expand All @@ -106,11 +111,17 @@ export class ActivityViewerComponent implements AfterViewInit {
remote: Remote | undefined;
@Input("remote") set _remote(value: Remote | undefined) {
this.remote = value;
if (value)
if (value) {
this.server.getRemoteVersion(value).subscribe(version => {
this.version = version;
this.cdr.detectChanges();
});
this.server.getConfigScreenLayout(value).subscribe(screenLayout => {
this.screenLayout = screenLayout;
console.debug("Screen layout", this.screenLayout);
this.cdr.detectChanges();
})
}
}
@Input() editMode = true;
@Output() onChange: EventEmitter<void> = new EventEmitter();
Expand Down Expand Up @@ -164,7 +175,12 @@ export class ActivityViewerComponent implements AfterViewInit {
this.server.getConfigEntityCommands(this.remote).subscribe(entityCommands => {
this.configEntityCommands = entityCommands;
this.cdr.detectChanges();
})
});
this.server.getConfigScreenLayout(this.remote).subscribe(screenLayout => {
this.screenLayout = screenLayout;
console.debug("Screen layout", this.screenLayout);
this.cdr.detectChanges();
});
}
this.server.getRemoteModels().subscribe(remoteModels => {
this.remoteModels = remoteModels;
Expand Down Expand Up @@ -205,6 +221,7 @@ export class ActivityViewerComponent implements AfterViewInit {
this.firstPage = 0;
console.log("View activity", this.activity);
this.updateButtonsGrid();
this.updateCurrentPage();
}

updateButtons()
Expand All @@ -221,6 +238,7 @@ export class ActivityViewerComponent implements AfterViewInit {
{
this.gridCommands = this.getGridItems();
this.updateButtons();
this.updateCurrentPage();
this.cdr.detectChanges();
}

Expand All @@ -237,6 +255,12 @@ export class ActivityViewerComponent implements AfterViewInit {
return "";
}

updateCurrentPage()
{
this.gridSizeMin = Helper.getGridMinSize(this.gridCommands);
console.debug("Minimal grid size", this.gridSizeMin);
}

getGridItems(): ActivityPageCommand[]
{

Expand Down Expand Up @@ -285,16 +309,25 @@ export class ActivityViewerComponent implements AfterViewInit {
this.firstPage = $event.page as number;
this.currentPage = this.activity?.options?.user_interface?.pages?.[$event.page!];
this.updateButtonsGrid();
this.updateCurrentPage();
console.log("Page changed", this.gridCommands);
this.cdr.detectChanges();
}

onReorderPages($event: any)
onReorderPages($event: {activity: Activity, page: UIPage, operation: Operation})
{
this.currentPage = this.activity?.options?.user_interface?.pages?.[0];
this.firstPage = 0;
if ($event.operation == Operation.AddPage)
{
this.currentPage = this.activity?.options?.user_interface?.pages?.[this.activity?.options?.user_interface?.pages?.length-1];
if (this.activity?.options?.user_interface?.pages?.length)
this.firstPage = this.activity.options.user_interface.pages.length-1;
}
this.updateButtonsGrid();
this.updateCurrentPage();
this.onChange.emit();

this.cdr.detectChanges();
}

Expand Down
21 changes: 17 additions & 4 deletions src/app/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,21 +354,34 @@ export class Helper
return true;
}

static getGridMinSize(grid: (ActivityPageCommand | null)[]): {width: number, height: number}
{
const gridSize = {width: 1, height: 1};
grid.forEach(item => {
if (!item || Helper.isEmptyItem(item)) return;
if (item.location.x + item.size.width > gridSize.width)
gridSize.width = item.location.x + item.size.width;
if (item.location.y + item.size.height > gridSize.height)
gridSize.height = item.location.y + item.size.height;
});
return gridSize;
}

static getItemPosition(grid: (ActivityPageCommand | null)[], index: number, gridWidth: number, gridHeight: number): {x: number, y: number, width: number, height: number} | null
{
if (gridWidth <= 0 || gridHeight <= 0 || grid.length == 0) return null;
const matrix: boolean[][] = new Array(gridHeight)
.fill(false)
.map(() =>
new Array(gridWidth).fill(false)
);
let x= 0, y = 0;
for (let i=0; i < grid.length; )
{
let width = 1, height = 1;
if (grid[i] && grid[i]?.size)
if (grid?.[i]?.size)
{
width = grid[i]!.size.width!;
height = grid[i]!.size.height!;
width = grid[i]?.size.width ? grid[i]!.size.width : 1;
height = grid[i]?.size.height ? grid[i]!.size.height : 1;
}
for (let row =0; row < matrix.length; row++)
{
Expand Down
Loading

0 comments on commit b65aaba

Please sign in to comment.