-
Query
-
-
-
- Name |
- Value |
- |
-
-
-
+ Query
+
+
+
{queryParams && queryParams.length
- ? queryParams.map((param, index) => {
- return (
-
-
+ ? queryParams.map((param, index) => (
+ |
+
+ handleQueryParamChange(e, param, 'name')}
+ />
+ |
+
+ handleQueryParamChange({ target: { value: newValue } }, param, 'value')}
+ onRun={handleRun}
+ collection={collection}
+ variablesAutocomplete={true}
+ />
+ |
+
+
handleQueryParamChange(e, param, 'name')}
+ type="checkbox"
+ checked={param.enabled}
+ tabIndex="-1"
+ className="mr-3 mousetrap"
+ onChange={(e) => handleQueryParamChange(e, param, 'enabled')}
/>
- |
-
-
- handleQueryParamChange(
- {
- target: {
- value: newValue
- }
- },
- param,
- 'value'
- )
- }
- onRun={handleRun}
- collection={collection}
- item={item}
- />
- |
-
-
- handleQueryParamChange(e, param, 'enabled')}
- />
-
-
- |
-
- );
- })
+
+
+
+
+ ))
: null}
-
-
+
+
+
diff --git a/packages/bruno-app/src/components/Table/StyledWrapper.js b/packages/bruno-app/src/components/Table/StyledWrapper.js
new file mode 100644
index 000000000..e35f11b3a
--- /dev/null
+++ b/packages/bruno-app/src/components/Table/StyledWrapper.js
@@ -0,0 +1,63 @@
+import styled from 'styled-components';
+
+const StyledWrapper = styled.div`
+ table {
+ width: 100%;
+ display: grid;
+ overflow-y: hidden;
+ overflow-x: auto;
+
+ // for icon hover
+ position: inherit;
+ left: -4px;
+ padding-left: 4px;
+ padding-right: 4px;
+
+ grid-template-columns: ${({ columns }) =>
+ columns?.[0]?.width
+ ? columns.map((col) => `${col?.width}`).join(' ')
+ : columns.map((col) => `${100 / columns.length}%`).join(' ')};
+ }
+
+ table thead,
+ table tbody,
+ table tr {
+ display: contents;
+ }
+
+ table th {
+ position: relative;
+ }
+
+ table tr td {
+ padding: 0.5rem;
+ text-align: left;
+ border-top: 1px solid ${(props) => props.theme.collection.environment.settings.gridBorder}77;
+ border-right: 1px solid ${(props) => props.theme.collection.environment.settings.gridBorder}77;
+ }
+
+ tr {
+ transition: transform 0.2s ease-in-out;
+ }
+
+ tr.dragging {
+ opacity: 0.5;
+ }
+
+ tr.hovered {
+ transform: translateY(10px); /* Adjust the value as needed for the animation effect */
+ }
+
+ table tr th {
+ padding: 0.5rem;
+ text-align: left;
+ border-top: 1px solid ${(props) => props.theme.collection.environment.settings.gridBorder}77;
+ border-right: 1px solid ${(props) => props.theme.collection.environment.settings.gridBorder}77;
+
+ &:nth-child(1) {
+ border-left: 1px solid ${(props) => props.theme.collection.environment.settings.gridBorder}77;
+ }
+ }
+`;
+
+export default StyledWrapper;
diff --git a/packages/bruno-app/src/components/Table/index.js b/packages/bruno-app/src/components/Table/index.js
new file mode 100644
index 000000000..80bfb19f3
--- /dev/null
+++ b/packages/bruno-app/src/components/Table/index.js
@@ -0,0 +1,110 @@
+import { useState, useRef, useEffect, useCallback } from 'react';
+import StyledWrapper from './StyledWrapper';
+
+const Table = ({ minColumnWidth = 1, headers = [], children }) => {
+ const [activeColumnIndex, setActiveColumnIndex] = useState(null);
+ const tableRef = useRef(null);
+
+ const columns = headers?.map((item) => ({
+ ...item,
+ ref: useRef()
+ }));
+
+ const updateDivHeights = () => {
+ if (tableRef.current) {
+ const height = tableRef.current.offsetHeight;
+ columns.forEach((col) => {
+ if (col.ref.current) {
+ col.ref.current.querySelector('.resizer').style.height = `${height}px`;
+ }
+ });
+ }
+ };
+
+ useEffect(() => {
+ updateDivHeights();
+ window.addEventListener('resize', updateDivHeights);
+
+ return () => {
+ window.removeEventListener('resize', updateDivHeights);
+ };
+ }, [columns]);
+
+ useEffect(() => {
+ if (tableRef.current) {
+ const observer = new MutationObserver(updateDivHeights);
+ observer.observe(tableRef.current, { childList: true, subtree: true });
+
+ return () => {
+ observer.disconnect();
+ };
+ }
+ }, [columns]);
+
+ const handleMouseDown = (index) => (e) => {
+ setActiveColumnIndex(index);
+ };
+
+ const handleMouseMove = useCallback(
+ (e) => {
+ const gridColumns = columns.map((col, i) => {
+ if (i === activeColumnIndex) {
+ const width = e.clientX - col.ref?.current?.getBoundingClientRect()?.left;
+
+ if (width >= minColumnWidth) {
+ return `${width}px`;
+ }
+ }
+ return `${col.ref.current.offsetWidth}px`;
+ });
+
+ tableRef.current.style.gridTemplateColumns = `${gridColumns.join(' ')}`;
+ },
+ [activeColumnIndex, columns, minColumnWidth]
+ );
+
+ const handleMouseUp = useCallback(() => {
+ setActiveColumnIndex(null);
+ removeListeners();
+ }, [removeListeners]);
+
+ const removeListeners = useCallback(() => {
+ window.removeEventListener('mousemove', handleMouseMove);
+ window.removeEventListener('mouseup', removeListeners);
+ }, [handleMouseMove]);
+
+ useEffect(() => {
+ if (activeColumnIndex !== null) {
+ window.addEventListener('mousemove', handleMouseMove);
+ window.addEventListener('mouseup', handleMouseUp);
+ }
+ return () => {
+ removeListeners();
+ };
+ }, [activeColumnIndex, handleMouseMove, handleMouseUp, removeListeners]);
+
+ return (
+
+
+
+
+
+ {columns.map(({ ref, name }, i) => (
+
+ {name}
+
+ |
+ ))}
+
+
+ {children}
+
+
+
+ );
+};
+
+export default Table;
diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
index 63e49360c..e8fb4d602 100644
--- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
+++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
@@ -503,6 +503,39 @@ export const collectionsSlice = createSlice({
}
}
},
+
+ moveQueryParam: (state, action) => {
+ const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
+
+ if (collection) {
+ const item = findItemInCollection(collection, action.payload.itemUid);
+
+ if (item && isItemARequest(item)) {
+ // Ensure item.draft is a deep clone of item if not already present
+ if (!item.draft) {
+ item.draft = cloneDeep(item);
+ }
+
+ // Extract payload data
+ const { updateReorderedItem } = action.payload;
+ const params = item.draft.request.params;
+
+ item.draft.request.params = updateReorderedItem.map((uid) => {
+ return params.find((param) => param.uid === uid);
+ });
+
+ // update request url
+ const parts = splitOnFirst(item.draft.request.url, '?');
+ const query = stringifyQueryParams(filter(item.draft.request.params, (p) => p.enabled && p.type === 'query'));
+ if (query && query.length) {
+ item.draft.request.url = parts[0] + '?' + query;
+ } else {
+ item.draft.request.url = parts[0];
+ }
+ }
+ }
+ },
+
updateQueryParam: (state, action) => {
const collection = findCollectionByUid(state.collections, action.payload.collectionUid);
@@ -1720,6 +1753,7 @@ export const {
requestUrlChanged,
updateAuth,
addQueryParam,
+ moveQueryParam,
updateQueryParam,
deleteQueryParam,
updatePathParam,