Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenthoms committed Sep 11, 2024
1 parent de6510b commit 37b23e1
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 111 deletions.
8 changes: 6 additions & 2 deletions frontend/src/lib/components/SortableList/sortableList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,10 @@ export function SortableList(props: SortableListProps): React.ReactNode {
}

function makeChildren(): React.ReactNode[] {
if (props.children.length === 0 && props.contentWhenEmpty) {
return [props.contentWhenEmpty];
}

const children: React.ReactNode[] = [];
for (const child of props.children) {
if (typeof child.type === "string") {
Expand All @@ -524,7 +528,7 @@ export function SortableList(props: SortableListProps): React.ReactNode {
}

return (
<div className="w-full h-full flex flex-col relative" ref={mainDivRef}>
<div className="w-full h-full flex flex-col relative min-h-0 max-h-full" ref={mainDivRef}>
<SortableListContext.Provider
value={{
draggedElementId: draggedItemId,
Expand All @@ -546,7 +550,7 @@ export function SortableList(props: SortableListProps): React.ReactNode {
ref={scrollDivRef}
onScroll={handleScroll}
>
<div className="flex flex-col relative" ref={listDivRef}>
<div className="flex flex-col relative min-h-0" ref={listDivRef}>
{makeChildren()}
<div className="h-2 min-h-2">
<div className="h-2" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { SortableListGroup } from "@lib/components/SortableList";
import { Delete, Visibility, VisibilityOff } from "@mui/icons-material";
import { Panorama } from "@mui/icons-material";

import { EditNameComponent } from "./editNameComponent";
import { RemoveButtonComponent } from "./removeButtonComponent";
import { makeComponent } from "./utils";
import { VisibilityToggleComponent } from "./visibilityToggleComponent";

import { usePublishSubscribeTopicValue } from "../PublishSubscribeHandler";
import { GroupBaseTopic } from "../delegates/GroupDelegate";
import { ItemDelegateTopic } from "../delegates/ItemDelegate";
import { Group, Item } from "../interfaces";

export type GroupComponentProps = {
Expand All @@ -19,60 +21,21 @@ export function GroupComponent(props: GroupComponentProps): React.ReactNode {
<SortableListGroup
key={props.group.getItemDelegate().getId()}
id={props.group.getItemDelegate().getId()}
title={props.group.getItemDelegate().getName()}
startAdornment={<StartActions group={props.group} />}
endAdornment={<Actions group={props.group} />}
title={
<div className="flex gap-2 items-center">
<Panorama fontSize="inherit" />
<EditNameComponent item={props.group} />
</div>
}
startAdornment={<VisibilityToggleComponent item={props.group} />}
endAdornment={<RemoveButtonComponent item={props.group} />}
contentWhenEmpty={
<div className="flex h-16 justify-center text-sm items-center gap-1">
Drag a layer inside to add it to this group.
</div>
}
>
{children.map((child: Item) => makeComponent(child))}
</SortableListGroup>
);
}

type StartActionsProps = {
group: Group;
};

function StartActions(props: StartActionsProps): React.ReactNode {
const visible = usePublishSubscribeTopicValue(props.group.getItemDelegate(), ItemDelegateTopic.VISIBILITY);

function handleToggleVisibility() {
props.group.getItemDelegate().setIsVisible(!visible);
}

return (
<div className="flex items-center">
<button onClick={handleToggleVisibility}>
{props.group.getItemDelegate().isVisible() ? (
<Visibility fontSize="inherit" />
) : (
<VisibilityOff fontSize="inherit" />
)}
</button>
</div>
);
}

type ActionProps = {
group: Group;
};

function Actions(props: ActionProps): React.ReactNode {
function handleRemove() {
const parentGroup = props.group.getItemDelegate().getParentGroup();
if (parentGroup) {
parentGroup.removeChild(props.group);
}
}

return (
<>
<div
className="hover:cursor-pointer rounded hover:text-red-800"
onClick={handleRemove}
title="Remove layer group"
>
<Delete fontSize="inherit" />
</div>
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import React from "react";
import { StatusMessage } from "@framework/ModuleInstanceStatusController";
import { CircularProgress } from "@lib/components/CircularProgress";
import { SortableListItem } from "@lib/components/SortableList";
import { Check, Delete, Error, Visibility, VisibilityOff } from "@mui/icons-material";
import { Check, Error } from "@mui/icons-material";

import { SettingComponent } from "./SettingComponent";
import { EditNameComponent } from "./editNameComponent";
import { RemoveButtonComponent } from "./removeButtonComponent";
import { VisibilityToggleComponent } from "./visibilityToggleComponent";

import { usePublishSubscribeTopicValue } from "../PublishSubscribeHandler";
import { ItemDelegateTopic } from "../delegates/ItemDelegate";
import { LayerDelegateTopic } from "../delegates/LayerDelegate";
import { Layer, LayerStatus, Setting } from "../interfaces";

Expand Down Expand Up @@ -45,8 +47,8 @@ export function LayerComponent(props: LayerComponentProps): React.ReactNode {
<SortableListItem
key={props.layer.getItemDelegate().getId()}
id={props.layer.getItemDelegate().getId()}
title={props.layer.getItemDelegate().getName()}
startAdornment={<StartActions layer={props.layer} />}
title={<EditNameComponent item={props.layer} />}
startAdornment={<VisibilityToggleComponent item={props.layer} />}
endAdornment={<Actions layer={props.layer} />}
>
<div className="table">
Expand All @@ -63,10 +65,6 @@ type ActionProps = {
function Actions(props: ActionProps): React.ReactNode {
const status = usePublishSubscribeTopicValue(props.layer.getLayerDelegate(), LayerDelegateTopic.STATUS);

function handleRemove() {
props.layer.getItemDelegate().getParentGroup()?.removeChild(props.layer);
}

function makeStatus(): React.ReactNode {
if (status === LayerStatus.LOADING) {
return (
Expand Down Expand Up @@ -105,35 +103,7 @@ function Actions(props: ActionProps): React.ReactNode {
return (
<>
{makeStatus()}
<div
className="hover:cursor-pointer rounded hover:text-red-800"
onClick={handleRemove}
title="Remove layer group"
>
<Delete fontSize="inherit" />
</div>
<RemoveButtonComponent item={props.layer} />
</>
);
}

type StartActionsProps = {
layer: Layer<any, any>;
};

function StartActions(props: StartActionsProps): React.ReactNode {
const isVisible = usePublishSubscribeTopicValue(props.layer.getItemDelegate(), ItemDelegateTopic.VISIBILITY);

function handleToggleLayerVisibility() {
props.layer.getItemDelegate().setIsVisible(!isVisible);
}

return (
<div
className="hover:cursor-pointer rounded hover:text-blue-800"
onClick={handleToggleLayerVisibility}
title="Toggle visibility"
>
{isVisible ? <Visibility fontSize="inherit" /> : <VisibilityOff fontSize="inherit" />}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from "react";

import { usePublishSubscribeTopicValue } from "../PublishSubscribeHandler";
import { ItemDelegateTopic } from "../delegates/ItemDelegate";
import { Item } from "../interfaces";

type EditItemNameComponentProps = {
item: Item;
};

export function EditNameComponent(props: EditItemNameComponentProps): React.ReactNode {
const itemName = usePublishSubscribeTopicValue(props.item.getItemDelegate(), ItemDelegateTopic.NAME);

const [editingName, setEditingName] = React.useState<boolean>(false);
const [currentName, setCurrentName] = React.useState<string>(itemName);

function handleNameDoubleClick() {
setEditingName(true);
}

function handleNameChange(e: React.ChangeEvent<HTMLInputElement>) {
setCurrentName(e.target.value);
}

function handleBlur() {
setEditingName(false);
props.item.getItemDelegate().setName(currentName);
}

function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
if (e.key === "Enter") {
setEditingName(false);
props.item.getItemDelegate().setName(currentName);
}
}

return (
<div
className="flex-grow font-bold flex items-center pt-1"
onDoubleClick={handleNameDoubleClick}
title="Double-click to edit name"
>
{editingName ? (
<input
type="text"
className="p-0.5 w-full"
value={currentName}
onChange={handleNameChange}
onBlur={handleBlur}
onKeyDown={handleKeyDown}
autoFocus
/>
) : (
itemName
)}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Delete } from "@mui/icons-material";

import { Item } from "../interfaces";

export type RemoveButtonComponentProps = {
item: Item;
};

export function RemoveButtonComponent(props: RemoveButtonComponentProps): React.ReactNode {
function handleRemove() {
const parentGroup = props.item.getItemDelegate().getParentGroup();
if (parentGroup) {
parentGroup.removeChild(props.item);
}
}

return (
<>
<div
className="hover:cursor-pointer rounded text-red-800 hover:text-red-600"
onClick={handleRemove}
title="Remove item"
>
<Delete fontSize="inherit" />
</div>
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Visibility, VisibilityOff } from "@mui/icons-material";

import { usePublishSubscribeTopicValue } from "../PublishSubscribeHandler";
import { ItemDelegateTopic } from "../delegates/ItemDelegate";
import { Item } from "../interfaces";

export type VisibilityToggleComponentProps = {
item: Item;
};

export function VisibilityToggleComponent(props: VisibilityToggleComponentProps): React.ReactNode {
const isVisible = usePublishSubscribeTopicValue(props.item.getItemDelegate(), ItemDelegateTopic.VISIBILITY);

function handleToggleLayerVisibility() {
props.item.getItemDelegate().setIsVisible(!isVisible);
}

return (
<div
className="hover:cursor-pointer rounded text-blue-800 hover:text-blue-600"
onClick={handleToggleLayerVisibility}
title="Toggle visibility"
>
{isVisible ? <Visibility fontSize="inherit" /> : <VisibilityOff fontSize="inherit" />}
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { v4 } from "uuid";

import { GroupDelegate } from "./GroupDelegate";

import { LayerManager } from "../LayerManager";
import { LayerManager, LayerManagerTopic } from "../LayerManager";
import { PublishSubscribe, PublishSubscribeHandler } from "../PublishSubscribeHandler";

export enum ItemDelegateTopic {
Expand Down Expand Up @@ -41,6 +41,9 @@ export class ItemDelegate implements PublishSubscribe<ItemDelegateTopic, ItemDel
setName(name: string): void {
this._name = name;
this._publishSubscribeHandler.notifySubscribers(ItemDelegateTopic.NAME);
if (this._layerManager) {
this._layerManager.publishTopic(LayerManagerTopic.LAYER_DATA_REVISION);
}
}

getParentGroup(): GroupDelegate | null {
Expand All @@ -67,6 +70,9 @@ export class ItemDelegate implements PublishSubscribe<ItemDelegateTopic, ItemDel
setIsVisible(visible: boolean): void {
this._visible = visible;
this._publishSubscribeHandler.notifySubscribers(ItemDelegateTopic.VISIBILITY);
if (this._layerManager) {
this._layerManager.publishTopic(LayerManagerTopic.LAYER_DATA_REVISION);
}
}

makeSnapshotGetter<T extends ItemDelegateTopic>(topic: T): () => ItemDelegatePayloads[T] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ export class LayerDelegate<TSettings extends Settings, TData>

private setStatus(status: LayerStatus): void {
this._status = status;
this._layerManager?.publishTopic(LayerManagerTopic.LAYER_DATA_REVISION);
this._publishSubscribeHandler.notifySubscribers(LayerDelegateTopic.STATUS);
}

Expand Down Expand Up @@ -234,6 +235,5 @@ export class LayerDelegate<TSettings extends Settings, TData>
}
this.setStatus(LayerStatus.ERROR);
}
this._layerManager?.publishTopic(LayerManagerTopic.LAYER_DATA_REVISION);
}
}
Loading

0 comments on commit 37b23e1

Please sign in to comment.