feat: refactored logic around query param parsing

This commit is contained in:
Anoop M D 2023-02-01 06:07:43 +05:30 committed by Anoop M D
parent 8bfb2591c2
commit 6852cc6631
6 changed files with 92 additions and 18 deletions

View File

@ -7,6 +7,7 @@
"build": "next build && next export", "build": "next build && next export",
"start": "next start", "start": "next start",
"lint": "next lint", "lint": "next lint",
"test": "jest",
"prettier": "prettier --write \"./src/**/*.{js,jsx,json,ts,tsx}\"" "prettier": "prettier --write \"./src/**/*.{js,jsx,json,ts,tsx}\""
}, },
"dependencies": { "dependencies": {

View File

@ -160,12 +160,12 @@ export default class QueryEditor extends React.Component {
if (this.props.theme !== prevProps.theme && this.editor) { if (this.props.theme !== prevProps.theme && this.editor) {
this.editor.setOption('theme', this.props.theme === 'dark' ? 'monokai' : 'default'); this.editor.setOption('theme', this.props.theme === 'dark' ? 'monokai' : 'default');
} }
this.ignoreChangeEvent = false;
let variables = getEnvironmentVariables(this.props.collection); let variables = getEnvironmentVariables(this.props.collection);
if (!isEqual(variables, this.variables)) { if (!isEqual(variables, this.variables)) {
this.editor.options.brunoVarInfo.variables = variables; this.editor.options.brunoVarInfo.variables = variables;
this.addOverlay(); this.addOverlay();
} }
this.ignoreChangeEvent = false;
} }
componentWillUnmount() { componentWillUnmount() {

View File

@ -1,13 +1,14 @@
import styled from 'styled-components'; import styled from 'styled-components';
const StyledWrapper = styled.div` const StyledWrapper = styled.div`
width: 100%;
height: 30px; height: 30px;
overflow-y: hidden; overflow-y: hidden;
overflow-x: hidden; overflow-x: hidden;
.CodeMirror { .CodeMirror {
background: transparent; background: transparent;
height: 30px; height: 34px;
font-size: 14px; font-size: 14px;
line-height: 30px; line-height: 30px;
overflow: hidden; overflow: hidden;
@ -16,6 +17,10 @@ const StyledWrapper = styled.div`
display: none !important; display: none !important;
} }
.CodeMirror-scroll {
overflow: hidden !important;
}
.CodeMirror-hscrollbar { .CodeMirror-hscrollbar {
display: none !important; display: none !important;
} }

View File

@ -14,6 +14,10 @@ if (!SERVER_RENDERED) {
class SingleLineEditor extends Component { class SingleLineEditor extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
// Keep a cached version of the value, this cache will be updated when the
// editor is updated, which can later be used to protect the editor from
// unnecessary updates during the update lifecycle.
this.cachedValue = props.value || '';
this.editorRef = React.createRef(); this.editorRef = React.createRef();
this.variables = {}; this.variables = {};
} }
@ -68,14 +72,26 @@ class SingleLineEditor extends Component {
'Tab': () => {} 'Tab': () => {}
}, },
}); });
this.editor.setValue(this.props.value); this.editor.setValue(this.props.value || '');
this.editor.on('change', (cm) => { this.editor.on('change', this._onEdit);
this.props.onChange(cm.getValue());
});
this.addOverlay(); this.addOverlay();
} }
_onEdit = () => {
if (!this.ignoreChangeEvent && this.editor) {
this.cachedValue = this.editor.getValue();
if (this.props.onChange) {
this.props.onChange(this.cachedValue);
}
}
};
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
// Ensure the changes caused by this update are not interpretted as
// user-input changes which could otherwise result in an infinite
// event loop.
this.ignoreChangeEvent = true;
let variables = getEnvironmentVariables(this.props.collection); let variables = getEnvironmentVariables(this.props.collection);
if (!isEqual(variables, this.variables)) { if (!isEqual(variables, this.variables)) {
this.editor.options.brunoVarInfo.variables = variables; this.editor.options.brunoVarInfo.variables = variables;
@ -84,6 +100,11 @@ class SingleLineEditor extends Component {
if (this.props.theme !== prevProps.theme && this.editor) { if (this.props.theme !== prevProps.theme && this.editor) {
this.editor.setOption('theme', this.props.theme === 'dark' ? 'monokai' : 'default'); this.editor.setOption('theme', this.props.theme === 'dark' ? 'monokai' : 'default');
} }
if (this.props.value !== prevProps.value && this.props.value !== this.cachedValue && this.editor) {
this.cachedValue = this.props.value;
this.editor.setValue(this.props.value);
}
this.ignoreChangeEvent = false;
} }
componentWillUnmount() { componentWillUnmount() {

View File

@ -1,25 +1,29 @@
import isEmpty from 'lodash/isEmpty'; import isEmpty from 'lodash/isEmpty';
import trim from 'lodash/trim'; import trim from 'lodash/trim';
import each from 'lodash/each'; import each from 'lodash/each';
import splitOnFirst from 'split-on-first'; import filter from 'lodash/filter';
const hasLength = (str) => {
if(!str || !str.length) {
return false;
}
str = str.trim();
return str.length > 0;
};
export const parseQueryParams = (query) => { export const parseQueryParams = (query) => {
if (!query || !query.length) { if (!query || !query.length) {
return []; return [];
} }
let params = query.split('&'); let params = query.split('&').map(param => {
let result = []; let [name, value = ''] = param.split('=');
return { name, value };
});
for (let i = 0; i < params.length; i++) { return filter(params, (p) => hasLength(p.name));
let pair = splitOnFirst(params[i], '=');
result.push({
name: pair[0],
value: pair[1]
});
}
return result;
}; };
export const stringifyQueryParams = (params) => { export const stringifyQueryParams = (params) => {

View File

@ -0,0 +1,43 @@
import { parseQueryParams } from './index';
describe('Url Utils - parseQueryParams', () => {
it('should parse query - case 1', () => {
const params = parseQueryParams("");
expect(params).toEqual([]);
});
it('should parse query - case 2', () => {
const params = parseQueryParams("a");
expect(params).toEqual([{name: 'a', value: ''}]);
});
it('should parse query - case 3', () => {
const params = parseQueryParams("a=");
expect(params).toEqual([{name: 'a', value: ''}]);
});
it('should parse query - case 4', () => {
const params = parseQueryParams("a=1");
expect(params).toEqual([{name: 'a', value: '1'}]);
});
it('should parse query - case 5', () => {
const params = parseQueryParams("a=1&");
expect(params).toEqual([{name: 'a', value: '1'}]);
});
it('should parse query - case 6', () => {
const params = parseQueryParams("a=1&b");
expect(params).toEqual([{name: 'a', value: '1'}, {name: 'b', value: ''}]);
});
it('should parse query - case 7', () => {
const params = parseQueryParams("a=1&b=");
expect(params).toEqual([{name: 'a', value: '1'}, {name: 'b', value: ''}]);
});
it('should parse query - case 8', () => {
const params = parseQueryParams("a=1&b=2");
expect(params).toEqual([{name: 'a', value: '1'}, {name: 'b', value: '2'}]);
});
});