blob: fb63dc98315efe7e8b33621f123d042cea79bb29 [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, { useEffect, useState } from 'react';
import { useDispatch } from 'react-redux';
import uuid from 'react-uuid';
import PropTypes from 'prop-types';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faTimesCircle, faToggleOff, faToggleOn } from '@fortawesome/free-solid-svg-icons';
import store from '../../../app/store';
import AlertContainers from '../../alert/containers/AlertContainers';
import CodeMirror from '../../editor/containers/CodeMirrorWapperContainer';
import SideBarToggle from '../../editor/containers/SideBarMenuToggleContainer';
import { setting } from '../../../conf/config';
import IconPlay from '../../../icons/IconPlay';
import { getMetaData } from '../../../features/database/MetadataSlice';
const Editor = ({
setCommand,
activeRequests,
command,
update,
addFrame,
trimFrame,
addAlert,
alertList,
isActive,
database,
executeCypherQuery,
addCommandHistory,
toggleMenu,
setLabel,
isLabel,
// addCommandFavorites,
}) => {
const dispatch = useDispatch();
const [alerts, setAlerts] = useState([]);
const [activePromises, setPromises] = useState({});
// const favoritesCommand = () => {
// dispatch(() => addCommandFavorites(command));
// };
const clearCommand = () => {
setCommand('');
};
const onClick = () => {
const refKey = uuid();
if (command.toUpperCase().startsWith(':PLAY')) {
dispatch(() => addFrame(command, 'Contents', refKey));
} else if (command.toUpperCase().startsWith(':CSV')) {
dispatch(() => addFrame(command, 'CSV', refKey));
} else if (command.toUpperCase() === ':SERVER STATUS') {
dispatch(() => trimFrame('ServerStatus'));
dispatch(() => addFrame(command, 'ServerStatus', refKey));
} else if (database.status === 'disconnected' && command.toUpperCase() === ':SERVER DISCONNECT') {
dispatch(() => trimFrame('ServerDisconnect'));
dispatch(() => trimFrame('ServerConnect'));
dispatch(() => addAlert('ErrorNoDatabaseConnected'));
dispatch(() => addFrame(command, 'ServerDisconnect', refKey));
} else if (database.status === 'disconnected' && command.toUpperCase() === ':SERVER CONNECT') {
if (!setting.closeWhenDisconnect) {
dispatch(() => trimFrame('ServerConnect'));
dispatch(() => addFrame(':server connect', 'ServerConnect'));
}
} else if (database.status === 'disconnected') {
dispatch(() => trimFrame('ServerConnect'));
dispatch(() => addAlert('ErrorNoDatabaseConnected'));
dispatch(() => addFrame(command, 'ServerConnect', refKey));
} else if (database.status === 'connected' && command.toUpperCase() === ':SERVER DISCONNECT') {
dispatch(() => trimFrame('ServerDisconnect'));
dispatch(() => addAlert('NoticeServerDisconnected'));
dispatch(() => addFrame(command, 'ServerDisconnect', refKey));
} else if (database.status === 'connected' && command.toUpperCase() === ':SERVER CONNECT') {
if (!setting.connectionStatusSkip) {
dispatch(() => trimFrame('ServerStatus'));
dispatch(() => addAlert('NoticeAlreadyConnected'));
dispatch(() => addFrame(command, 'ServerStatus', refKey));
}
} else if (database.status === 'connected') {
addFrame(command, 'CypherResultFrame', refKey);
const req = dispatch(() => executeCypherQuery([refKey, command]));
req.then((response) => {
if (response.type === 'cypher/executeCypherQuery/rejected') {
if (response.error.name !== 'AbortError') {
dispatch(() => addAlert('ErrorCypherQuery'));
const currentCommand = store.getState().editor.command;
if (currentCommand === '') {
setCommand(command);
}
}
return;
}
if (update) dispatch(getMetaData());
});
activePromises[refKey] = req;
setPromises({ ...activePromises });
}
dispatch(() => addCommandHistory(command));
clearCommand();
};
useEffect(() => {
const reqCancel = Object.keys(activePromises).filter((ref) => !activeRequests.includes(ref));
reqCancel.forEach((ref) => {
activePromises[ref].abort();
delete activePromises[ref];
});
setPromises({ ...activePromises });
}, [activeRequests]);
useEffect(() => {
setAlerts(
alertList.map((alert) => (
<AlertContainers
key={alert.alertProps.key}
alertKey={alert.alertProps.key}
alertName={alert.alertName}
errorMessage={alert.alertProps.errorMessage}
/>
)),
);
}, [alertList]);
return (
<div className="container-fluid">
<div className="editor">
<div className="container-fluid editor-area card-header">
<div className="input-group input-style">
<div id="codeMirrorEditor" className="form-control col-11 editor-code-wrapper">
<CodeMirror
onClick={onClick}
value={command}
onChange={setCommand}
/>
</div>
<div className="input-group-append ml-auto editor-button-wrapper" id="editor-buttons">
{/* <button className="frame-head-button btn btn-link"
type="button" onClick={() => favoritesCommand()}>
<FontAwesomeIcon
icon={faStar}
size="lg"
/>
</button> */}
<button className={command ? 'btn show-eraser' : 'btn hide-eraser'} type="button" id="eraser" onDoubleClick={() => clearCommand()} aria-label="Clear Command">
<FontAwesomeIcon
icon={faTimesCircle}
size="1x"
/>
</button>
<button
className="frame-head-button btn btn-link"
type="button"
onClick={() => onClick()}
title="Run Query"
aria-label="Run Query"
>
<IconPlay />
</button>
<button
className="frame-head-button btn btn-link"
type="button"
onClick={() => {
toggleMenu('home');
/*
if (!isActive) {
document.getElementById('wrapper')?.classList?.remove('wrapper');
document.getElementById('wrapper')?.classList?.add('wrapper-extension-padding');
} else {
document.getElementById('wrapper')?
.classList?.remove('wrapper-extension-padding');
document.getElementById('wrapper')?.classList?.add('wrapper');
} */
}}
title={(isActive) ? 'Hide' : 'Show'}
aria-label="toggleMenu"
>
<SideBarToggle isActive={isActive} />
</button>
<button
className="frame-head-button btn btn-link"
type="button"
onClick={() => setLabel()}
title="Run Query"
aria-label="Run Query"
>
<FontAwesomeIcon
icon={isLabel ? faToggleOn : faToggleOff}
size="2x"
/>
</button>
</div>
</div>
</div>
</div>
{alerts}
</div>
);
};
Editor.propTypes = {
setCommand: PropTypes.func.isRequired,
activeRequests: PropTypes.arrayOf(PropTypes.string).isRequired,
command: PropTypes.string.isRequired,
addFrame: PropTypes.func.isRequired,
trimFrame: PropTypes.func.isRequired,
addAlert: PropTypes.func.isRequired,
alertList: PropTypes.arrayOf(PropTypes.shape({
alertName: PropTypes.string.isRequired,
alertProps: PropTypes.shape({
key: PropTypes.string.isRequired,
alertType: PropTypes.string.isRequired,
errorMessage: PropTypes.string.isRequired,
}),
})).isRequired,
isActive: PropTypes.bool.isRequired,
database: PropTypes.shape({
status: PropTypes.string.isRequired,
host: PropTypes.string.isRequired,
}).isRequired,
executeCypherQuery: PropTypes.func.isRequired,
addCommandHistory: PropTypes.func.isRequired,
toggleMenu: PropTypes.func.isRequired,
update: PropTypes.bool.isRequired,
setLabel: PropTypes.func.isRequired,
isLabel: PropTypes.bool.isRequired,
// addCommandFavorites: PropTypes.func.isRequired,
};
export default Editor;