mirror of
https://github.com/usebruno/bruno.git
synced 2025-06-20 11:48:03 +02:00
feat: codemirror single line editor
This commit is contained in:
parent
fb8ff37d83
commit
60c3d41c8e
@ -5,6 +5,7 @@ import { requestUrlChanged, updateRequestMethod } from 'providers/ReduxStore/sli
|
|||||||
import HttpMethodSelector from './HttpMethodSelector';
|
import HttpMethodSelector from './HttpMethodSelector';
|
||||||
import { useTheme } from 'providers/Theme';
|
import { useTheme } from 'providers/Theme';
|
||||||
import SendIcon from 'components/Icons/Send';
|
import SendIcon from 'components/Icons/Send';
|
||||||
|
import SingleLineEditor from 'components/SingleLineEditor';
|
||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
|
||||||
const QueryUrl = ({ item, collection, handleRun }) => {
|
const QueryUrl = ({ item, collection, handleRun }) => {
|
||||||
@ -39,15 +40,10 @@ const QueryUrl = ({ item, collection, handleRun }) => {
|
|||||||
<HttpMethodSelector method={method} onMethodSelect={onMethodSelect} />
|
<HttpMethodSelector method={method} onMethodSelect={onMethodSelect} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center flex-grow input-container h-full">
|
<div className="flex items-center flex-grow input-container h-full">
|
||||||
<input
|
<SingleLineEditor
|
||||||
className="px-3 w-full mousetrap"
|
|
||||||
type="text"
|
|
||||||
value={url}
|
value={url}
|
||||||
autoComplete="off"
|
onChange={(newValue) => onUrlChange(newValue)}
|
||||||
autoCorrect="off"
|
collection={collection}
|
||||||
autoCapitalize="off"
|
|
||||||
spellCheck="false"
|
|
||||||
onChange={(event) => onUrlChange(event.target.value)}
|
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center h-full mr-2 cursor-pointer" id="send-request" onClick={handleRun}>
|
<div className="flex items-center h-full mr-2 cursor-pointer" id="send-request" onClick={handleRun}>
|
||||||
<SendIcon color={theme.requestTabPanel.url.icon} width={22}/>
|
<SendIcon color={theme.requestTabPanel.url.icon} width={22}/>
|
||||||
|
@ -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;
|
103
packages/bruno-app/src/components/SingleLineEditor/index.js
Normal file
103
packages/bruno-app/src/components/SingleLineEditor/index.js
Normal 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;
|
@ -6,7 +6,6 @@ import RequestTabPanel from 'components/RequestTabPanel';
|
|||||||
import Sidebar from 'components/Sidebar';
|
import Sidebar from 'components/Sidebar';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
import 'codemirror/lib/codemirror.css';
|
|
||||||
import 'codemirror/theme/material.css';
|
import 'codemirror/theme/material.css';
|
||||||
import 'codemirror/theme/monokai.css';
|
import 'codemirror/theme/monokai.css';
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user