| /* |
| * Copyright 2020 Bitnine Co., Ltd. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| import React, { useState } from 'react'; |
| import PropTypes from 'prop-types'; |
| import { Badge } from 'react-bootstrap'; |
| import uuid from 'react-uuid'; |
| import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; |
| import { faAngleDown, faAngleUp } from '@fortawesome/free-solid-svg-icons'; |
| import { |
| updateEdgeLabelSize, |
| updateLabelCaption, |
| updateLabelColor, |
| updateNodeLabelSize, |
| } from '../../features/cypher/CypherUtil'; |
| |
| const CypherResultCytoscapeFooter = ({ |
| footerData, |
| edgeLabelColors, |
| nodeLabelColors, |
| nodeLabelSizes, |
| edgeLabelSizes, |
| colorChange, |
| sizeChange, |
| captionChange, |
| selectedCaption, |
| captions, |
| setCytoscapeLayout, |
| cytoscapeLayout, |
| }) => { |
| const [footerExpanded, setFooterExpanded] = useState(false); |
| |
| const extractData = (d) => { |
| const extractedData = []; |
| for (let i = 0; i < Object.entries(d).length; i += 1) { |
| const [alias, val] = Object.entries(d)[i]; |
| extractedData.push( |
| <span key={uuid()} className="label"> |
| <strong className="pl-3"> |
| {alias} |
| {' '} |
| : |
| {' '} |
| </strong> |
| {' '} |
| {typeof val === 'object' ? JSON.stringify(val) : val} |
| </span>, |
| ); |
| } |
| return extractedData; |
| }; |
| |
| const displayFooterData = () => { |
| if (footerData.type === 'elements') { |
| const isEdge = footerData.data.source; |
| |
| return ( |
| <div className="d-flex pl-3"> |
| <div className={`mr-auto graphFrameFooter ${footerExpanded ? 'expandedGraphFrameFooter' : ''}`}> |
| <Badge |
| className="px-3 py-1" |
| pill={isEdge === false} |
| style={{ |
| backgroundColor: footerData.data.backgroundColor, |
| color: footerData.data.fontColor, |
| }} |
| > |
| {footerData.data.label} |
| </Badge> |
| <span className="label"> |
| <strong className="pl-3"><gid> : </strong> |
| {' '} |
| {footerData.data.id} |
| </span> |
| {extractData(footerData.data.properties)} |
| </div> |
| <button |
| type="button" |
| className="frame-head-button btn btn-link px-3" |
| onClick={() => setFooterExpanded(!footerExpanded)} |
| > |
| <FontAwesomeIcon |
| icon={footerExpanded ? faAngleUp : faAngleDown} |
| /> |
| </button> |
| </div> |
| ); |
| } |
| if (footerData.type === 'background') { |
| return ( |
| <div className="d-flex pl-3"> |
| <div className="mr-auto label pl-3"> |
| Displaying |
| <strong>{footerData.data.nodeCount}</strong> |
| |
| nodes, |
| <strong>{footerData.data.edgeCount}</strong> |
| {' '} |
| edges |
| </div> |
| Layout : |
| <select |
| id="selectLayout" |
| className="col-1 custom-select custom-select-sm layout-select" |
| defaultValue={cytoscapeLayout} |
| onChange={(e) => [setCytoscapeLayout(e.target.value)]} |
| > |
| <option value="random">Random</option> |
| <option value="grid">Grid</option> |
| <option value="breadthFirst">Breadth-First</option> |
| <option value="concentric">Concentric</option> |
| <option value="cola">Cola</option> |
| <option value="cose">Cose</option> |
| <option value="coseBilkent">Cose-Bilkent</option> |
| <option value="dagre">Dagre</option> |
| <option value="klay">Klay</option> |
| <option value="euler">Euler</option> |
| <option value="avsdf">Avsdf</option> |
| <option value="spread">Spread</option> |
| </select> |
| </div> |
| ); |
| } |
| if (footerData.type === 'labels') { |
| const isEdge = footerData.data.type === 'edge'; |
| |
| const nodeSizeButton = (nodeSize, i) => { |
| const size = (i * 3) + 12; |
| return ( |
| <button |
| onClick={() => [updateNodeLabelSize(footerData.data.label, nodeSize), |
| sizeChange(footerData.data.type, footerData.data.label, nodeSize)]} |
| key={uuid()} |
| type="button" |
| className={`btn sizeSelector node ${footerData.data.size >= nodeSize ? ' selectedSize ' : ''}`} |
| style={{ width: `${size}px`, height: `${size}px` }} |
| > |
| |
| </button> |
| ); |
| }; |
| |
| const edgeSizeButton = (edgeSize, i) => { |
| const size = (i * 3) + 12; |
| return ( |
| <button |
| onClick={() => [updateEdgeLabelSize(footerData.data.label, edgeSize), |
| sizeChange(footerData.data.type, footerData.data.label, edgeSize)]} |
| key={uuid()} |
| type="button" |
| className={`btn sizeSelector edge ${footerData.data.size >= edgeSize ? ' selectedSize ' : ''}`} |
| style={{ width: `${size + 18}px`, height: `${size}px` }} |
| > |
| |
| </button> |
| ); |
| }; |
| |
| const generateButton = () => { |
| if (footerData.data.type === 'node') { |
| return nodeLabelSizes.map((labelSize, i) => nodeSizeButton(labelSize.size, i)); |
| } |
| if (footerData.data.type === 'edge') { |
| return edgeLabelSizes.map((labelSize, i) => edgeSizeButton(labelSize.size, i)); |
| } |
| return null; |
| }; |
| const generateColors = () => { |
| if (footerData.data.type === 'node') { |
| return nodeLabelColors.map((color) => ( |
| <button |
| onClick={() => [ |
| updateLabelColor(footerData.data.type, footerData.data.label, color), |
| colorChange(footerData.data.type, footerData.data.label, color)]} |
| key={uuid()} |
| type="button" |
| className={`btn colorSelector ${footerData.data.backgroundColor === color.color ? ' selectedColor ' : ''}`} |
| style={{ backgroundColor: color.color }} |
| > |
| |
| </button> |
| )); |
| } |
| if (footerData.data.type === 'edge') { |
| return edgeLabelColors.map((color) => ( |
| <button |
| onClick={() => [ |
| updateLabelColor(footerData.data.type, footerData.data.label, color), |
| colorChange(footerData.data.type, footerData.data.label, color)]} |
| key={uuid()} |
| type="button" |
| className={`btn colorSelector ${footerData.data.backgroundColor === color.color ? ' selectedColor ' : ''}`} |
| style={{ backgroundColor: color.color }} |
| > |
| |
| </button> |
| )); |
| } |
| return null; |
| }; |
| |
| return ( |
| <div className="d-flex pl-3"> |
| <div className={`mr-auto graphFrameFooter ${footerExpanded ? 'expandedGraphFrameFooter' : ''}`}> |
| <Badge |
| className="px-3 py-1" |
| pill={isEdge === false} |
| style={{ |
| backgroundColor: footerData.data.backgroundColor, |
| color: footerData.data.fontColor, |
| }} |
| > |
| {footerData.data.label} |
| </Badge> |
| <span className="label"> |
| <span className="pl-3">Color : </span> |
| {generateColors()} |
| </span> |
| <span className="label"> |
| <span className="pl-3">Size : </span> |
| {generateButton()} |
| </span> |
| <span className="label"> |
| <span className="pl-3">Caption : </span> |
| {captions.map((caption) => ( |
| <button |
| onClick={() => [ |
| updateLabelCaption(footerData.data.type, footerData.data.label, caption), |
| captionChange(footerData.data.type, footerData.data.label, caption)]} |
| key={uuid()} |
| type="button" |
| className={`btn captionSelector ${selectedCaption === caption ? ' btn-secondary ' : ' btn-outline-dark '}`} |
| > |
| <strong> |
| < |
| {caption} |
| > |
| </strong> |
| </button> |
| ))} |
| <button |
| onClick={() => [ |
| updateLabelCaption(footerData.data.type, footerData.data.label, null), |
| captionChange(footerData.data.type, footerData.data.label, null)]} |
| key={uuid()} |
| type="button" |
| className={`btn captionSelector ${selectedCaption === null ? ' btn-secondary ' : ' btn-outline-dark '}`} |
| > |
| <strong> |
| < |
| > |
| </strong> |
| </button> |
| </span> |
| </div> |
| <button |
| type="button" |
| className="frame-head-button btn btn-link px-3" |
| onClick={() => setFooterExpanded(!footerExpanded)} |
| > |
| <FontAwesomeIcon |
| icon={footerExpanded ? faAngleUp : faAngleDown} |
| /> |
| </button> |
| </div> |
| ); |
| } |
| return ( |
| <div className="d-flex pl-3"> |
| <div className="mr-auto label pl-3" /> |
| <div className="px-1">Layout : </div> |
| <select |
| id="selectLayout" |
| className="col-1 custom-select custom-select-sm layout-select" |
| defaultValue={cytoscapeLayout} |
| onChange={(e) => [setCytoscapeLayout(e.target.value)]} |
| > |
| <option value="random">Random</option> |
| <option value="grid">Grid</option> |
| <option value="breadthFirst">Breadth-First</option> |
| <option value="concentric">Concentric</option> |
| <option value="cola">Cola</option> |
| <option value="cose">Cose</option> |
| <option value="coseBilkent">Cose-Bilkent</option> |
| <option value="dagre">Dagre</option> |
| <option value="klay">Klay</option> |
| <option value="euler">Euler</option> |
| <option value="avsdf">Avsdf</option> |
| <option value="spread">Spread</option> |
| </select> |
| </div> |
| ); |
| }; |
| |
| return ( |
| <div className="chart-footer-area text-muted"> |
| {displayFooterData()} |
| </div> |
| ); |
| }; |
| |
| CypherResultCytoscapeFooter.defaultProps = { |
| selectedCaption: null, |
| }; |
| |
| CypherResultCytoscapeFooter.propTypes = { |
| // eslint-disable-next-line react/forbid-prop-types |
| footerData: PropTypes.any.isRequired, |
| edgeLabelColors: PropTypes.arrayOf(PropTypes.shape({ |
| color: PropTypes.string, |
| borderColor: PropTypes.string, |
| fontColor: PropTypes.string, |
| // eslint-disable-next-line react/forbid-prop-types |
| edgeLabels: PropTypes.any, |
| index: PropTypes.number, |
| })).isRequired, |
| nodeLabelColors: PropTypes.arrayOf(PropTypes.shape({ |
| color: PropTypes.string, |
| borderColor: PropTypes.string, |
| fontColor: PropTypes.string, |
| // eslint-disable-next-line react/forbid-prop-types |
| nodeLabels: PropTypes.any, |
| index: PropTypes.number, |
| })).isRequired, |
| nodeLabelSizes: PropTypes.arrayOf(PropTypes.shape({ |
| size: PropTypes.number, |
| // eslint-disable-next-line react/forbid-prop-types |
| labels: PropTypes.any, |
| index: PropTypes.number, |
| })).isRequired, |
| edgeLabelSizes: PropTypes.arrayOf(PropTypes.shape({ |
| size: PropTypes.number, |
| // eslint-disable-next-line react/forbid-prop-types |
| labels: PropTypes.any, |
| index: PropTypes.number, |
| })).isRequired, |
| colorChange: PropTypes.func.isRequired, |
| sizeChange: PropTypes.func.isRequired, |
| captionChange: PropTypes.func.isRequired, |
| setCytoscapeLayout: PropTypes.func.isRequired, |
| cytoscapeLayout: PropTypes.string.isRequired, |
| selectedCaption: PropTypes.string, |
| captions: PropTypes.arrayOf(PropTypes.string).isRequired, |
| }; |
| |
| export default CypherResultCytoscapeFooter; |