From c670ae579e698b5c3f24c6671aba2098e41e6453 Mon Sep 17 00:00:00 2001 From: aurmartin Date: Sat, 12 Oct 2024 12:54:44 +0200 Subject: [PATCH] feature: Asserts table resizable and orderable --- .../Assertions/AssertionRow/index.js | 218 --------------- .../RequestPane/Assertions/StyledWrapper.js | 8 - .../RequestPane/Assertions/index.js | 250 ++++++++++++++++-- .../ReduxStore/slices/collections/index.js | 21 ++ 4 files changed, 247 insertions(+), 250 deletions(-) delete mode 100644 packages/bruno-app/src/components/RequestPane/Assertions/AssertionRow/index.js diff --git a/packages/bruno-app/src/components/RequestPane/Assertions/AssertionRow/index.js b/packages/bruno-app/src/components/RequestPane/Assertions/AssertionRow/index.js deleted file mode 100644 index 38250f8ea..000000000 --- a/packages/bruno-app/src/components/RequestPane/Assertions/AssertionRow/index.js +++ /dev/null @@ -1,218 +0,0 @@ -import React from 'react'; -import { IconTrash } from '@tabler/icons'; -import SingleLineEditor from 'components/SingleLineEditor'; -import AssertionOperator from '../AssertionOperator'; -import { useTheme } from 'providers/Theme'; - -/** - * Assertion operators - * - * eq : equal to - * neq : not equal to - * gt : greater than - * gte : greater than or equal to - * lt : less than - * lte : less than or equal to - * in : in - * notIn : not in - * contains : contains - * notContains : not contains - * length : length - * matches : matches - * notMatches : not matches - * startsWith : starts with - * endsWith : ends with - * between : between - * isEmpty : is empty - * isNull : is null - * isUndefined : is undefined - * isDefined : is defined - * isTruthy : is truthy - * isFalsy : is falsy - * isJson : is json - * isNumber : is number - * isString : is string - * isBoolean : is boolean - * isArray : is array - */ -const parseAssertionOperator = (str = '') => { - if (!str || typeof str !== 'string' || !str.length) { - return { - operator: 'eq', - value: str - }; - } - - const operators = [ - 'eq', - 'neq', - 'gt', - 'gte', - 'lt', - 'lte', - 'in', - 'notIn', - 'contains', - 'notContains', - 'length', - 'matches', - 'notMatches', - 'startsWith', - 'endsWith', - 'between', - 'isEmpty', - 'isNull', - 'isUndefined', - 'isDefined', - 'isTruthy', - 'isFalsy', - 'isJson', - 'isNumber', - 'isString', - 'isBoolean', - 'isArray' - ]; - - const unaryOperators = [ - 'isEmpty', - 'isNull', - 'isUndefined', - 'isDefined', - 'isTruthy', - 'isFalsy', - 'isJson', - 'isNumber', - 'isString', - 'isBoolean', - 'isArray' - ]; - - const [operator, ...rest] = str.trim().split(' '); - const value = rest.join(' '); - - if (unaryOperators.includes(operator)) { - return { - operator, - value: '' - }; - } - - if (operators.includes(operator)) { - return { - operator, - value - }; - } - - return { - operator: 'eq', - value: str - }; -}; - -const isUnaryOperator = (operator) => { - const unaryOperators = [ - 'isEmpty', - 'isNull', - 'isUndefined', - 'isDefined', - 'isTruthy', - 'isFalsy', - 'isJson', - 'isNumber', - 'isString', - 'isBoolean', - 'isArray' - ]; - - return unaryOperators.includes(operator); -}; - -const AssertionRow = ({ - item, - collection, - assertion, - handleAssertionChange, - handleRemoveAssertion, - onSave, - handleRun -}) => { - const { storedTheme } = useTheme(); - - const { operator, value } = parseAssertionOperator(assertion.value); - - return ( - - - handleAssertionChange(e, assertion, 'name')} - /> - - - - handleAssertionChange( - { - target: { - value: `${op} ${value}` - } - }, - assertion, - 'value' - ) - } - /> - - - {!isUnaryOperator(operator) ? ( - - handleAssertionChange( - { - target: { - value: `${operator} ${newValue}` - } - }, - assertion, - 'value' - ) - } - onRun={handleRun} - collection={collection} - item={item} - /> - ) : ( - - )} - - -
- handleAssertionChange(e, assertion, 'enabled')} - /> - -
- - - ); -}; - -export default AssertionRow; diff --git a/packages/bruno-app/src/components/RequestPane/Assertions/StyledWrapper.js b/packages/bruno-app/src/components/RequestPane/Assertions/StyledWrapper.js index 6f28fee13..b9dfc7f7b 100644 --- a/packages/bruno-app/src/components/RequestPane/Assertions/StyledWrapper.js +++ b/packages/bruno-app/src/components/RequestPane/Assertions/StyledWrapper.js @@ -20,14 +20,6 @@ const Wrapper = styled.div` td { padding: 6px 10px; - &:nth-child(1) { - width: 30%; - } - - &:nth-child(4) { - width: 70px; - } - select { background-color: transparent; } diff --git a/packages/bruno-app/src/components/RequestPane/Assertions/index.js b/packages/bruno-app/src/components/RequestPane/Assertions/index.js index 1805a632e..a8979d4f0 100644 --- a/packages/bruno-app/src/components/RequestPane/Assertions/index.js +++ b/packages/bruno-app/src/components/RequestPane/Assertions/index.js @@ -2,12 +2,142 @@ import React from 'react'; import get from 'lodash/get'; import cloneDeep from 'lodash/cloneDeep'; import { useDispatch } from 'react-redux'; -import { addAssertion, updateAssertion, deleteAssertion } from 'providers/ReduxStore/slices/collections'; +import { IconTrash } from '@tabler/icons'; +import { addAssertion, moveAssertion, updateAssertion, deleteAssertion } from 'providers/ReduxStore/slices/collections'; import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions'; -import AssertionRow from './AssertionRow'; +import { useTheme } from 'providers/Theme'; +import AssertionOperator from './AssertionOperator'; import StyledWrapper from './StyledWrapper'; +import Table from 'components/Table/index'; +import ReorderTable from 'components/ReorderTable/index'; +import SingleLineEditor from 'components/SingleLineEditor'; + +/** + * Assertion operators + * + * eq : equal to + * neq : not equal to + * gt : greater than + * gte : greater than or equal to + * lt : less than + * lte : less than or equal to + * in : in + * notIn : not in + * contains : contains + * notContains : not contains + * length : length + * matches : matches + * notMatches : not matches + * startsWith : starts with + * endsWith : ends with + * between : between + * isEmpty : is empty + * isNull : is null + * isUndefined : is undefined + * isDefined : is defined + * isTruthy : is truthy + * isFalsy : is falsy + * isJson : is json + * isNumber : is number + * isString : is string + * isBoolean : is boolean + * isArray : is array + */ +const parseAssertionOperator = (str = '') => { + if (!str || typeof str !== 'string' || !str.length) { + return { + operator: 'eq', + value: str + }; + } + + const operators = [ + 'eq', + 'neq', + 'gt', + 'gte', + 'lt', + 'lte', + 'in', + 'notIn', + 'contains', + 'notContains', + 'length', + 'matches', + 'notMatches', + 'startsWith', + 'endsWith', + 'between', + 'isEmpty', + 'isNull', + 'isUndefined', + 'isDefined', + 'isTruthy', + 'isFalsy', + 'isJson', + 'isNumber', + 'isString', + 'isBoolean', + 'isArray' + ]; + + const unaryOperators = [ + 'isEmpty', + 'isNull', + 'isUndefined', + 'isDefined', + 'isTruthy', + 'isFalsy', + 'isJson', + 'isNumber', + 'isString', + 'isBoolean', + 'isArray' + ]; + + const [operator, ...rest] = str.trim().split(' '); + const value = rest.join(' '); + + if (unaryOperators.includes(operator)) { + return { + operator, + value: '' + }; + } + + if (operators.includes(operator)) { + return { + operator, + value + }; + } + + return { + operator: 'eq', + value: str + }; +}; + +const isUnaryOperator = (operator) => { + const unaryOperators = [ + 'isEmpty', + 'isNull', + 'isUndefined', + 'isDefined', + 'isTruthy', + 'isFalsy', + 'isJson', + 'isNumber', + 'isString', + 'isBoolean', + 'isArray' + ]; + + return unaryOperators.includes(operator); +}; const Assertions = ({ item, collection }) => { + const { storedTheme } = useTheme(); const dispatch = useDispatch(); const assertions = item.draft ? get(item, 'draft.request.assertions') : get(item, 'request.assertions'); @@ -57,36 +187,108 @@ const Assertions = ({ item, collection }) => { ); }; + const handleAssertionDrag = ({ updateReorderedItem }) => { + dispatch( + moveAssertion({ + collectionUid: collection.uid, + itemUid: item.uid, + updateReorderedItem + }) + ); + }; + return ( - - - - - - - - - - +
ExprOperatorValue
+ {assertions && assertions.length ? assertions.map((assertion) => { + const { operator, value } = parseAssertionOperator(assertion.value); + return ( - + + + + + + ); }) : null} - -
+ handleAssertionChange(e, assertion, 'name')} + /> + + + handleAssertionChange( + { + target: { + value: `${op} ${value}` + } + }, + assertion, + 'value' + ) + } + /> + + {!isUnaryOperator(operator) ? ( + + handleAssertionChange( + { + target: { + value: `${operator} ${newValue}` + } + }, + assertion, + 'value' + ) + } + onRun={handleRun} + collection={collection} + item={item} + /> + ) : ( + + )} + +
+ handleAssertionChange(e, assertion, 'enabled')} + /> + +
+
+ + + 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 b7ef2f86e..725889046 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -986,6 +986,26 @@ export const collectionsSlice = createSlice({ } } }, + moveAssertion: (state, action) => { + const collection = findCollectionByUid(state.collections, action.payload.collectionUid); + + if (collection) { + const item = findItemInCollection(collection, action.payload.itemUid); + + if (item && isItemARequest(item)) { + if (!item.draft) { + item.draft = cloneDeep(item); + } + + const { updateReorderedItem } = action.payload; + const assertions = item.draft.request.assertions; + + item.draft.request.assertions = updateReorderedItem.map((uid) => { + return assertions.find((assertion) => assertion.uid === uid); + }); + } + } + }, updateAssertion: (state, action) => { const collection = findCollectionByUid(state.collections, action.payload.collectionUid); @@ -1790,6 +1810,7 @@ export const { updateRequestTests, updateRequestMethod, addAssertion, + moveAssertion, updateAssertion, deleteAssertion, addVar,