diff --git a/src/editor/components/spacemanager.css b/src/editor/components/spacemanager.css index 250fd4bccdf409196e16b50b3369a25061864fb5..dafd8c94e21fc996785ce973a5682713da7aa0e1 100644 --- a/src/editor/components/spacemanager.css +++ b/src/editor/components/spacemanager.css @@ -1,4 +1,4 @@ -div#ks-editor #space-manager #pop-up { +div#ks-editor #space-manager { border: 1px lightgrey solid; border-radius: 5px; background-color: white; @@ -7,6 +7,9 @@ div#ks-editor #space-manager #pop-up { max-width: 20rem; margin: 0.5rem 0rem; padding: 0.7rem; + + position: fixed; + z-index: 1000; } div#ks-editor #space-manager .warning { diff --git a/src/editor/components/spacemanager.tsx b/src/editor/components/spacemanager.tsx index dbfec190c7879f85b757fbb56d62c5e421a4025e..937f89ec91c5724780e9b3a6660967787255efbf 100644 --- a/src/editor/components/spacemanager.tsx +++ b/src/editor/components/spacemanager.tsx @@ -1,108 +1,91 @@ -import React from "react"; -import { ReactNode } from "react"; +import React, { useState } from "react"; import "./spacemanager.css"; -type propTypes = unknown; -type stateTypes = { - hidden: boolean; - deleteConfirmationHidden: boolean; - newName: string; -}; +interface SpaceManagerProps { + spaceId: string; + onDeleteSpace: (spaceId: string) => void; + onRenameSpace: (newId: string) => void; + onDuplicateSpace: (newId: string) => void; + onCreateSpace: (spaceId: string) => void; +} -export class SpaceManager extends React.Component<propTypes, stateTypes> { - constructor(props: propTypes) { - super(props); - this.deleteSpace = this.deleteSpace.bind(this); +function SpaceManager({ + spaceId, + onDeleteSpace, + onRenameSpace, + onDuplicateSpace, + onCreateSpace, +}: SpaceManagerProps) { + const [deleteConfirmationVisible, setDeleteConfirmationVisible] = + useState(false); + const [newSpaceName, setNewSpaceName] = useState("New graph"); - this.state = { - hidden: true, - deleteConfirmationHidden: true, - newName: "New space", - }; - } + const handleDeleteSpace = () => { + setDeleteConfirmationVisible(false); + onDeleteSpace(spaceId); + }; - private deleteSpace() { - this.setState({ - deleteConfirmationHidden: true, - }); - } + return ( + <div id="space-manager"> + <label htmlFor="space-name">New graph name</label> + <br /> + <input + id="space-name" + type={"text"} + value={newSpaceName} + onChange={(e) => setNewSpaceName(e.target.value)} + /> - render(): ReactNode { - return ( - <div id="space-manager"> - <button - className="warning" - onClick={() => - this.setState({ - hidden: !this.state.hidden, - deleteConfirmationHidden: true, - }) - } - > - Manage Space - </button> - {this.state.hidden ? ( - "" - ) : ( - <div id="pop-up"> - <input - className="space-name" - type={"text"} - value={this.state.newName} - onChange={(event) => - this.setState({ newName: event.target.value }) - } - /> - <ul> - <li> - <button> - Rename to {'"' + this.state.newName + '"'} - </button> - </li> - <li> - <button> - Duplicate as{" "} - {'"' + this.state.newName + '"'} - </button> - </li> - <li> - <button> - Create empty space{" "} - {'"' + this.state.newName + '"'} - </button> - </li> - </ul> - <hr /> - <ul> - <li> - <button - onClick={() => - this.setState({ - deleteConfirmationHidden: - !this.state - .deleteConfirmationHidden, - }) - } - > - Delete Space? - </button> - </li> - {this.state.deleteConfirmationHidden ? ( - "" - ) : ( - <li> - <button - className="warning" - onClick={this.deleteSpace} - > - Delete the space and all its data - </button> - </li> - )} - </ul> - </div> + <ul> + <li> + <button + disabled={newSpaceName.length === 0} + onClick={() => onRenameSpace(newSpaceName)} + > + Rename to {'"' + newSpaceName + '"'} + </button> + </li> + <li> + <button + disabled={newSpaceName.length === 0} + onClick={() => onDuplicateSpace(newSpaceName)} + > + Duplicate as {'"' + newSpaceName + '"'} + </button> + </li> + <li> + <button + disabled={newSpaceName.length === 0} + onClick={() => onCreateSpace(newSpaceName)} + > + Create empty graph {'"' + newSpaceName + '"'} + </button> + </li> + </ul> + <hr /> + <ul> + <li> + <button + onClick={() => + setDeleteConfirmationVisible( + !deleteConfirmationVisible + ) + } + > + Delete graph {'"' + spaceId + '"'}? + </button> + </li> + {deleteConfirmationVisible && ( + <li> + <button className="warning" onClick={handleDeleteSpace}> + Delete the graph {'"' + spaceId + '"'} and all its + data + </button> + </li> )} - </div> - ); - } + </ul> + </div> + ); } + +export default SpaceManager; diff --git a/src/editor/components/spaceselect.tsx b/src/editor/components/spaceselect.tsx index 237852ef8b37cddbbeb9b90c5a2ca4aec94186e7..86503b25a88490fbbeb2fdd3f16aeb2e15761be2 100644 --- a/src/editor/components/spaceselect.tsx +++ b/src/editor/components/spaceselect.tsx @@ -1,14 +1,33 @@ import React, { useState } from "react"; +import SpaceManager from "./spacemanager"; import "./spaceselect.css"; interface SpaceSelectProps { onLoadSpace: (spaceId: string) => boolean; + onDeleteSpace: (spaceId: string) => void; + onRenameSpace: (newId: string) => void; + onDuplicateSpace: (newId: string) => void; + onCreateSpace: (spaceId: string) => void; spaces: string[]; spaceId: string; } -function SpaceSelect({ onLoadSpace, spaces, spaceId }: SpaceSelectProps) { +function SpaceSelect({ + onLoadSpace, + spaces, + spaceId, + onRenameSpace, + onDuplicateSpace, + onCreateSpace, + onDeleteSpace, +}: SpaceSelectProps) { const [selected, setSelected] = useState(spaceId); + const [managerVisible, setMangerVisible] = useState(false); + + const handleDeleteSpace = (spaceId: string) => { + setMangerVisible(false); + onDeleteSpace(spaceId); + }; return ( <div id="spaceselect"> @@ -25,6 +44,20 @@ function SpaceSelect({ onLoadSpace, spaces, spaceId }: SpaceSelectProps) { </option> ))} </select> + + <button onClick={() => setMangerVisible(!managerVisible)}> + {/* Should be called "Space manager", but since a space is currently an unused concept for the user, graph is easier to understand */} + Graph manager + </button> + {managerVisible && ( + <SpaceManager + spaceId={spaceId} + onCreateSpace={onCreateSpace} + onRenameSpace={onRenameSpace} + onDeleteSpace={handleDeleteSpace} + onDuplicateSpace={onDuplicateSpace} + /> + )} </div> ); } diff --git a/src/editor/editor.tsx b/src/editor/editor.tsx index d65164474e0175c38b8213cfa671c7c1117f597a..8879c15aeca262a9b4b2c570cd42a0c815115c87 100644 --- a/src/editor/editor.tsx +++ b/src/editor/editor.tsx @@ -426,16 +426,55 @@ export class Editor extends React.PureComponent<any, stateTypes> { this.setState({ graph: graph }); } + /** + * @param newId Explicit id of space that should be deleted. + */ + private deleteSpace(spaceId: string) { + throw new Error( + 'Function "deleteSpace(spaceId)" has not been implemented.' + ); + } + + /** + * @param newId New id for currently selected space. + */ + private renameSpace(newId: string) { + throw new Error( + 'Function "renameSpace(newId)" has not been implemented.' + ); + } + + /** + * @param newId Id for the newly created space with the data of the currently selected space copied over. + */ + private duplicateSpace(newId: string) { + throw new Error( + 'Function "duplicateSpace(newId)" has not been implemented.' + ); + } + + /** + * @param newSpaceId Id for newly created space with the default empty space data. + */ + private createSpace(newSpaceId: string) { + throw new Error( + 'Function "createSpace(newSpaceId)" has not been implemented.' + ); + } + render(): React.ReactNode { return ( <div id="ks-editor"> <h1>Interface</h1> <SpaceSelect onLoadSpace={this.loadSpace} + onDeleteSpace={this.deleteSpace} + onRenameSpace={this.renameSpace} + onDuplicateSpace={this.duplicateSpace} + onCreateSpace={this.createSpace} spaces={this.state.spaces} spaceId={this.state.spaceId} /> - <SpaceManager /> {this.state.graph && ( <div id="content"> <div id="force-graph-renderer">