Skip to content

Commit 661b7ab

Browse files
authored
Merge pull request #63 from FlowTestAI/ui-improvements
New side sheet component and other UI changes
2 parents 9fc827d + 6742daa commit 661b7ab

File tree

22 files changed

+344
-82
lines changed

22 files changed

+344
-82
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"react-router": "^6.15.0",
3030
"react-router-dom": "^6.22.2",
3131
"react-scripts": "5.0.1",
32+
"react-sliding-pane": "^7.3.0",
3233
"react-toastify": "^10.0.5",
3334
"react-tooltip": "^5.26.2",
3435
"reactflow": "^11.8.3",

packages/flowtest-electron/electron-main.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Modules to control application life and create native browser window
2-
const { app, BrowserWindow, Menu } = require('electron');
2+
const { app, BrowserWindow, Menu, shell } = require('electron');
33
const path = require('path');
44
const url = require('url');
55
const template = require('./electron-menu');
@@ -38,6 +38,13 @@ app.on('ready', async () => {
3838

3939
// Open the DevTools.
4040
// mainWindow.webContents.openDevTools()
41+
42+
// This is required to open a link in the external browser
43+
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
44+
shell.openExternal(url);
45+
return { action: 'deny' };
46+
});
47+
4148
watcher = new Watcher();
4249

4350
registerRendererEventHandlers(mainWindow, watcher);
13.4 KB
Loading

src/components/atoms/Logo.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React from 'react';
2+
import FlowTestAI from 'assets/icons/FlowTestAI-black.png';
3+
4+
const AppLogo = ({ styleClasses }) => {
5+
return (
6+
<div className={styleClasses}>
7+
<img src={FlowTestAI} alt='FlowTestAI app logo' />
8+
</div>
9+
);
10+
};
11+
12+
export default AppLogo;

src/components/atoms/Tabs.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ const Tabs = () => {
2525
const [closingTabId, setClosingTabId] = useState('');
2626
const [closingCollectionId, setClosingCollectionId] = useState('');
2727

28-
const activeTabStyles =
29-
'before:absolute before:h-[0.25rem] before:w-full before:bg-slate-300 before:content-[""] before:bottom-0 before:left-0';
28+
// const activeTabStyles =
29+
// 'before:absolute before:h-[0.25rem] before:w-full before:bg-slate-300 before:content-[""] before:bottom-0 before:left-0 bg-cyan-950 text-white';
30+
const activeTabStyles = 'bg-cyan-900 text-white';
3031
const tabCommonStyles =
31-
'tab flex items-center gap-x-2 border-r border-neutral-300 bg-transparent pr-0 tracking-[0.15em] transition duration-500 ease-in text-sm flex-nowrap';
32+
'tab flex items-center gap-x-2 border-r border-neutral-300 pr-0 tracking-[0.15em] transition duration-300 ease-in text-sm flex-nowrap';
3233
const messageForConfirmActionModal = `You have unsaved changes in the ${focusTab?.type}, are you sure you want to close it?`;
3334

3435
const handleCloseTab = (event, tab) => {
@@ -71,7 +72,7 @@ const Tabs = () => {
7172
</a>
7273
{/* close needs to be a separate clickable component other wise it gets confused with above */}
7374
<div
74-
className='flex items-center h-full px-2 hover:rounded hover:rounded-l-none hover:bg-slate-200'
75+
className={`flex h-full items-center px-2 ${focusTabId === tab.id ? 'text-white hover:bg-cyan-950 ' : 'text-cyan-900 hover:bg-slate-200'} `}
7576
data-tab-id={tab.id}
7677
onClick={(e) => handleCloseTab(e, tab)}
7778
>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React, { useState } from 'react';
2+
3+
const LoadingSpinner = ({ spinnerColor }) => {
4+
return (
5+
<div className='absolute z-50 flex items-center justify-center w-full h-full p-4 bg-slate-500/50'>
6+
<span className={`loading loading-spinner loading-lg ${spinnerColor}`}></span>
7+
</div>
8+
);
9+
};
10+
11+
export default LoadingSpinner;

src/components/atoms/sidebar/environments/EnvOptionsMenu.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { EllipsisVerticalIcon } from '@heroicons/react/20/solid';
66
import { DirectoryOptionsActions } from 'constants/WorkspaceDirectory';
77

88
// ToDo: Combine this component with OptionsMenu in sidebar atoms to make it generic
9-
const EnvOptionsMenu = ({ pathName, itemType }) => {
9+
const EnvOptionsMenu = ({ pathName, itemType, collectionId }) => {
1010
const menuItemsStyles =
1111
'group flex w-full items-center rounded px-2 py-2 text-sm text-gray-900 transition duration-200 ease-out hover:bg-slate-100';
1212
return (
@@ -43,6 +43,7 @@ const EnvOptionsMenu = ({ pathName, itemType }) => {
4343
data-click-from='env-options-menu'
4444
data-options-menu-item={DirectoryOptionsActions.addNewEnvironment.value}
4545
data-path-name={pathName}
46+
data-collection-id={collectionId}
4647
>
4748
<PencilSquareIcon
4849
className='w-4 h-4 mr-2'

src/components/molecules/environment/index.js

Lines changed: 56 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import React, { useState } from 'react';
22
import useEnvStore from 'stores/EnvStore';
33
import 'react-edit-text/dist/index.css';
4-
import { TrashIcon } from '@heroicons/react/24/outline';
4+
import { TrashIcon, PlusIcon } from '@heroicons/react/24/outline';
55
import AddEnvVariableModal from '../modals/AddEnvVariableModal';
66
import ConfirmActionModal from '../modals/ConfirmActionModal';
7+
import Button from 'components/atoms/common/Button';
8+
import { BUTTON_TYPES, OBJ_TYPES } from 'constants/Common';
79

810
const Env = () => {
911
const variables = useEnvStore((state) => state.variables);
@@ -17,40 +19,60 @@ const Env = () => {
1719

1820
return (
1921
<div className='p-4'>
20-
{/* <div>Test Tab panel for environment</div> */}
21-
<div className='overflow-x-auto'>
22-
<table className='table table-zebra'>
23-
{/* head */}
24-
<thead>
25-
<tr>
26-
<th></th>
27-
<th>Key</th>
28-
<th>Value</th>
29-
{/* <th>New Value</th> */}
22+
<table className='w-full leading-normal'>
23+
<thead>
24+
<tr>
25+
<th className='px-5 py-3 text-xs font-semibold tracking-wider text-left text-gray-600 uppercase border-r-0 max-w-4 rounded-tl-xl border-slate-400 bg-slate-200'>
26+
Serial Number
27+
</th>
28+
<th className='px-5 py-3 text-xs font-semibold tracking-wider text-left text-gray-600 uppercase border-slate-400 bg-slate-200'>
29+
Key
30+
</th>
31+
<th className='px-5 py-3 text-xs font-semibold tracking-wider text-left text-gray-600 uppercase border-slate-400 bg-slate-200 '>
32+
Value
33+
</th>
34+
<th className='px-5 py-3 text-xs font-semibold tracking-wider text-left text-gray-600 uppercase rounded-tr-xl border-slate-400 bg-slate-200'>
35+
Action
36+
</th>
37+
</tr>
38+
</thead>
39+
<tbody>
40+
{Object.entries(variables).map(([key, value], index) => (
41+
<tr key={index} className='text-sm hover:bg-slate-100'>
42+
<td className='px-5 py-3 border-b border-gray-200 max-w-4'>
43+
<p className='text-gray-900 whitespace-no-wrap'>{index + 1}</p>
44+
</td>
45+
<td className='px-5 py-3 border-b border-gray-200'>
46+
<p className='text-gray-900 whitespace-no-wrap'>{key}</p>
47+
</td>
48+
<td className='px-5 py-3 border-b border-gray-200'>
49+
<p className='text-gray-900 whitespace-no-wrap'>{value}</p>
50+
</td>
51+
<td className='px-5 py-3 border-b border-gray-200'>
52+
<div
53+
className='relative inline-block p-2 text-left transition duration-200 ease-out rounded rounded-l-none cursor-pointer hover:bg-slate-200'
54+
onClick={() => {
55+
setDeleteKey(key);
56+
setConfirmActionModalOpen(true);
57+
}}
58+
>
59+
<TrashIcon className='w-4 h-4' aria-hidden='true' />
60+
</div>
61+
</td>
3062
</tr>
31-
</thead>
32-
<tbody>
33-
{Object.entries(variables).map(([key, value], index) => (
34-
<tr key={index}>
35-
<th>{index}</th>
36-
<td>{key}</td>
37-
<td>{value}</td>
38-
<td>
39-
<div
40-
className='relative inline-block p-2 text-left transition duration-200 ease-out rounded rounded-l-none hover:bg-slate-200'
41-
onClick={() => {
42-
setDeleteKey(key);
43-
setConfirmActionModalOpen(true);
44-
}}
45-
>
46-
<TrashIcon className='w-4 h-4' aria-hidden='true' />
47-
</div>
48-
</td>
49-
</tr>
50-
))}
51-
</tbody>
52-
</table>
53-
<button onClick={() => setAddVariableModalOpen(true)}>+ Add Variable</button>
63+
))}
64+
</tbody>
65+
</table>
66+
<div className='mt-6'>
67+
<Button
68+
btnType={BUTTON_TYPES.tertiary}
69+
isDisabled={false}
70+
onClickHandle={() => setAddVariableModalOpen(true)}
71+
fullWidth={true}
72+
>
73+
<PlusIcon className='w-4 h-4' />
74+
<span>Add Variable</span>
75+
</Button>
5476
</div>
5577
<AddEnvVariableModal
5678
closeFn={() => setAddVariableModalOpen(false)}

src/components/molecules/flow/nodes/RequestNode.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const RequestNode = ({ id, data }) => {
3939
Object.keys(data.variables).map((id) => (
4040
<div className='flex items-center justify-between pb-2' key={id}>
4141
<div className='flex items-center justify-between text-sm border rounded-md border-neutral-500 text-neutral-500 outline-0 focus:ring-0'>
42+
<label className='px-4 py-2 border-r rounded-bl-md rounded-tl-md border-r-neutral-500'>{id}</label>
4243
{data.variables[id].type === 'Boolean' ? (
4344
<select
4445
onChange={(e) => handleVariableChange(e, id)}
@@ -59,7 +60,6 @@ const RequestNode = ({ id, data }) => {
5960
value={data.variables[id].value}
6061
/>
6162
)}
62-
<label>{id}</label>
6363
<div className='px-4 py-2 border-l rounded-br-md rounded-tr-md border-l-neutral-500'>
6464
{data.variables[id].type}
6565
</div>

src/components/molecules/footers/MainFooter.js

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,60 @@
11
import React from 'react';
2+
import { ArrowLeftEndOnRectangleIcon, ArrowRightStartOnRectangleIcon } from '@heroicons/react/24/outline';
3+
import Tippy from '@tippyjs/react';
4+
import useNavigationStore from 'stores/AppNavBarStore';
25

36
const MainFooter = () => {
7+
const collapseNavBarValue = useNavigationStore((state) => state.collapseNavBar);
8+
const updateNavCollapseState = useNavigationStore((state) => state.setNavCollapseState);
49
return (
5-
<footer className='flex px-4 py-2 text-xs border-t border-neutral-300'>
6-
<p>Footer</p>
10+
<footer className='flex items-center justify-between px-6 py-2 text-xs border-t border-neutral-300'>
11+
<label className='py-1 cursor-pointer swap swap-rotate'>
12+
<input
13+
type='checkbox'
14+
onClick={() => {
15+
console.log('I have been clicked');
16+
updateNavCollapseState(!collapseNavBarValue);
17+
}}
18+
/>
19+
<ArrowRightStartOnRectangleIcon className='w-6 h-6 swap-on' />
20+
<ArrowLeftEndOnRectangleIcon className='w-6 h-6 swap-off' />
21+
</label>
22+
<div className='flex items-center justify-between gap-4'>
23+
<Tippy content='Github' placement='top'>
24+
<a href='https://github.com/FlowTestAI/FlowTest' target='_blank' rel='noreferrer' className='link'>
25+
<b>Github</b>
26+
</a>
27+
</Tippy>
28+
29+
<Tippy content='Contact Us' placement='top'>
30+
<a
31+
href='https://github.com/FlowTestAI/FlowTest/discussions'
32+
target='_blank'
33+
rel='noreferrer'
34+
className='link'
35+
>
36+
<b>Contact us</b>
37+
</a>
38+
</Tippy>
39+
40+
<Tippy content='Discord' placement='top'>
41+
<a href='https://discord.gg/Pf9tdSjPeF' target='_blank' rel='noreferrer' className='link'>
42+
<b>Discord</b>
43+
</a>
44+
</Tippy>
45+
46+
<Tippy content='Coming Soon' placement='top'>
47+
<a href='#' className='link'>
48+
<b>Docs</b>
49+
</a>
50+
</Tippy>
51+
52+
<Tippy content='About' placement='top'>
53+
<a href='https://github.com/FlowTestAI/FlowTest' target='_blank' rel='noreferrer' className='link'>
54+
<b>About</b>
55+
</a>
56+
</Tippy>
57+
</div>
758
</footer>
859
);
960
};

0 commit comments

Comments
 (0)