blob: 652158540e8e0ca9b0019ae5cb463e2dda3bf7ef [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 from 'react';
import PropTypes from 'prop-types';
import { Modal } from 'antd';
import uuid from 'react-uuid';
import { connect, useDispatch } from 'react-redux';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faRedo, faTimes } from '@fortawesome/free-solid-svg-icons';
import { VerticalLine, SubLabelLeft, SubLabelRight } from './SidebarComponents';
const genLabelQuery = (eleType, labelName, database) => {
function age() {
if (eleType === 'node') {
if (labelName === '*') {
return `SELECT * from cypher('${database.graph}', $$
MATCH (V)
RETURN V
$$) as (V agtype);`;
}
return `SELECT * from cypher('${database.graph}', $$
MATCH (V:${labelName})
RETURN V
$$) as (V agtype);`;
}
if (eleType === 'edge') {
if (labelName === '*') {
return `SELECT * from cypher('${database.graph}', $$
MATCH (V)-[R]-(V2)
RETURN V,R,V2
$$) as (V agtype, R agtype, V2 agtype);`;
}
return `SELECT * from cypher('${database.graph}', $$
MATCH (V)-[R:${labelName}]-(V2)
RETURN V,R,V2
$$) as (V agtype, R agtype, V2 agtype);`;
}
return '';
}
function agens() {
if (eleType === 'node') {
if (labelName === '*') {
return 'MATCH (V) RETURN V';
}
return `MATCH (V) WHERE LABEL(V) = '${labelName}' RETURN V`;
}
if (eleType === 'edge') {
if (labelName === '*') {
return 'MATCH (V)-[R]->(V2) RETURN *';
}
return `MATCH (V)-[R]->(V2) WHERE LABEL(R) = '${labelName}' RETURN *`;
}
return '';
}
if (database.flavor === 'AGE') {
return age();
}
if (database.flavor === 'AGENS') {
return agens();
}
return '';
};
const genPropQuery = (eleType, propertyName) => {
if (eleType === 'v') {
return `MATCH (V) WHERE V.${propertyName} IS NOT NULL RETURN V`;
}
if (eleType === 'e') {
return `MATCH (V)-[R]->(V2) WHERE R.${propertyName} IS NOT NULL RETURN *`;
}
return '';
};
const NodeList = ({ nodes, setCommand }) => {
let list;
if (nodes) {
list = nodes.map((item) => (
<NodeItems
key={uuid()}
label={item.label}
cnt={item.cnt}
setCommand={setCommand}
/>
));
return (
<div style={{
display: 'flex',
flexWrap: 'wrap',
height: '80px',
overflowY: 'auto',
marginTop: '12px',
}}
>
{list}
</div>
);
}
return null;
};
NodeList.propTypes = {
nodes: PropTypes.arrayOf(PropTypes.shape({
label: PropTypes.string,
cnt: PropTypes.number,
})).isRequired,
setCommand: PropTypes.func.isRequired,
};
const NodeItems = connect((state) => ({
database: state.database,
}), {})(
({
label, cnt, setCommand, database,
}) => (
<button
type="button"
className="node-item"
onClick={() => setCommand(genLabelQuery('node', label, database))}
>
{label}
(
{cnt}
)
</button>
),
);
NodeItems.propTypes = {
database: PropTypes.shape({
flavor: PropTypes.string,
}).isRequired,
label: PropTypes.string.isRequired,
cnt: PropTypes.number.isRequired,
setCommand: PropTypes.func.isRequired,
};
const EdgeList = ({ edges, setCommand }) => {
let list;
if (edges) {
list = edges.map((item) => (
<EdgeItems
key={uuid()}
label={item.label}
cnt={item.cnt}
setCommand={setCommand}
/>
));
return (
<div style={{
display: 'flex',
flexWrap: 'wrap',
height: '80px',
overflowY: 'auto',
marginTop: '12px',
}}
>
{list}
</div>
);
}
return null;
};
EdgeList.propTypes = {
edges: PropTypes.arrayOf(PropTypes.shape({
label: PropTypes.string,
cnt: PropTypes.number,
})).isRequired,
setCommand: PropTypes.func.isRequired,
};
const EdgeItems = connect((state) => ({
database: state.database,
}), {})(({
label, cnt, setCommand, database,
}) => (
<button
type="button"
className="edge-item"
onClick={() => setCommand(genLabelQuery('edge', label, database))}
>
{label}
(
{cnt}
)
</button>
));
EdgeItems.propTypes = {
database: PropTypes.shape({
flavor: PropTypes.string,
}).isRequired,
label: PropTypes.string.isRequired,
cnt: PropTypes.number.isRequired,
setCommand: PropTypes.func.isRequired,
};
const PropertyList = ({ propertyKeys, setCommand }) => {
let list;
if (propertyKeys) {
list = propertyKeys.map((item) => (
<PropertyItems
key={uuid()}
propertyName={item.key}
keyType={item.key_type}
setCommand={setCommand}
/>
));
return (
<div style={{
display: 'flex',
flexWrap: 'wrap',
height: '80px',
overflowY: 'auto',
marginTop: '12px',
}}
>
{list}
</div>
);
}
return null;
};
PropertyList.propTypes = {
propertyKeys: PropTypes.arrayOf(PropTypes.shape({
key: PropTypes.string,
key_type: PropTypes.string,
})).isRequired,
setCommand: PropTypes.func.isRequired,
};
const PropertyItems = ({ propertyName, keyType, setCommand }) => (
<button
type="button"
className={`${keyType === 'v' ? 'propertie-item' : 'propertie-item'} propertie-item`}
onClick={() => setCommand(genPropQuery(keyType, propertyName))}
>
{propertyName}
</button>
);
PropertyItems.propTypes = {
propertyName: PropTypes.string.isRequired,
keyType: PropTypes.string.isRequired,
setCommand: PropTypes.func.isRequired,
};
const ConnectedText = ({ userName, roleName }) => (
<div>
<h6>
<div style={{ display: 'flex', flexWrap: 'wrap' }}>
<SubLabelRight label="Username :" classes="col-sm-6" />
<SubLabelLeft label={userName} classes="col-sm-6" />
</div>
<div style={{ display: 'flex', flexWrap: 'wrap' }}>
<SubLabelRight label="Roles :" classes="col-sm-6" />
<SubLabelLeft label={roleName} classes="col-sm-6" />
</div>
</h6>
</div>
);
ConnectedText.propTypes = {
userName: PropTypes.string.isRequired,
roleName: PropTypes.string.isRequired,
};
const DBMSText = ({ dbname, graph }) => (
<div>
<h6>
<div style={{ display: 'flex', flexWrap: 'wrap' }}>
<SubLabelRight label="Databases :" classes="col-sm-6" />
<SubLabelLeft label={dbname} classes="col-sm-6" />
</div>
<div style={{ display: 'flex', flexWrap: 'wrap' }}>
<SubLabelRight label="Graph Path :" classes="col-sm-6" />
<SubLabelLeft label={graph} classes="col-sm-6" />
</div>
<div style={{ display: 'flex', flexWrap: 'wrap' }}>
<SubLabelRight label="Information :" classes="col-sm-6" />
<SubLabelLeft label="-" classes="col-sm-6" />
</div>
<div style={{ display: 'flex', flexWrap: 'wrap' }}>
<SubLabelRight label="Query List :" classes="col-sm-6" />
<SubLabelLeft label="-" classes="col-sm-6" />
</div>
</h6>
</div>
);
DBMSText.propTypes = {
dbname: PropTypes.string.isRequired,
graph: PropTypes.string.isRequired,
};
const SidebarHome = ({
edges,
nodes,
propertyKeys,
setCommand,
command,
trimFrame,
addFrame,
getMetaData,
}) => {
const dispatch = useDispatch();
const { confirm } = Modal;
const requestDisconnect = () => {
const refKey = uuid();
dispatch(() => trimFrame('ServerDisconnect'));
dispatch(() => addFrame(command, 'ServerDisconnect', refKey));
};
const refreshSidebarHome = () => {
getMetaData();
};
return (
<div className="sidebar-home">
<div className="sidebar sidebar-body">
<div className="form-group sidebar-item">
<b>Node Label</b>
<br />
<NodeList nodes={nodes} setCommand={setCommand} />
</div>
<VerticalLine />
<div className="form-group sidebar-item">
<b>Edge Label</b>
<br />
<EdgeList edges={edges} setCommand={setCommand} />
</div>
<VerticalLine />
<div className="form-group sidebar-item">
<b>Properties</b>
<br />
<PropertyList propertyKeys={propertyKeys} setCommand={setCommand} />
</div>
<VerticalLine />
<div className="form-group sidebar-item-disconnect">
<button
className="frame-head-button refresh_button btn btn-link"
type="button"
onClick={() => refreshSidebarHome()}
>
<FontAwesomeIcon
icon={faRedo}
size="1x"
color="white"
flip="horizontal"
/>
</button>
<br />
<b>Refresh</b>
<div style={{
border: '1px solid #C4C4C4',
opacity: '1',
width: '80%',
height: '0',
margin: '3px auto',
}}
/>
<button
className="frame-head-button close_session btn btn-link"
type="button"
color="#142B80"
onClick={() => confirm({
title: 'Are you sure you want to close this window?',
onOk() {
requestDisconnect();
},
onCancel() {
return false;
},
})}
>
<FontAwesomeIcon
icon={faTimes}
size="1x"
color="white"
/>
</button>
<br />
<b>Close Session</b>
</div>
</div>
</div>
);
};
SidebarHome.propTypes = {
edges: PropTypes.arrayOf(PropTypes.shape({
label: PropTypes.string,
cnt: PropTypes.number,
})).isRequired,
nodes: PropTypes.arrayOf(PropTypes.shape({
label: PropTypes.string,
cnt: PropTypes.number,
})).isRequired,
propertyKeys: PropTypes.arrayOf(PropTypes.shape({
key: PropTypes.string,
key_type: PropTypes.string,
})).isRequired,
setCommand: PropTypes.func.isRequired,
command: PropTypes.string.isRequired,
trimFrame: PropTypes.func.isRequired,
addFrame: PropTypes.func.isRequired,
getMetaData: PropTypes.func.isRequired,
};
export default SidebarHome;