feat(#95): runner runs inside a tab of a collection view

This commit is contained in:
Anoop M D 2023-09-28 04:02:20 +05:30
parent 487dd73040
commit c27f090583
13 changed files with 109 additions and 126 deletions

View File

@ -120,8 +120,7 @@ const RequestTabPanel = () => {
return <div className="pb-4 px-4">Collection not found!</div>;
}
const showRunner = collection.showRunner;
if (showRunner) {
if (focusedTab.type === 'collection-runner') {
return <RunnerResults collection={collection} />;
}

View File

@ -4,7 +4,6 @@ import { IconFiles, IconRun, IconEye, IconSettings } from '@tabler/icons';
import EnvironmentSelector from 'components/Environments/EnvironmentSelector';
import { addTab } from 'providers/ReduxStore/slices/tabs';
import { useDispatch } from 'react-redux';
import { toggleRunnerView } from 'providers/ReduxStore/slices/collections';
import StyledWrapper from './StyledWrapper';
const CollectionToolBar = ({ collection }) => {
@ -12,8 +11,10 @@ const CollectionToolBar = ({ collection }) => {
const handleRun = () => {
dispatch(
toggleRunnerView({
collectionUid: collection.uid
addTab({
uid: uuid(),
collectionUid: collection.uid,
type: 'collection-runner'
})
);
};

View File

@ -1,5 +1,5 @@
import React from 'react';
import { IconVariable, IconSettings } from '@tabler/icons';
import { IconVariable, IconSettings, IconRun } from '@tabler/icons';
const SpecialTab = ({ handleCloseClick, type }) => {
const getTabInfo = (type) => {
@ -20,6 +20,14 @@ const SpecialTab = ({ handleCloseClick, type }) => {
</>
);
}
case 'collection-runner': {
return (
<>
<IconRun size={18} strokeWidth={1.5} className="text-yellow-600" />
<span className="ml-1">Runner</span>
</>
);
}
}
};

View File

@ -57,7 +57,7 @@ const RequestTab = ({ tab, collection }) => {
return color;
};
if (['collection-settings', 'variables'].includes(tab.type)) {
if (['collection-settings', 'variables', 'collection-runner'].includes(tab.type)) {
return (
<StyledWrapper className="flex items-center justify-between tab-container px-1">
<SpecialTab handleCloseClick={handleCloseClick} type={tab.type} />

View File

@ -76,8 +76,6 @@ const RequestTabs = () => {
});
};
const showRunner = activeCollection && activeCollection.showRunner;
// Todo: Must support ephermal requests
return (
<StyledWrapper className={getRootClassname()}>
@ -87,72 +85,70 @@ const RequestTabs = () => {
{collectionRequestTabs && collectionRequestTabs.length ? (
<>
<CollectionToolBar collection={activeCollection} />
{!showRunner ? (
<div className="flex items-center pl-4">
<ul role="tablist">
{showChevrons ? (
<li className="select-none short-tab" onClick={leftSlide}>
<div className="flex items-center">
<IconChevronLeft size={18} strokeWidth={1.5} />
</div>
</li>
) : null}
{/* Moved to post mvp */}
{/* <li className="select-none new-tab mr-1" onClick={createNewTab}>
<div className="flex items-center home-icon-container">
<IconHome2 size={18} strokeWidth={1.5}/>
</div>
</li> */}
</ul>
<ul role="tablist" style={{ maxWidth: maxTablistWidth }} ref={tabsRef}>
{collectionRequestTabs && collectionRequestTabs.length
? collectionRequestTabs.map((tab, index) => {
return (
<li
key={tab.uid}
className={getTabClassname(tab, index)}
role="tab"
onClick={() => handleClick(tab)}
>
<RequestTab key={tab.uid} tab={tab} collection={activeCollection} />
</li>
);
})
: null}
</ul>
<ul role="tablist">
{showChevrons ? (
<li className="select-none short-tab" onClick={rightSlide}>
<div className="flex items-center">
<IconChevronRight size={18} strokeWidth={1.5} />
</div>
</li>
) : null}
<li className="select-none short-tab" id="create-new-tab" onClick={createNewTab}>
<div className="flex items-center pl-4">
<ul role="tablist">
{showChevrons ? (
<li className="select-none short-tab" onClick={leftSlide}>
<div className="flex items-center">
<svg
xmlns="http://www.w3.org/2000/svg"
width="22"
height="22"
fill="currentColor"
viewBox="0 0 16 16"
>
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z" />
</svg>
<IconChevronLeft size={18} strokeWidth={1.5} />
</div>
</li>
{/* Moved to post mvp */}
{/* <li className="select-none new-tab choose-request">
) : null}
{/* Moved to post mvp */}
{/* <li className="select-none new-tab mr-1" onClick={createNewTab}>
<div className="flex items-center home-icon-container">
<IconHome2 size={18} strokeWidth={1.5}/>
</div>
</li> */}
</ul>
<ul role="tablist" style={{ maxWidth: maxTablistWidth }} ref={tabsRef}>
{collectionRequestTabs && collectionRequestTabs.length
? collectionRequestTabs.map((tab, index) => {
return (
<li
key={tab.uid}
className={getTabClassname(tab, index)}
role="tab"
onClick={() => handleClick(tab)}
>
<RequestTab key={tab.uid} tab={tab} collection={activeCollection} />
</li>
);
})
: null}
</ul>
<ul role="tablist">
{showChevrons ? (
<li className="select-none short-tab" onClick={rightSlide}>
<div className="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 16 16">
<path d="M3 9.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z"/>
</svg>
<IconChevronRight size={18} strokeWidth={1.5} />
</div>
</li> */}
</ul>
</div>
) : null}
</li>
) : null}
<li className="select-none short-tab" id="create-new-tab" onClick={createNewTab}>
<div className="flex items-center">
<svg
xmlns="http://www.w3.org/2000/svg"
width="22"
height="22"
fill="currentColor"
viewBox="0 0 16 16"
>
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z" />
</svg>
</div>
</li>
{/* Moved to post mvp */}
{/* <li className="select-none new-tab choose-request">
<div className="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 16 16">
<path d="M3 9.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z"/>
</svg>
</div>
</li> */}
</ul>
</div>
</>
) : null}
</StyledWrapper>

View File

@ -3,7 +3,7 @@ import path from 'path';
import { useDispatch } from 'react-redux';
import { get, each, cloneDeep } from 'lodash';
import { runCollectionFolder } from 'providers/ReduxStore/slices/collections/actions';
import { closeCollectionRunner } from 'providers/ReduxStore/slices/collections';
import { resetCollectionRunner } from 'providers/ReduxStore/slices/collections';
import { findItemInCollection, getTotalRequestCountInCollection } from 'utils/collections';
import { IconRefresh, IconCircleCheck, IconCircleX, IconCheck, IconX, IconRun } from '@tabler/icons';
import slash from 'utils/common/slash';
@ -69,9 +69,9 @@ export default function RunnerResults({ collection }) {
dispatch(runCollectionFolder(collection.uid, runnerInfo.folderUid, runnerInfo.isRecursive));
};
const closeRunner = () => {
const resetRunner = () => {
dispatch(
closeCollectionRunner({
resetCollectionRunner({
collectionUid: collection.uid
})
);
@ -101,8 +101,8 @@ export default function RunnerResults({ collection }) {
Run Collection
</button>
<button className="submit btn btn-sm btn-close mt-6 ml-3" onClick={closeRunner}>
Close
<button className="submit btn btn-sm btn-close mt-6 ml-3" onClick={resetRunner}>
Reset
</button>
</StyledWrapper>
);
@ -202,8 +202,8 @@ export default function RunnerResults({ collection }) {
<button type="submit" className="submit btn btn-sm btn-secondary mt-6 ml-3" onClick={runCollection}>
Run Collection
</button>
<button className="btn btn-sm btn-close mt-6 ml-3" onClick={closeRunner}>
Close
<button className="btn btn-sm btn-close mt-6 ml-3" onClick={resetRunner}>
Reset
</button>
</div>
) : null}

View File

@ -1,9 +1,10 @@
import React from 'react';
import get from 'lodash/get';
import { uuid } from 'utils/common';
import Modal from 'components/Modal';
import { useDispatch } from 'react-redux';
import { addTab } from 'providers/ReduxStore/slices/tabs';
import { runCollectionFolder } from 'providers/ReduxStore/slices/collections/actions';
import { showRunnerView } from 'providers/ReduxStore/slices/collections';
import { flattenItems } from 'utils/collections';
import StyledWrapper from './StyledWrapper';
@ -12,8 +13,10 @@ const RunCollectionItem = ({ collection, item, onClose }) => {
const onSubmit = (recursive) => {
dispatch(
showRunnerView({
collectionUid: collection.uid
addTab({
uid: uuid(),
collectionUid: collection.uid,
type: 'collection-runner'
})
);
dispatch(runCollectionFolder(collection.uid, item ? item.uid : null, recursive));

View File

@ -6,7 +6,7 @@ import { useDrag, useDrop } from 'react-dnd';
import { IconChevronRight, IconDots } from '@tabler/icons';
import { useSelector, useDispatch } from 'react-redux';
import { addTab, focusTab } from 'providers/ReduxStore/slices/tabs';
import { collectionFolderClicked, hideRunnerView } from 'providers/ReduxStore/slices/collections';
import { collectionFolderClicked } from 'providers/ReduxStore/slices/collections';
import { moveItem } from 'providers/ReduxStore/slices/collections/actions';
import Dropdown from 'components/Dropdown';
import NewRequest from 'components/Sidebar/NewRequest';
@ -86,11 +86,6 @@ const CollectionItem = ({ item, collection, searchText }) => {
});
const handleClick = (event) => {
dispatch(
hideRunnerView({
collectionUid: collection.uid
})
);
if (isItemARequest(item)) {
if (itemIsOpenedInTabs(item, tabs)) {
dispatch(

View File

@ -1,5 +1,6 @@
import React, { useState, forwardRef, useRef, useEffect } from 'react';
import classnames from 'classnames';
import { uuid } from 'utils/common';
import filter from 'lodash/filter';
import cloneDeep from 'lodash/cloneDeep';
import { useDrop } from 'react-dnd';
@ -8,12 +9,12 @@ import Dropdown from 'components/Dropdown';
import { collectionClicked } from 'providers/ReduxStore/slices/collections';
import { moveItemToRootOfCollection } from 'providers/ReduxStore/slices/collections/actions';
import { useDispatch } from 'react-redux';
import { addTab } from 'providers/ReduxStore/slices/tabs';
import NewRequest from 'components/Sidebar/NewRequest';
import NewFolder from 'components/Sidebar/NewFolder';
import CollectionItem from './CollectionItem';
import RemoveCollection from './RemoveCollection';
import CollectionProperties from './CollectionProperties';
import RunCollectionItem from './CollectionItem/RunCollectionItem';
import { doesCollectionHaveItemsMatchingSearchText } from 'utils/collections/search';
import { isItemAFolder, isItemARequest, transformCollectionToSaveToIdb } from 'utils/collections';
import exportCollection from 'utils/collections/export';
@ -26,7 +27,6 @@ const Collection = ({ collection, searchText }) => {
const [showNewRequestModal, setShowNewRequestModal] = useState(false);
const [showRenameCollectionModal, setShowRenameCollectionModal] = useState(false);
const [showRemoveCollectionModal, setShowRemoveCollectionModal] = useState(false);
const [showRunCollectionModal, setShowRunCollectionModal] = useState(false);
const [collectionPropertiesModal, setCollectionPropertiesModal] = useState(false);
const [collectionIsCollapsed, setCollectionIsCollapsed] = useState(collection.collapsed);
const dispatch = useDispatch();
@ -41,6 +41,16 @@ const Collection = ({ collection, searchText }) => {
);
});
const handleRun = () => {
dispatch(
addTab({
uid: uuid(),
collectionUid: collection.uid,
type: 'collection-runner'
})
);
};
useEffect(() => {
if (searchText && searchText.length) {
setCollectionIsCollapsed(false);
@ -105,9 +115,6 @@ const Collection = ({ collection, searchText }) => {
{showRemoveCollectionModal && (
<RemoveCollection collection={collection} onClose={() => setShowRemoveCollectionModal(false)} />
)}
{showRunCollectionModal && (
<RunCollectionItem collection={collection} onClose={() => setShowRunCollectionModal(false)} />
)}
{collectionPropertiesModal && (
<CollectionProperties collection={collection} onClose={() => setCollectionPropertiesModal(false)} />
)}
@ -147,7 +154,7 @@ const Collection = ({ collection, searchText }) => {
className="dropdown-item"
onClick={(e) => {
menuDropdownTippyRef.current.hide();
setShowRunCollectionModal(true);
handleRun();
}}
>
Run

View File

@ -769,7 +769,6 @@ export const openCollectionEvent = (uid, pathname, brunoConfig) => (dispatch, ge
name: brunoConfig.name,
pathname: pathname,
items: [],
showRunner: false,
collectionVariables: {},
brunoConfig: brunoConfig
};

View File

@ -1016,30 +1016,6 @@ export const collectionsSlice = createSlice({
collection.name = newName;
}
},
toggleRunnerView: (state, action) => {
const { collectionUid } = action.payload;
const collection = findCollectionByUid(state.collections, collectionUid);
if (collection) {
collection.showRunner = !collection.showRunner;
}
},
showRunnerView: (state, action) => {
const { collectionUid } = action.payload;
const collection = findCollectionByUid(state.collections, collectionUid);
if (collection) {
collection.showRunner = true;
}
},
hideRunnerView: (state, action) => {
const { collectionUid } = action.payload;
const collection = findCollectionByUid(state.collections, collectionUid);
if (collection) {
collection.showRunner = false;
}
},
resetRunResults: (state, action) => {
const { collectionUid } = action.payload;
const collection = findCollectionByUid(state.collections, collectionUid);
@ -1149,13 +1125,12 @@ export const collectionsSlice = createSlice({
}
}
},
closeCollectionRunner: (state, action) => {
resetCollectionRunner: (state, action) => {
const { collectionUid } = action.payload;
const collection = findCollectionByUid(state.collections, collectionUid);
if (collection) {
collection.runnerResult = null;
collection.showRunner = false;
}
}
}
@ -1216,13 +1191,10 @@ export const {
collectionUnlinkDirectoryEvent,
collectionAddEnvFileEvent,
collectionRenamedEvent,
toggleRunnerView,
showRunnerView,
hideRunnerView,
resetRunResults,
runRequestEvent,
runFolderEvent,
closeCollectionRunner
resetCollectionRunner
} = collectionsSlice.actions;
export default collectionsSlice.reducer;

View File

@ -10,6 +10,10 @@ const initialState = {
activeTabUid: null
};
const tabTypeAlreadyExists = (tabs, collectionUid, type) => {
return find(tabs, (tab) => tab.collectionUid === collectionUid && tab.type === type);
};
export const tabsSlice = createSlice({
name: 'tabs',
initialState,
@ -20,8 +24,8 @@ export const tabsSlice = createSlice({
return;
}
if (action.payload.type === 'variables') {
const tab = find(state.tabs, (t) => t.collectionUid === action.payload.collectionUid && t.type === 'variables');
if (['variables', 'collection-settings', 'collection-runner'].includes(action.payload.type)) {
const tab = tabTypeAlreadyExists(state.tabs, action.payload.collectionUid, action.payload.type);
if (tab) {
state.activeTabUid = tab.uid;
return;

View File

@ -124,7 +124,6 @@ const collectionSchema = Yup.object({
.nullable(),
environments: environmentsSchema,
pathname: Yup.string().nullable(),
showRunner: Yup.boolean(),
runnerResult: Yup.object({
items: Yup.array()
}),