mirror of
https://github.com/usebruno/bruno.git
synced 2025-06-21 12:33:34 +02:00
Added properties to collections
This commit is contained in:
parent
f8f38802a9
commit
36d6d115d4
@ -0,0 +1,40 @@
|
|||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const StyledWrapper = styled.div`
|
||||||
|
div.method-selector-container {
|
||||||
|
border: solid 1px ${(props) => props.theme.modal.input.border};
|
||||||
|
border-right: none;
|
||||||
|
background-color: ${(props) => props.theme.modal.input.bg};
|
||||||
|
border-top-left-radius: 3px;
|
||||||
|
border-bottom-left-radius: 3px;
|
||||||
|
|
||||||
|
.method-selector {
|
||||||
|
min-width: 80px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div.method-selector-container,
|
||||||
|
div.input-container {
|
||||||
|
background-color: ${(props) => props.theme.modal.input.bg};
|
||||||
|
height: 2.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.input-container {
|
||||||
|
border: solid 1px ${(props) => props.theme.modal.input.border};
|
||||||
|
border-top-right-radius: 3px;
|
||||||
|
border-bottom-right-radius: 3px;
|
||||||
|
|
||||||
|
input {
|
||||||
|
background-color: ${(props) => props.theme.modal.input.bg};
|
||||||
|
outline: none;
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default StyledWrapper;
|
@ -1,5 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Modal from 'components/Modal';
|
import Modal from 'components/Modal';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useFormik } from 'formik';
|
||||||
|
import * as Yup from 'yup';
|
||||||
|
import StyledWrapper from './StyledWrapper';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
|
import { updateCollectionProperties } from 'providers/ReduxStore/slices/collections/actions';
|
||||||
|
|
||||||
function countRequests(items) {
|
function countRequests(items) {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
@ -21,29 +28,116 @@ function countRequests(items) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const CollectionProperties = ({ collection, onClose }) => {
|
const CollectionProperties = ({ collection, onClose }) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const {
|
||||||
|
brunoConfig: { properties: defaultProperties = {} }
|
||||||
|
} = collection;
|
||||||
|
const formik = useFormik({
|
||||||
|
enableReinitialize: true,
|
||||||
|
initialValues: {
|
||||||
|
defaultType: defaultProperties.defaultType || 'http-request',
|
||||||
|
defaultUrl: defaultProperties.defaultUrl || ''
|
||||||
|
},
|
||||||
|
onSubmit: (newProperties) => {
|
||||||
|
dispatch(updateCollectionProperties(newProperties, collection.uid));
|
||||||
|
toast.success('Collection properties updated');
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = () => formik.handleSubmit();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal size="sm" title="Collection Properties" hideFooter={true} handleCancel={onClose}>
|
<StyledWrapper>
|
||||||
<table className="w-full border-collapse">
|
<Modal
|
||||||
<tbody>
|
size="sm"
|
||||||
<tr className="">
|
title="Collection Properties"
|
||||||
<td className="py-2 px-2 text-right">Name :</td>
|
confirmText="Update"
|
||||||
<td className="py-2 px-2">{collection.name}</td>
|
handleConfirm={onSubmit}
|
||||||
</tr>
|
handleCancel={onClose}
|
||||||
<tr className="">
|
>
|
||||||
<td className="py-2 px-2 text-right">Location :</td>
|
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
||||||
<td className="py-2 px-2 break-all">{collection.pathname}</td>
|
<table className="w-full border-collapse">
|
||||||
</tr>
|
<tbody>
|
||||||
<tr className="">
|
<tr className="">
|
||||||
<td className="py-2 px-2 text-right">Environments :</td>
|
<td className="py-2 px-2 text-right">Name :</td>
|
||||||
<td className="py-2 px-2">{collection.environments?.length || 0}</td>
|
<td className="py-2 px-2">{collection.name}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr className="">
|
<tr className="">
|
||||||
<td className="py-2 px-2 text-right">Requests :</td>
|
<td className="py-2 px-2 text-right">Location :</td>
|
||||||
<td className="py-2 px-2">{countRequests(collection.items)}</td>
|
<td className="py-2 px-2 break-all">{collection.pathname}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
<tr className="">
|
||||||
</table>
|
<td className="py-2 px-2 text-right">Environments :</td>
|
||||||
</Modal>
|
<td className="py-2 px-2">{collection.environments?.length || 0}</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="">
|
||||||
|
<td className="py-2 px-2 text-right">Requests :</td>
|
||||||
|
<td className="py-2 px-2">{countRequests(collection.items)}</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="">
|
||||||
|
<td className="py-2 px-2 text-right">Default Request Type :</td>
|
||||||
|
<td className="py-2 px-2">
|
||||||
|
<div className="flex items-center mt-2">
|
||||||
|
<input
|
||||||
|
id="http-request"
|
||||||
|
className="cursor-pointer"
|
||||||
|
type="radio"
|
||||||
|
name="defaultType"
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
value="http-request"
|
||||||
|
checked={formik.values.defaultType === 'http-request'}
|
||||||
|
/>
|
||||||
|
<label htmlFor="http-request" className="ml-1 cursor-pointer select-none">
|
||||||
|
HTTP
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input
|
||||||
|
id="graphql-request"
|
||||||
|
className="ml-4 cursor-pointer"
|
||||||
|
type="radio"
|
||||||
|
name="defaultType"
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
value="graphql-request"
|
||||||
|
checked={formik.values.defaultType === 'graphql-request'}
|
||||||
|
/>
|
||||||
|
<label htmlFor="graphql-request" className="ml-1 cursor-pointer select-none">
|
||||||
|
GraphQL
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="">
|
||||||
|
<td className="py-2 px-2 text-right">Default Base URL :</td>
|
||||||
|
<td className="py-2 px-2">
|
||||||
|
<div className="flex items-center mt-2 ">
|
||||||
|
<div className="flex items-center flex-grow input-container h-full">
|
||||||
|
<input
|
||||||
|
id="request-url"
|
||||||
|
type="text"
|
||||||
|
name="defaultUrl"
|
||||||
|
className="px-3 w-full "
|
||||||
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
value={formik.values.defaultUrl || ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div className="mt-4">
|
||||||
|
{formik.touched.defaultUrl && formik.errors.defaultUrl ? (
|
||||||
|
<div className="text-red-500">{formik.errors.defaultUrl}</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Modal>
|
||||||
|
</StyledWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,12 +15,15 @@ import StyledWrapper from './StyledWrapper';
|
|||||||
const NewRequest = ({ collection, item, isEphemeral, onClose }) => {
|
const NewRequest = ({ collection, item, isEphemeral, onClose }) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const inputRef = useRef();
|
const inputRef = useRef();
|
||||||
|
const {
|
||||||
|
brunoConfig: { properties: collectionProperties = {} }
|
||||||
|
} = collection;
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
enableReinitialize: true,
|
enableReinitialize: true,
|
||||||
initialValues: {
|
initialValues: {
|
||||||
requestName: '',
|
requestName: '',
|
||||||
requestType: 'http-request',
|
requestType: collectionProperties.defaultType || 'http-request',
|
||||||
requestUrl: '',
|
requestUrl: collectionProperties.defaultUrl || '',
|
||||||
requestMethod: 'GET'
|
requestMethod: 'GET'
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object({
|
validationSchema: Yup.object({
|
||||||
|
@ -18,6 +18,7 @@ import { updatePreferences } from 'providers/ReduxStore/slices/app';
|
|||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import { openCollectionEvent, collectionAddEnvFileEvent } from 'providers/ReduxStore/slices/collections/actions';
|
import { openCollectionEvent, collectionAddEnvFileEvent } from 'providers/ReduxStore/slices/collections/actions';
|
||||||
import { isElectron } from 'utils/common/platform';
|
import { isElectron } from 'utils/common/platform';
|
||||||
|
import { collectionPropertiesUpdatedEvent } from 'providers/ReduxStore/slices/collections/index';
|
||||||
|
|
||||||
const useIpcEvents = () => {
|
const useIpcEvents = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@ -107,6 +108,10 @@ const useIpcEvents = () => {
|
|||||||
dispatch(collectionRenamedEvent(val));
|
dispatch(collectionRenamedEvent(val));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const removeCollectionPropertiesUpdatedListener = ipcRenderer.on('main:collection-properties-updated', (val) => {
|
||||||
|
dispatch(collectionPropertiesUpdatedEvent(val));
|
||||||
|
});
|
||||||
|
|
||||||
const removeRunFolderEventListener = ipcRenderer.on('main:run-folder-event', (val) => {
|
const removeRunFolderEventListener = ipcRenderer.on('main:run-folder-event', (val) => {
|
||||||
dispatch(runFolderEvent(val));
|
dispatch(runFolderEvent(val));
|
||||||
});
|
});
|
||||||
@ -138,6 +143,7 @@ const useIpcEvents = () => {
|
|||||||
removeDisplayErrorListener();
|
removeDisplayErrorListener();
|
||||||
removeScriptEnvUpdateListener();
|
removeScriptEnvUpdateListener();
|
||||||
removeCollectionRenamedListener();
|
removeCollectionRenamedListener();
|
||||||
|
removeCollectionPropertiesUpdatedListener();
|
||||||
removeRunFolderEventListener();
|
removeRunFolderEventListener();
|
||||||
removeRunRequestEventListener();
|
removeRunRequestEventListener();
|
||||||
removeProcessEnvUpdatesListener();
|
removeProcessEnvUpdatesListener();
|
||||||
|
@ -47,6 +47,22 @@ import { resolveRequestFilename } from 'utils/common/platform';
|
|||||||
import { parseQueryParams, splitOnFirst } from 'utils/url/index';
|
import { parseQueryParams, splitOnFirst } from 'utils/url/index';
|
||||||
import { each } from 'lodash';
|
import { each } from 'lodash';
|
||||||
|
|
||||||
|
export const updateCollectionProperties = (newProperties, collectionUid) => (dispatch, getState) => {
|
||||||
|
const state = getState();
|
||||||
|
const collection = findCollectionByUid(state.collections.collections, collectionUid);
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!collection) {
|
||||||
|
return reject(new Error('Collection not found'));
|
||||||
|
}
|
||||||
|
|
||||||
|
ipcRenderer
|
||||||
|
.invoke('renderer:update-collection-properties', newProperties, collection.pathname)
|
||||||
|
.then(resolve)
|
||||||
|
.catch(reject);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const renameCollection = (newName, collectionUid) => (dispatch, getState) => {
|
export const renameCollection = (newName, collectionUid) => (dispatch, getState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const collection = findCollectionByUid(state.collections.collections, collectionUid);
|
const collection = findCollectionByUid(state.collections.collections, collectionUid);
|
||||||
|
@ -1224,6 +1224,14 @@ export const collectionsSlice = createSlice({
|
|||||||
collection.name = newName;
|
collection.name = newName;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
collectionPropertiesUpdatedEvent: (state, action) => {
|
||||||
|
const { collectionPathname, newProperties } = action.payload;
|
||||||
|
const collection = findCollectionByPathname(state.collections, collectionPathname);
|
||||||
|
|
||||||
|
if (collection) {
|
||||||
|
collection.properties = newProperties;
|
||||||
|
}
|
||||||
|
},
|
||||||
resetRunResults: (state, action) => {
|
resetRunResults: (state, action) => {
|
||||||
const { collectionUid } = action.payload;
|
const { collectionUid } = action.payload;
|
||||||
const collection = findCollectionByUid(state.collections, collectionUid);
|
const collection = findCollectionByUid(state.collections, collectionUid);
|
||||||
@ -1427,6 +1435,7 @@ export const {
|
|||||||
collectionUnlinkDirectoryEvent,
|
collectionUnlinkDirectoryEvent,
|
||||||
collectionAddEnvFileEvent,
|
collectionAddEnvFileEvent,
|
||||||
collectionRenamedEvent,
|
collectionRenamedEvent,
|
||||||
|
collectionPropertiesUpdatedEvent,
|
||||||
resetRunResults,
|
resetRunResults,
|
||||||
runRequestEvent,
|
runRequestEvent,
|
||||||
runFolderEvent,
|
runFolderEvent,
|
||||||
|
@ -94,6 +94,28 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// update collection properties
|
||||||
|
ipcMain.handle('renderer:update-collection-properties', async (event, newProperties, collectionPathname) => {
|
||||||
|
try {
|
||||||
|
const brunoJsonFilePath = path.join(collectionPathname, 'bruno.json');
|
||||||
|
const content = fs.readFileSync(brunoJsonFilePath, 'utf8');
|
||||||
|
const json = JSON.parse(content);
|
||||||
|
|
||||||
|
json.properties = newProperties;
|
||||||
|
|
||||||
|
const newContent = await stringifyJson(json);
|
||||||
|
await writeFile(brunoJsonFilePath, newContent);
|
||||||
|
|
||||||
|
// fire an event in renderer to change the collection properties
|
||||||
|
mainWindow.webContents.send('main:collection-properties-updated', {
|
||||||
|
collectionPathname,
|
||||||
|
newProperties
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ipcMain.handle('renderer:save-collection-root', async (event, collectionPathname, collectionRoot) => {
|
ipcMain.handle('renderer:save-collection-root', async (event, collectionPathname, collectionRoot) => {
|
||||||
try {
|
try {
|
||||||
const collectionBruFilePath = path.join(collectionPathname, 'collection.bru');
|
const collectionBruFilePath = path.join(collectionPathname, 'collection.bru');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user