diff --git a/cra-client/src/components/GlossaryAuthor/components/nodepages/NodeInput.js b/cra-client/src/components/GlossaryAuthor/components/nodepages/NodeInput.js index 94c31b71..f8b571bb 100644 --- a/cra-client/src/components/GlossaryAuthor/components/nodepages/NodeInput.js +++ b/cra-client/src/components/GlossaryAuthor/components/nodepages/NodeInput.js @@ -5,7 +5,6 @@ import { Accordion, AccordionItem, TextInput } from "carbon-components-react"; import DateTimePicker from "../../../common/DateTimePicker"; import Info16 from "@carbon/icons-react/lib/information/16"; - /** * Component to take user input for node page as part of a wizard. * @@ -37,7 +36,8 @@ export default function NodeInput(props) { if (attributeValue !== undefined) { attributesWithValuesElement.value = attributeValue.value; attributesWithValuesElement.invalid = attributeValue.invalid; - attributesWithValuesElement.invalidText = attributeValue.invalidText; + attributesWithValuesElement.invalidText = + attributeValue.invalidText; } attributesWithValuesElement.id = attributeKey; attributesWithValues.push(attributesWithValuesElement); @@ -147,15 +147,17 @@ export default function NodeInput(props) { > {item.label} - setAttribute(item, e.target.value)} - placeholder={item.label} - > +
+ setAttribute(item, e.target.value)} + placeholder={item.label} + > +
); })} @@ -165,14 +167,14 @@ export default function NodeInput(props) { dateLabel="Effective from date (mm/dd/yyyy)" timeLabel="Effective from time (hh:mm)" onDateTimeChange={onFromDateTimeChange} - value={effectiveFrom} + value={effectiveFrom} onDateTimeMessage={props.onDateTimeFromMessage} /> diff --git a/cra-client/src/components/GlossaryAuthor/components/update/UpdateNodeInline.js b/cra-client/src/components/GlossaryAuthor/components/update/UpdateNodeInline.js index c0e73242..ebd8ceae 100644 --- a/cra-client/src/components/GlossaryAuthor/components/update/UpdateNodeInline.js +++ b/cra-client/src/components/GlossaryAuthor/components/update/UpdateNodeInline.js @@ -1,12 +1,13 @@ /* SPDX-License-Identifier: Apache-2.0 */ /* Copyright Contributors to the ODPi Egeria project. */ import React, { useState, useEffect } from "react"; +import { parse, format } from "date-fns"; import { Accordion, AccordionItem, Button, - DatePicker, - DatePickerInput, + // DatePicker, + // DatePickerInput, DataTable, TableContainer, Table, @@ -16,18 +17,74 @@ import { TableHeader, TableBody, } from "carbon-components-react"; -import Info16 from "@carbon/icons-react/lib/information/16"; +// import Info16 from "@carbon/icons-react/lib/information/16"; +import { + validateNodePropertiesUserInput, + extendUserInput, +} from "../../../common/Validators"; import { issueRestUpdate } from "../RestCaller"; +import NodeInput from "../nodepages/NodeInput"; export default function UpdateNodeInline(props) { - const [updateBody, setUpdateBody] = useState({}); + // const [nodeToUpdate, setNodeToUpdate] = useState({}); const [currentNode, setCurrentNode] = useState(); const [errorMsg, setErrorMsg] = useState(); + const [userInput, setUserInput] = useState(); useEffect(() => { setCurrentNode(props.node); + updateUserInputFromNode(props.node); + }, [props]); + /** + * There is new node content (from an update response or we are initialising with content). The node is the serialised for of a glossary author artifact, used on rest calls. + * The userInput state variable stores data in a format that the user interface needs, including a value and invalid flag + * for each attrribute value. + * This function maps the node content to the userInput. + * @param {*} node + */ + const updateUserInputFromNode = (node) => { + const currentNodeType = props.currentNodeType; + let newUserInput = {}; + if (currentNodeType && currentNodeType.attributes && currentNodeType.attributes.length >0) { + for (let i = 0 ; i< currentNodeType.attributes.length ; i++) { + const attributeName = currentNodeType.attributes[i].key; + newUserInput[attributeName] = {}; + newUserInput[attributeName].value= node[attributeName]; + newUserInput[attributeName].invalid= false; + } + } + + // change the dates from longs to an object with a date and time + if (node.effectiveFromTime) { + let dateTimeObject = {}; + dateTimeObject.date = {}; + dateTimeObject.date.value = new Date(node.effectiveFromTime); + dateTimeObject.date.invalid = false; + dateTimeObject.time = {}; + dateTimeObject.time.value = format( + node.effectiveFromTime, + "HH:mm" + ); + dateTimeObject.time.invalid = false; + newUserInput.effectiveFromTime = dateTimeObject; + } + if (node.effectiveToTime) { + let dateTimeObject = {}; + dateTimeObject.date = {}; + dateTimeObject.date.value = new Date(node.effectiveToTime); + dateTimeObject.date.invalid = false; + dateTimeObject.time = {}; + dateTimeObject.time.value = format( + node.effectiveToTime, + "HH:mm" + ); + dateTimeObject.time.invalid = false; + newUserInput.effectiveToTime = dateTimeObject; + } + setUserInput(newUserInput); + }; console.log("UpdateNodeInline"); const url = getUrl(); @@ -41,7 +98,7 @@ export default function UpdateNodeInline(props) { const handleClickUpdate = (e) => { console.log("handleClickUpdate()"); e.preventDefault(); - let body = updateBody; + let body = currentNode; // TODO consider moving this up to a node controller as per the CRUD pattern. // in the meantime this will be self contained. @@ -49,12 +106,16 @@ export default function UpdateNodeInline(props) { // console.log("issueUpdate " + url); issueRestUpdate(url, body, onSuccessfulUpdate, onErrorUpdate); }; + const handleCreateRelationship = () => { + alert("TODO create relationship!"); + }; const onSuccessfulUpdate = (json) => { console.log("onSuccessfulUpdate"); if (json.result.length === 1) { const node = json.result[0]; node.gen = currentNode.gen; setCurrentNode(node); + updateUserInputFromNode(node); } else { setErrorMsg("Error did not get a node from the server"); setCurrentNode(undefined); @@ -64,16 +125,45 @@ export default function UpdateNodeInline(props) { console.log("Error on Update " + msg); setErrorMsg(msg); setCurrentNode(undefined); + updateUserInputFromNode(undefined); }; - function updateLabelId(labelKey) { - return "text-input-update" + props.currentNodeType.name + "-" + labelKey; - } - const setAttribute = (item, value) => { - console.log("setAttribute " + item.key + ",value=" + value); - let myUpdateBody = updateBody; - myUpdateBody[item.key] = value; - setUpdateBody(myUpdateBody); + const onAttributeChange = (attributeKey, attributeValue) => { + const extendedUserInput = extendUserInput( + userInput, + attributeKey, + attributeValue + ); + + let newUserInput = { + ...extendedUserInput, + }; + + setUserInput(newUserInput); + if (validateNodePropertiesUserInput(extendedUserInput)) { + if ( + attributeKey === "effectiveFromTime" || + attributeKey === "effectiveToTime" + ) { + // the value is an object with date and time properties + // we need to create a single date + if (attributeValue !== undefined) { + let time = attributeValue.time; + let date = attributeValue.date; + if (time === undefined) { + attributeValue = date; + } else { + attributeValue = parse(time, "HH:mm", date); + } + attributeValue = attributeValue.getTime(); + } + } + let myCurrentNode = { + ...currentNode, + [attributeKey]: attributeValue, + }; + setCurrentNode(myCurrentNode); + } }; const updatedTableHeaderData = [ { @@ -102,6 +192,7 @@ export default function UpdateNodeInline(props) { } return rowData; }; + return (
{currentNode !== undefined && ( @@ -114,46 +205,14 @@ export default function UpdateNodeInline(props) { )} {currentNode !== undefined && props.currentNodeType !== undefined && - props.currentNodeType.attributes !== undefined && - props.currentNodeType.attributes.map((item) => { - return ( -
- - setAttribute(item, e.target.value)} - placeholder={item.label} - > -
- ); - })} - {/* {currentNode !== undefined && ( - - - - - - - - - )} */} + props.currentNodeType.attributes !== undefined && ( + + )} {currentNode !== undefined && ( @@ -204,6 +263,15 @@ export default function UpdateNodeInline(props) { Update )} + {currentNode && ( + + )}
); } diff --git a/cra-client/src/components/GlossaryAuthor/components/visualisation/glove.scss b/cra-client/src/components/GlossaryAuthor/components/visualisation/glove.scss index 9a0c082f..7201ccbc 100644 --- a/cra-client/src/components/GlossaryAuthor/components/visualisation/glove.scss +++ b/cra-client/src/components/GlossaryAuthor/components/visualisation/glove.scss @@ -96,6 +96,10 @@ background-color : rgb(180,180,180); } +.fullwidth { + width : 100%; +} + .title { padding : 20px; font-size : 20px;