From 4c3b6346846146b4391176082263fdb6e1a1b6ef Mon Sep 17 00:00:00 2001 From: Jordan Conklin Date: Mon, 1 Aug 2022 16:44:34 -0500 Subject: [PATCH 1/3] fixed z index issue but form is not yet submitting. import form is the same as create form Signed-off-by: Jordan Conklin --- src/components/builder/ArchitectureModal.jsx | 6 +- src/components/builder/ArchitectureView.jsx | 339 +++++++++++++++++- src/components/builder/_ArchitectureView.scss | 5 + .../builder/bom/_BillofMaterials.scss | 4 - 4 files changed, 341 insertions(+), 13 deletions(-) diff --git a/src/components/builder/ArchitectureModal.jsx b/src/components/builder/ArchitectureModal.jsx index ddb48e9..02094ce 100644 --- a/src/components/builder/ArchitectureModal.jsx +++ b/src/components/builder/ArchitectureModal.jsx @@ -16,6 +16,9 @@ import { updateArchitecture } from '../../services/architectures'; +import SlidingPane from 'react-sliding-pane' + + class ArchitectureModal extends Component { constructor(props) { super(props); @@ -183,7 +186,7 @@ class ArchitectureModal extends Component { - +
{!this.props.isImport && } -
diff --git a/src/components/builder/ArchitectureView.jsx b/src/components/builder/ArchitectureView.jsx index fa294ac..b712a05 100644 --- a/src/components/builder/ArchitectureView.jsx +++ b/src/components/builder/ArchitectureView.jsx @@ -18,7 +18,9 @@ import { OverflowMenuItem, SearchSkeleton, Button, - Grid, Row, Column + Grid, Row, Column, + Form, FormGroup, + TextInput, TextArea, Select, SelectItem, FileUploader } from 'carbon-components-react'; import YAML from 'yaml'; @@ -32,7 +34,16 @@ import ArchitectureModal from './ArchitectureModal'; import ImageWithStatus from '../ImageWithStatus'; import ValidateModal from '../ValidateModal'; -import { deleteArchitecture } from '../../services/architectures'; +import { uploadDiagrams, deleteArchitecture, importBomYaml, duplicateArchitecture, + addArchitecture, updateArchitecture } from '../../services/architectures'; + +import SlidingPane from 'react-sliding-pane' + +import AceEditor from "react-ace"; + +import { + servicePlatforms +} from '../../data/data'; class ArchitectureView extends Component { @@ -59,8 +70,34 @@ class ArchitectureView extends Component { isSoftware: false, showValidate: false, curArch: undefined, - show: "public-archs" + show: "public-archs", + + show: this.props.show, + onRequestClose: this.props.handleClose, + diagramDrawio: undefined, + diagramPng: undefined, + bomYaml: undefined, + overwrite: "", + fields: { + arch_id: "", + name: "", + short_desc: "", + long_desc: "", + public: false, + production_ready: false, + yaml: "", + platform: "", + } }; + + if (this.props.isUpdate) { + let jsonObject = JSON.parse(JSON.stringify(this.props.data).replace(/"id":/g, "\"_id\":")); + console.log(jsonObject); + this.state = { + fields: jsonObject + } + } + this.loadArchitectures = this.loadArchitectures.bind(this); this.loadGallery = this.loadGallery.bind(this); this.showArchModal = this.showArchModal.bind(this); @@ -69,8 +106,138 @@ class ArchitectureView extends Component { this.handleImageLoaded = this.handleImageLoaded.bind(this); this.handleImageErrored = this.handleImageErrored.bind(this); this.syncIascable = this.syncIascable.bind(this); + + this.handleChange = this.handleChange.bind(this) + this.handleSubmit = this.handleSubmit.bind(this) } + + uploadDiagrams(arch_id) { + // Upload Diagrams + const drawio = this.state.diagramDrawio; + const png = this.state.diagramPng; + if (drawio || png) { + this.props.toast("info", "Uploading Diagram", `Uploading diagrams for architecture ${arch_id}.`); + console.log(drawio); + console.log(png); + if (drawio && !drawio?.name.endsWith(".drawio")) return this.props.toast("error", "Wrong File Type", "Only .drawio is accepted."); + if (png && png?.type !== "image/png") return this.props.toast("error", "Wrong File Type", "Only .drawio is accepted."); + if (drawio && drawio?.size > 2048000) return this.props.toast("error", "Too Large", "Drawio file too larde, max size: 2MiB."); + if (png && png?.size > 2048000) return this.props.toast("error", "Too Large", "PNG file too larde, max size: 2MiB."); + let data = new FormData(); + if (drawio) data.append("drawio", drawio); + if (png) data.append("png", png); + uploadDiagrams(arch_id, data).then((res) => { + if (res && res.body && res.body.error) { + this.props.toast("error", "Upload Error", res.body.error.message); + } else { + this.props.toast("success", "Success", `Diagrams upload successful!`); + this.props.handleReload(); + } + this.props.handleClose(true); + }); + } else { + this.props.handleClose(); + this.props.handleReload(); + } + } + + + handleChange(field, e) { + let fields = this.state.fields; + let overwrite = ""; + if (field === "overwrite") { + overwrite = e.target.value + } else if (field === "yaml") { + fields[field] = e; + } else if (field === "public" || field === "production_ready") { + fields[field] = e.target.value === "true"; + } else { + fields[field] = e.target.value; + } + this.setState({ fields, overwrite }); + } + handleSubmit = (event) => { + event.preventDefault(); + if (this.props.isImport) { + // Upload Diagrams + const boms = this.state.bomYaml; + if (boms?.length > 0) { + this.props.toast("info", "Uploading BOM", `Uploading BOMs yaml.`); + let data = new FormData(); + let bomIx = 0; + for (const bom of boms) { + console.log(bom) + if (bom?.type !== "application/x-yaml" && bom?.type !== "text/yaml" && !bom?.name.endsWith('.yaml')) return this.props.toast("error", "Wrong File Type", "Only .yaml is accepted."); + if (bom?.size > 409600) return this.props.toast("error", "Too Large", "YAML file too larde, max size: 400KiB."); + data.append(`bom${bomIx}`, bom); + bomIx = bomIx + 1; + } + importBomYaml(data, this.state.overwrite === "overwrite", this.state.fields?.public).then(res => { + if (res && res.body && res.body.error) { + this.props.toast("error", res?.status === 401 ? "Unauthorized" : "Error", res.body.error.message); + } else { + this.props.toast("success", "Success", `BOM(s) successfully imported!`); + this.props.handleClose(); + this.props.handleReload(); + } + }); + } else { + this.props.toast("error", "File Missing", "You must upload the BOM yaml file."); + } + } else if (this.state.fields.name && this.props.isDuplicate) { + this.props.toast("info", "Duplicating", `Duplicating architecture ${this.props.isDuplicate}...`); + duplicateArchitecture(this.props.isDuplicate, { + arch_id: this.state.fields.name.replace(/[\s_]+/g, '-').replace(/[^0-9a-zA-Z-]+/g, '').toLowerCase(), + name: this.state.fields.name + }) + .then((res) => { + if (res?.body?.error) this.props.toast("error", res?.status === 401 ? "Unauthorized" : "Error", res?.body?.error?.message); + else { + this.props.toast("success", "Success", `Bill of Materials ${this.props.isDuplicate} duplicated!`); + this.props.handleClose(); + this.props.handleReload(); + } + }) + .catch((err) => { + this.addNotification("error", "Error", err); + }) + } else if (this.state.fields.name && !this.props.isUpdate) { + const fields = this.state.fields; + fields.arch_id = this.state.fields.name.replace(/[\s_]+/g, '-').replace(/[^0-9a-zA-Z-]+/g, '').toLowerCase(); + addArchitecture(fields).then(res => { + if (res && res.body && res.body.error) { + this.props.toast("error", res?.status === 401 ? "Unauthorized" : "Error", res.body.error.message); + } else { + this.props.toast("success", "Success", `Bill of Materials ${res.arch_id} successfully added!`); + this.uploadDiagrams(res.arch_id); + } + }); + } else if(this.state.fields.name) { + updateArchitecture(this.props.data.arch_id, { + name: this.state.fields.name, + short_desc: this.state.fields.short_desc, + long_desc: this.state.fields.long_desc, + public: this.state.fields.public, + platform: this.state.fields.platform, + yaml: this.state.fields.yaml, + }).then(res => { + if (res && res.body && res.body.error) { + this.props.toast("error", res?.status === 401 ? "Unauthorized" : "Error", res.body.error.message); + } else { + this.props.toast("success", "Success", `Bill of Materials ${res.arch_id} successfully updated!`); + this.uploadDiagrams(res.arch_id); + } + }); + } else { + this.props.toast("error", "INVALID INPUT", "You must set an architecture Name."); + } + + } + + + + handleImageLoaded(archid) { const images = this.state.images; const imgIx = images?.findIndex(i => i.archid === archid); @@ -258,7 +425,7 @@ class ArchitectureView extends Component { - {this.state.showArchModal && + {/* {this.state.showArchModal && - } + } */} + + + + {this.state.showValidate && this.state.curArch && {(this.state.user?.roles?.includes("editor") && this.props.isUser) || this.state.user?.roles?.includes("admin") ? - : <>} - {this.state.user?.role === "admin" ? : <>} + : <>} + {this.state.user?.role === "admin" ? : <>} @@ -324,6 +495,160 @@ class ArchitectureView extends Component { +
+ } + title="Add Bill of Materials" + isOpen={this.state.showForm} + width="600px" + onRequestClose={() => this.setState({ showForm: false })} + onRequestSubmit={this.handleSubmit} + data={this.state.archRecord} + handleReload={this.loadArchitectures} + > +
+ {!this.props.isImport && } + {!this.props.isImport && !this.props.isDuplicate && } + {!this.props.isImport && !this.props.isDuplicate &&