Skip to content
Snippets Groups Projects
nodedetails.tsx 7.19 KiB
import React from "react";
import { Node } from "../../common/graph/node";
import { NodeType } from "../../common/graph/nodetype";
import "./nodedetails.css";
import { NodeDataChangeRequest } from "../editor";

type NodeDetailsProps = {
    selectedNodes: Node[];
    idToObjectType: Map<number, NodeType>;
    onNodeDataChange: { (requests: NodeDataChangeRequest[]): void };
};

function NodeDetails({
    selectedNodes,
    idToObjectType,
    onNodeDataChange,
}: NodeDetailsProps) {
    if (selectedNodes.length == 0) {
        return <div id="nodedetails">No node selected.</div>;
    }

    const getCollectiveValue = function <ValueType>(
        getter: (n: Node) => ValueType,
        defaultValue: ValueType
    ) {
        const referenceValue = getter(selectedNodes[0]);
        const differentValueFound = selectedNodes.some(
            (n: Node) => getter(n) !== referenceValue
        );
        return differentValueFound ? defaultValue : referenceValue;
    };

    const referenceData: NodeDataChangeRequest = {
        id: -1,
        name: getCollectiveValue((n) => n.name, undefined),
        description: getCollectiveValue((n) => n.description, undefined),
        video: getCollectiveValue((n) => n.video, undefined),
        icon: getCollectiveValue((n) => n.icon, undefined),
        banner: getCollectiveValue((n) => n.banner, undefined),
        references: getCollectiveValue((n) => n.references, undefined),
        type: getCollectiveValue((n) => n.type, undefined),
    };

    const handleDataChange = function <ValueType>(
        key: keyof NodeDataChangeRequest,
        value: ValueType
    ) {
        Object.assign(referenceData, { [key]: value });
        onNodeDataChange(
            selectedNodes.map((node) => {
                return { ...referenceData, id: node.id, name: node.name };
            })
        );
    };

    return (
        <div id="nodedetails">
            {selectedNodes.length === 1 ? (
                <div>
                    <label htmlFor="node-name" hidden>
                        Name
                    </label>
                    <input
                        type="text"
                        id="node-name"
                        name="node-name"
                        placeholder="Enter name"
                        className="bottom-space"
                        value={referenceData.name}
                        onChange={(event) =>
                            handleDataChange("name", event.target.value)
                        }
                    ></input>
                </div>
            ) : (
                <h3>{selectedNodes.length} nodes selected</h3>
            )}

            {selectedNodes.length === 1 ? (
                <div>
                    <label htmlFor="node-description">Description</label>
                    <br />
                    <textarea
                        id="node-description"
                        name="node-description"
                        className="bottom-space"
                        value={referenceData.description}
                        onChange={(event) =>
                            handleDataChange("description", event.target.value)
                        }
                    ></textarea>
                </div>
            ) : (
                ""
            )}
            <div>
                <label htmlFor="node-image">Icon Image</label>
                <br />
                {referenceData.icon && (
                    <div>
                        <img
                            id="node-image-preview"
                            className="preview-image"
                            src={referenceData.icon}
                        />
                        <br />
                    </div>
                )}
                <input
                    type="text"
                    id="node-image"
                    name="node-image"
                    placeholder="Image URL"
                    className="bottom-space"
                    value={referenceData.icon ?? ""}
                    onChange={(event) =>
                        handleDataChange("icon", event.target.value)
                    }
                />
            </div>
            <div>
                <label htmlFor="node-detail-image">Banner Image</label>
                <br />
                {referenceData.banner && (
                    <div>
                        <img
                            id="node-image-preview"
                            className="preview-image"
                            src={referenceData.banner}
                        />
                        <br />
                    </div>
                )}
                <input
                    type="text"
                    id="node-detail-image"
                    name="node-detail-image"
                    placeholder="Image URL"
                    className="bottom-space"
                    value={referenceData.banner ?? ""}
                    onChange={(event) =>
                        handleDataChange("banner", event.target.value)
                    }
                />
            </div>
            <div>
                <label htmlFor="node-type">Type</label>
                <br />
                <select
                    id="node-type"
                    name="node-type"
                    className="bottom-space"
                    value={referenceData.type ? referenceData.type.id : ""}
                    onChange={(event) =>
                        handleDataChange(
                            "type",
                            idToObjectType.get(Number(event.target.value))
                        )
                    }
                >
                    <option className="empty-select-option" disabled></option>
                    {[...idToObjectType.values()].map((type) => (
                        <option key={type.id} value={type.id}>
                            {type.name}
                        </option>
                    ))}
                </select>
            </div>
            <div>
                <label htmlFor="node-video">Video</label>
                <br />
                <input
                    type="text"
                    placeholder="Video URL"
                    id="node-video"
                    name="node-video"
                    value={referenceData.video ?? ""}
                    onChange={(event) =>
                        handleDataChange("video", event.target.value)
                    }
                ></input>
            </div>
            {selectedNodes.length === 1 ? (
                <div>
                    <label htmlFor="node-references">References</label>{" "}
                    <small>One URL per line</small>
                    <br />
                    <textarea
                        id="node-references"
                        name="node-references"
                        className="bottom-space"
                        value={referenceData.references}
                        onChange={(event) =>
                            handleDataChange("references", event.target.value)
                        }
                    ></textarea>
                </div>
            ) : (
                ""
            )}
        </div>
    );
}

export default NodeDetails;