Skip to content

Commit 02583e0

Browse files
authored
Merge pull request #53 from sergptz/feature/buttons_to_load_json_files
Added buttons to load params, headers or body from a JSON file
2 parents 562acc2 + 8ae4f7f commit 02583e0

File tree

7 files changed

+148
-6
lines changed

7 files changed

+148
-6
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { render } from "@testing-library/react";
2+
import React from "react";
3+
4+
import LoadButtonsBlock from "../components/LoadButtonsBlock";
5+
import { COMMON } from "../constants";
6+
7+
describe("LoadButtonsBlock component test", () => {
8+
it("should render text correctly", () => {
9+
const { getByText } = render(<LoadButtonsBlock optionsType={COMMON.HEADERS} />);
10+
11+
expect(getByText(/Set data from file/i)).toBeInTheDocument();
12+
expect(getByText(/Add data from file/i)).toBeInTheDocument();
13+
});
14+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { render } from "@testing-library/react";
2+
import React from "react";
3+
4+
import { COMMON } from "../constants";
5+
import LoadJSONFileButton from "../features/Request/Button/LoadJSONFileButton";
6+
7+
describe("LoadJSONFileButton component test", () => {
8+
it("should render text correctly", () => {
9+
const { getByText } = render(<LoadJSONFileButton optionsType={COMMON.HEADERS} />);
10+
expect(getByText(/Add data from file/i)).toBeInTheDocument();
11+
});
12+
13+
it("should render text correctly when 'replaceValues' prop is true", () => {
14+
const { getByText } = render(<LoadJSONFileButton optionsType={COMMON.HEADERS} replaceValues={true} />);
15+
expect(getByText(/Set data from file/i)).toBeInTheDocument();
16+
});
17+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import PropTypes from "prop-types";
2+
import React from "react";
3+
import styled from "styled-components";
4+
5+
import LoadJSONFileButton from "../../webview/features/Request/Button/LoadJSONFileButton";
6+
import { COMMON, REQUEST } from "../constants";
7+
8+
const LoadButtonsBlock = ({
9+
optionsType,
10+
}) => (
11+
<ButtonsWrapper>
12+
<LoadJSONFileButton optionsType={optionsType} />
13+
<LoadJSONFileButton optionsType={optionsType} replaceValues={true} />
14+
</ButtonsWrapper>
15+
)
16+
;
17+
18+
LoadButtonsBlock.propTypes = {
19+
optionsType: PropTypes.oneOf([COMMON.HEADERS, REQUEST.PARAMS, REQUEST.FORM_DATA, REQUEST.FORM_URLENCODED]),
20+
replaceValues: PropTypes.bool,
21+
};
22+
23+
const ButtonsWrapper = styled.div`
24+
display: flex;
25+
flex-direction: row;
26+
justify-content: end;
27+
margin-right: 25px;
28+
`;
29+
30+
export default LoadButtonsBlock;

webview/features/Request/Body/RequestBodySelectMenuOption.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from "react";
22
import shallow from "zustand/shallow";
33

4+
import LoadButtonsBlock from "../../../components/LoadButtonsBlock";
45
import { HEIGHT, OPTION, REQUEST } from "../../../constants";
56
import CodeEditor from "../../../shared/CodeEditor";
67
import KeyValueTable from "../../../shared/KeyValueTable";
@@ -48,11 +49,14 @@ const RequestBodySelectMenuOption = () => {
4849
case REQUEST.FORM_DATA:
4950
case REQUEST.FORM_URLENCODED:
5051
return (
51-
<KeyValueTable
52-
type={bodyOption}
53-
title={bodyOption}
54-
{...keyValueProps}
55-
/>
52+
<>
53+
<LoadButtonsBlock optionsType={bodyOption} />
54+
<KeyValueTable
55+
type={bodyOption}
56+
title={bodyOption}
57+
{...keyValueProps}
58+
/>
59+
</>
5660
);
5761
case REQUEST.RAW:
5862
return (
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import PropTypes from "prop-types";
2+
import React from "react";
3+
import shallow from "zustand/shallow";
4+
5+
import Button from "../../../components/Button";
6+
import useStore from "../../../store/useStore";
7+
8+
const LoadJSONFileButton = ({
9+
optionsType,
10+
replaceValues = false,
11+
}) => {
12+
const {
13+
handleFileUpload,
14+
} = useStore(
15+
(state) => ({ handleFileUpload: state.handleFileUpload }),
16+
shallow,
17+
);
18+
19+
async function loadSettingsFromJSONFile(e) {
20+
const config = await readFileJSON(e.target.files.item(0))
21+
handleFileUpload(config, optionsType, replaceValues)
22+
}
23+
24+
async function readFileJSON(file) {
25+
return JSON.parse(await file.text())
26+
}
27+
28+
const fileInput = document.createElement('input')
29+
const inputAttrs = {
30+
hidden: true,
31+
type: 'file',
32+
accept: '.json'
33+
}
34+
for (let attr in inputAttrs) {
35+
fileInput.setAttribute(attr, inputAttrs[attr])
36+
}
37+
fileInput.addEventListener('change', (e) => loadSettingsFromJSONFile(e))
38+
39+
return (
40+
<Button buttonType="submit" handleButtonClick={() => fileInput.click()}>
41+
{ replaceValues ? 'Set data from file' : 'Add data from file'}
42+
</Button>
43+
);
44+
};
45+
46+
LoadJSONFileButton.propTypes = {
47+
optionsType: PropTypes.string,
48+
replaceValues: PropTypes.bool,
49+
};
50+
51+
52+
export default LoadJSONFileButton;

webview/features/Request/Menu/RequestMenuOption.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from "react";
22
import shallow from "zustand/shallow";
33

4+
import LoadButtonsBlock from "../../../components/LoadButtonsBlock";
45
import { COMMON, REQUEST } from "../../../constants";
56
import KeyValueTable from "../../../shared/KeyValueTable";
67
import useStore from "../../../store/useStore";
@@ -30,7 +31,12 @@ const RequestMenuOption = () => {
3031
switch (requestOption) {
3132
case REQUEST.PARAMS:
3233
case COMMON.HEADERS:
33-
return <KeyValueTable type={requestOption} {...keyValueProps} />;
34+
return (
35+
<>
36+
<LoadButtonsBlock optionsType={requestOption} />
37+
<KeyValueTable type={requestOption} {...keyValueProps} />
38+
</>
39+
);
3440
case REQUEST.AUTH:
3541
return <RequestAuthSelectMenu />;
3642
case COMMON.BODY:

webview/store/slices/keyValueTableDataSlice.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,25 @@ const keyValueTableDataSlice = (set) => ({
7272
),
7373
})),
7474

75+
handleFileUpload: (data, optionsType = COMMON.HEADERS, replaceValues) => {
76+
const rows = []
77+
for (let key in data) {
78+
rows.push({
79+
optionType: optionsType,
80+
isChecked: true,
81+
key,
82+
value: data[key],
83+
description: "",
84+
})
85+
}
86+
set((state) => ({
87+
keyValueTableData: [
88+
...(state.keyValueTableData.filter(v => data[v.key] === undefined && (!replaceValues || v.optionType !== optionsType))),
89+
...rows
90+
]
91+
}))
92+
},
93+
7594
handleRequestKey: (dataIndex, detail) =>
7695
set((state) => ({
7796
keyValueTableData: state.keyValueTableData.map((tableData, index) =>

0 commit comments

Comments
 (0)