feat: codemirror single line editor

This commit is contained in:
Anoop M D 2023-01-20 09:39:32 +05:30
parent fb8ff37d83
commit 60c3d41c8e
4 changed files with 141 additions and 10 deletions

View File

@ -5,6 +5,7 @@ import { requestUrlChanged, updateRequestMethod } from 'providers/ReduxStore/sli
import HttpMethodSelector from './HttpMethodSelector';
import { useTheme } from 'providers/Theme';
import SendIcon from 'components/Icons/Send';
import SingleLineEditor from 'components/SingleLineEditor';
import StyledWrapper from './StyledWrapper';
const QueryUrl = ({ item, collection, handleRun }) => {
@ -39,15 +40,10 @@ const QueryUrl = ({ item, collection, handleRun }) => {
<HttpMethodSelector method={method} onMethodSelect={onMethodSelect} />
</div>
<div className="flex items-center flex-grow input-container h-full">
<input
className="px-3 w-full mousetrap"
type="text"
value={url}
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
onChange={(event) => onUrlChange(event.target.value)}
<SingleLineEditor
value={url}
onChange={(newValue) => onUrlChange(newValue)}
collection={collection}
/>
<div className="flex items-center h-full mr-2 cursor-pointer" id="send-request" onClick={handleRun}>
<SendIcon color={theme.requestTabPanel.url.icon} width={22}/>

View File

@ -0,0 +1,33 @@
import styled from 'styled-components';
const StyledWrapper = styled.div`
width: 100%;
height: 30px;
overflow-y: hidden;
.CodeMirror {
background: transparent;
height: 30px;
font-size: 14px;
line-height: 30px;
.CodeMirror-lines {
padding: 0;
}
.CodeMirror-cursor {
height: 20px !important;
margin-top: 5px !important;
}
pre {
font-family: Inter, sans-serif !important;
}
}
.cm-variable-valid{color: green}
.cm-variable-invalid{color: red}
.cm-matchhighlight {background-color: yellow}
`;
export default StyledWrapper;

View File

@ -0,0 +1,103 @@
import React, { Component } from 'react';
import CodeMirror from 'codemirror';
import each from 'lodash/each';
import isEqual from 'lodash/isEqual';
import { findEnvironmentInCollection } from 'utils/collections';
import StyledWrapper from './StyledWrapper';
class SingleLineEditor extends Component {
constructor(props) {
super(props);
this.editorRef = React.createRef();
this.variables = {};
}
componentDidMount() {
// Initialize CodeMirror as a single line editor
this.editor = CodeMirror(this.editorRef.current, {
lineWrapping: false,
lineNumbers: false,
autofocus: true,
mode: "brunovariables",
extraKeys: {
"Enter": () => {},
"Ctrl-Enter": () => {},
"Cmd-Enter": () => {},
"Alt-Enter": () => {},
"Shift-Enter": () => {}
},
});
this.editor.setValue(this.props.value)
this.editor.on('change', (cm) => {
this.props.onChange(cm.getValue());
});
this.addOverlay();
}
componentDidUpdate(prevProps) {
let variables = this.getEnvironmentVariables();
if (!isEqual(variables, this.variables)) {
this.addOverlay();
}
}
componentWillUnmount() {
this.editor.getWrapperElement().remove();
}
getEnvironmentVariables = () => {
let variables = {};
const collection = this.props.collection;
if (collection) {
const environment = findEnvironmentInCollection(collection, collection.activeEnvironmentUid);
if (environment) {
each(environment.variables, (variable) => {
if(variable.name && variable.value && variable.enabled) {
variables[variable.name] = variable.value;
}
});
}
}
return variables;
}
addOverlay = () => {
let variables = this.getEnvironmentVariables();
this.variables = variables;
CodeMirror.defineMode("brunovariables", function(config, parserConfig) {
let variablesOverlay = {
token: function(stream, state) {
if (stream.match("{{", true)) {
let ch;
let word = "";
while ((ch = stream.next()) != null) {
if (ch == "}" && stream.next() == "}") {
stream.eat("}");
if (word in variables) {
return "variable-valid";
} else {
return "variable-invalid";
}
}
word += ch;
}
}
while (stream.next() != null && !stream.match("{{", false)) {}
return null;
}
};
return CodeMirror.overlayMode(CodeMirror.getMode(config, parserConfig.backdrop || "text/plain"), variablesOverlay);
});
this.editor.setOption('mode', 'brunovariables');
}
render() {
return (
<StyledWrapper ref={this.editorRef} className="single-line-editor"></StyledWrapper>
);
}
}
export default SingleLineEditor;

View File

@ -6,7 +6,6 @@ import RequestTabPanel from 'components/RequestTabPanel';
import Sidebar from 'components/Sidebar';
import { useSelector } from 'react-redux';
import StyledWrapper from './StyledWrapper';
import 'codemirror/lib/codemirror.css';
import 'codemirror/theme/material.css';
import 'codemirror/theme/monokai.css';