feat: added helptips for file and folder custom names

This commit is contained in:
Anoop M D
2025-03-17 02:52:03 +05:30
parent cd2f5d5233
commit 3808089e60
8 changed files with 276 additions and 201 deletions

View File

@@ -31,7 +31,7 @@ const StyledWrapper = styled.div`
.separator {
color: ${(props) => props.theme.text};
opacity: 0.6;
margin: 0 1px;
margin: 0 2px;
}
}
`;

View File

@@ -4,6 +4,7 @@ import path from 'utils/common/path';
import StyledWrapper from './StyledWrapper';
const PathDisplay = ({
collection,
dirName = '',
baseName = ''
}) => {
@@ -14,10 +15,16 @@ const PathDisplay = ({
return (
<StyledWrapper>
<div className="path-display mt-2">
<div className="path-layout flex">
<div className="path-layout flex font-mono">
<div className="icon-column flex">
{hasExtension ? <IconFile size={16} /> : <IconFolder size={16} />}
</div>
{collection?.name && (
<div className="path-segment collection-segment">
{collection.name}
<span className="separator">/</span>
</div>
)}
{pathSegments?.map((segment, index) => (
<React.Fragment key={index}>
<div className="path-segment">

View File

@@ -7,7 +7,8 @@ import { cloneCollection } from 'providers/ReduxStore/slices/collections/actions
import toast from 'react-hot-toast';
import Modal from 'components/Modal';
import { sanitizeName, validateName, validateNameError } from 'utils/common/regex';
import PathDisplay from 'components/PathDisplay/index';
import Help from 'components/Help';
import PathDisplay from 'components/PathDisplay';
import { useState } from 'react';
import { IconArrowBackUp, IconEdit } from "@tabler/icons";
@@ -125,23 +126,46 @@ const CloneCollection = ({ onClose, collection }) => {
<div className="text-red-500">{formik.errors.collectionLocation}</div>
) : null}
<div className="mt-1">
<span className="text-link cursor-pointer hover:underline" onClick={browse}>
<span
className="text-link cursor-pointer hover:underline" onClick={browse}
style={{
fontSize: '0.8125rem'
}}
>
Browse
</span>
</div>
{isEditing ?
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="block font-semibold">
Folder Name
</label>
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="flex items-center font-semibold">
Folder Name
<Help width="300">
<p>
The name of the folder used to store the collection.
</p>
<p className="mt-2">
You can choose a folder name different from your collection's name or one compatible with filesystem rules.
</p>
</Help>
</label>
{isEditing ? (
<IconArrowBackUp
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(false)}
/>
</div>
) : (
<IconEdit
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(true)}
/>
)}
</div>
{isEditing ? (
<input
id="collection-folder-name"
type="text"
@@ -154,30 +178,18 @@ const CloneCollection = ({ onClose, collection }) => {
spellCheck="false"
value={formik.values.collectionFolderName || ''}
/>
</div>
:
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="baseName" className="block font-semibold">
Folder Path
</label>
<IconEdit
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(true)}
/>
</div>
) : (
<div className='relative flex flex-row gap-1 items-center justify-between'>
<PathDisplay
baseName={formik.values.collectionFolderName}
/>
</div>
</div>
}
{formik.touched.collectionFolderName && formik.errors.collectionFolderName ? (
<div className="text-red-500">{formik.errors.collectionFolderName}</div>
) : null}
)}
{formik.touched.collectionFolderName && formik.errors.collectionFolderName ? (
<div className="text-red-500">{formik.errors.collectionFolderName}</div>
) : null}
</div>
</div>
</form>
</Modal>

View File

@@ -8,6 +8,7 @@ import { isItemAFolder } from 'utils/tabs';
import { cloneItem } from 'providers/ReduxStore/slices/collections/actions';
import { IconArrowBackUp, IconEdit } from "@tabler/icons";
import { sanitizeName, validateName, validateNameError } from 'utils/common/regex';
import Help from 'components/Help';
import PathDisplay from 'components/PathDisplay/index';
import path from 'utils/common/path';
@@ -91,60 +92,76 @@ const CloneCollectionItem = ({ collection, item, onClose }) => {
/>
{formik.touched.name && formik.errors.name ? <div className="text-red-500">{formik.errors.name}</div> : null}
</div>
{isEditing ? (
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="block font-semibold">
{isFolder ? 'Folder' : 'File'} Name
</label>
<IconArrowBackUp
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(false)}
/>
</div>
<div className='relative flex flex-row gap-1 items-center justify-between'>
<input
id="file-name"
type="text"
name="filename"
placeholder="File Name"
className={`!pr-10 block textbox mt-2 w-full`}
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
onChange={formik.handleChange}
value={formik.values.filename || ''}
/>
{itemType !== 'folder' && <span className='absolute right-2 top-4 flex justify-center items-center file-extension'>.bru</span>}
</div>
</div>
) : (
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="baseName" className="block font-semibold">
{isFolder ? 'Folder' : 'File'} Path
</label>
<IconEdit
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="flex items-center font-semibold">
{isFolder ? 'Folder' : 'File'} Name
{ isFolder ? (
<Help width="300">
<p>
Bruno stores folders in the UI as folders on your filesystem.
</p>
<p className="mt-2">
You can specify a custom folder name if you'd prefer a different name or need one compatible with filesystem rules.
</p>
</Help>
) : (
<Help width="300">
<p>
Bruno saves each request as a file in your collection's folder.
</p>
<p className="mt-2">
You can choose a file name different from your request's name or one compatible with filesystem rules.
</p>
</Help>
)}
</label>
{isEditing ? (
<IconArrowBackUp
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(false)}
/>
) : (
<IconEdit
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(true)}
/>
</div>
<div className='relative flex flex-row gap-1 items-center justify-between'>
<PathDisplay
dirName={path.relative(collection?.pathname, path.dirname(item?.pathname))}
baseName={formik.values.filename}
/>
</div>
)}
</div>
{isEditing ? (
<div className='relative flex flex-row gap-1 items-center justify-between'>
<input
id="file-name"
type="text"
name="filename"
placeholder={isFolder ? 'Folder Name' : 'File Name'}
className={`!pr-10 block textbox mt-2 w-full`}
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
onChange={formik.handleChange}
value={formik.values.filename || ''}
/>
{itemType !== 'folder' && <span className='absolute right-2 top-4 flex justify-center items-center file-extension'>.bru</span>}
</div>
) : (
<div className='relative flex flex-row gap-1 items-center justify-between'>
<PathDisplay
collection={collection}
dirName={path.relative(collection?.pathname, path.dirname(item?.pathname))}
baseName={formik.values.filename}
/>
</div>
)}
{formik.touched.filename && formik.errors.filename ? (
<div className="text-red-500">{formik.errors.filename}</div>
) : null}
</div>
</form>
</Modal>
);

View File

@@ -10,6 +10,7 @@ import { IconArrowBackUp, IconEdit } from '@tabler/icons';
import { sanitizeName, validateName, validateNameError } from 'utils/common/regex';
import toast from 'react-hot-toast';
import { closeTabs } from 'providers/ReduxStore/slices/tabs';
import Help from 'components/Help';
import PathDisplay from 'components/PathDisplay';
const RenameCollectionItem = ({ collection, item, onClose }) => {
@@ -110,26 +111,54 @@ const RenameCollectionItem = ({ collection, item, onClose }) => {
/>
{formik.touched.name && formik.errors.name ? <div className="text-red-500">{formik.errors.name}</div> : null}
</div>
{isEditing ? (
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="block font-semibold">
{isFolder ? 'Folder' : 'File'} Name
</label>
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="flex items-center font-semibold">
{isFolder ? 'Folder' : 'File'} Name
{ isFolder ? (
<Help width="300">
<p>
Bruno stores folders in the UI as folders on your filesystem.
</p>
<p className="mt-2">
You can specify a custom folder name if you'd prefer a different name or need one compatible with filesystem rules.
</p>
</Help>
) : (
<Help width="300">
<p>
Bruno saves each request as a file in your collection's folder.
</p>
<p className="mt-2">
You can choose a file name different from your request's name or one compatible with filesystem rules.
</p>
</Help>
)}
</label>
{isEditing ? (
<IconArrowBackUp
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(false)}
/>
</div>
) : (
<IconEdit
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(true)}
/>
)}
</div>
{isEditing ? (
<div className='relative flex flex-row gap-1 items-center justify-between'>
<input
id="file-name"
type="text"
name="filename"
placeholder="File Name"
placeholder={isFolder ? 'Folder Name' : 'File Name'}
className={`!pr-10 block textbox mt-2 w-full`}
autoComplete="off"
autoCorrect="off"
@@ -140,31 +169,19 @@ const RenameCollectionItem = ({ collection, item, onClose }) => {
/>
{itemType !== 'folder' && <span className='absolute right-2 top-4 flex justify-center items-center file-extension'>.bru</span>}
</div>
</div>
) : (
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="baseName" className="block font-semibold">
{isFolder ? 'Folder' : 'File'} Path
</label>
<IconEdit
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(true)}
/>
</div>
) : (
<div className='relative flex flex-row gap-1 items-center justify-between'>
<PathDisplay
collection={collection}
dirName={path.relative(collection?.pathname, path.dirname(item?.pathname))}
baseName={formik.values.filename}
/>
</div>
</div>
)}
{formik.touched.filename && formik.errors.filename ? (
<div className="text-red-500">{formik.errors.filename}</div>
) : null}
)}
{formik.touched.filename && formik.errors.filename ? (
<div className="text-red-500">{formik.errors.filename}</div>
) : null}
</div>
</form>
</Modal>
);

View File

@@ -105,7 +105,7 @@ const CreateCollection = ({ onClose }) => {
Bruno stores your collections on your computer's filesystem.
</p>
<p className="mt-2">
Choose where you want to store this collection.
Choose the location where you want to store this collection.
</p>
</Help>
</label>
@@ -126,59 +126,70 @@ const CreateCollection = ({ onClose }) => {
<div className="text-red-500">{formik.errors.collectionLocation}</div>
) : null}
<div className="mt-1">
<span className="text-link cursor-pointer hover:underline" onClick={browse}>
<span
className="text-link cursor-pointer hover:underline" onClick={browse}
style={{
fontSize: '0.8125rem'
}}
>
Browse
</span>
</div>
{isEditing ?
{formik.values.collectionName?.trim()?.length > 0 && (
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="block font-semibold">
<label htmlFor="filename" className="flex items-center font-semibold">
Folder Name
<Help width="300">
<p>
The name of the folder used to store the collection.
</p>
<p className="mt-2">
You can choose a folder name different from your collection's name or one compatible with filesystem rules.
</p>
</Help>
</label>
<IconArrowBackUp
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(false)}
/>
{isEditing ? (
<IconArrowBackUp
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(false)}
/>
) : (
<IconEdit
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(true)}
/>
)}
</div>
<input
id="collection-folder-name"
type="text"
name="collectionFolderName"
className="block textbox mt-2 w-full"
onChange={formik.handleChange}
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
value={formik.values.collectionFolderName || ''}
/>
{isEditing ? (
<input
id="collection-folder-name"
type="text"
name="collectionFolderName"
className="block textbox mt-2 w-full"
onChange={formik.handleChange}
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
value={formik.values.collectionFolderName || ''}
/>
) : (
<div className='relative flex flex-row gap-1 items-center justify-between'>
<PathDisplay
baseName={formik.values.collectionFolderName}
/>
</div>
)}
{formik.touched.collectionFolderName && formik.errors.collectionFolderName ? (
<div className="text-red-500">{formik.errors.collectionFolderName}</div>
) : null}
</div>
:
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="baseName" className="block font-semibold">
Folder Path
</label>
<IconEdit
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(true)}
/>
</div>
<div className='relative flex flex-row gap-1 items-center justify-between'>
<PathDisplay
baseName={formik.values.collectionFolderName}
/>
</div>
</div>
}
{formik.touched.collectionFolderName && formik.errors.collectionFolderName ? (
<div className="text-red-500">{formik.errors.collectionFolderName}</div>
) : null}
)}
</div>
</form>
</Modal>

View File

@@ -9,7 +9,7 @@ import { IconArrowBackUp, IconEdit} from '@tabler/icons';
import { sanitizeName, validateName, validateNameError } from 'utils/common/regex';
import PathDisplay from 'components/PathDisplay/index';
import path from "utils/common/path";
import Help from 'components/Help';
const NewFolder = ({ collection, item, onClose }) => {
const dispatch = useDispatch();
const inputRef = useRef();
@@ -88,20 +88,37 @@ const NewFolder = ({ collection, item, onClose }) => {
<div className="text-red-500">{formik.errors.folderName}</div>
) : null}
</div>
{isEditing ? (
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="directoryName" className="block font-semibold">
Folder Name
</label>
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="directoryName" className="flex items-center font-semibold">
Folder Name
<Help width="300">
<p>
Bruno stores folders in the UI as folders on your filesystem.
</p>
<p className="mt-2">
You can specify a custom folder name if you'd prefer a different name or need one compatible with filesystem rules.
</p>
</Help>
</label>
{isEditing ? (
<IconArrowBackUp
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(false)}
/>
</div>
): (
<IconEdit
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(true)}
/>
)}
</div>
{isEditing ? (
<div className='relative flex flex-row gap-1 items-center justify-between'>
<input
id="file-name"
@@ -117,31 +134,19 @@ const NewFolder = ({ collection, item, onClose }) => {
value={formik.values.directoryName || ''}
/>
</div>
</div>
) : (
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="directoryName" className="block font-semibold">
Folder Path
</label>
<IconEdit
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(true)}
/>
</div>
) : (
<div className='relative flex flex-row gap-1 items-center justify-between'>
<PathDisplay
collection={collection}
dirName={path.relative(collection?.pathname, item?.pathname || collection?.pathname)}
baseName={formik.values.directoryName}
/>
</div>
</div>
)}
{formik.touched.directoryName && formik.errors.directoryName ? (
<div className="text-red-500">{formik.errors.directoryName}</div>
) : null}
)}
{formik.touched.directoryName && formik.errors.directoryName ? (
<div className="text-red-500">{formik.errors.directoryName}</div>
) : null}
</div>
</form>
</Modal>
);

View File

@@ -16,6 +16,7 @@ import { IconArrowBackUp, IconCaretDown, IconEdit } from '@tabler/icons';
import { sanitizeName, validateName, validateNameError } from 'utils/common/regex';
import Dropdown from 'components/Dropdown';
import PathDisplay from 'components/PathDisplay';
import Help from 'components/Help';
import StyledWrapper from './StyledWrapper';
const NewRequest = ({ collection, item, isEphemeral, onClose }) => {
@@ -318,19 +319,36 @@ const NewRequest = ({ collection, item, isEphemeral, onClose }) => {
<div className="text-red-500">{formik.errors.requestName}</div>
) : null}
</div>
{isEditing ? (
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="block font-semibold">
File Name
</label>
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="flex items-center font-semibold">
File Name
<Help width="300">
<p>
Bruno saves each request as a file in your collection's folder.
</p>
<p className="mt-2">
You can choose a file name different from your request's name or one compatible with filesystem rules.
</p>
</Help>
</label>
{isEditing ? (
<IconArrowBackUp
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(false)}
/>
</div>
) : (
<IconEdit
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(true)}
/>
)}
</div>
{isEditing ? (
<div className='relative flex flex-row gap-1 items-center justify-between'>
<input
id="file-name"
@@ -347,31 +365,19 @@ const NewRequest = ({ collection, item, isEphemeral, onClose }) => {
/>
<span className='absolute right-2 top-4 flex justify-center items-center file-extension'>.bru</span>
</div>
</div>
) : (
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="baseName" className="block font-semibold">
File Path
</label>
<IconEdit
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(true)}
/>
</div>
) : (
<div className='relative flex flex-row gap-1 items-center justify-between'>
<PathDisplay
collection={collection}
dirName={path.relative(collection?.pathname, item?.pathname || collection?.pathname)}
baseName={formik.values.filename? `${formik.values.filename}.bru` : ''}
/>
</div>
</div>
)}
{formik.touched.filename && formik.errors.filename ? (
<div className="text-red-500">{formik.errors.filename}</div>
) : null}
)}
{formik.touched.filename && formik.errors.filename ? (
<div className="text-red-500">{formik.errors.filename}</div>
) : null}
</div>
{formik.values.requestType !== 'from-curl' ? (
<>
<div className="mt-4">