filename support ui updates, regex update for generating validation error for the last char, getEncoding function headers props optional chaining validation (#4243)

This commit is contained in:
lohit
2025-03-17 01:36:39 +05:30
committed by GitHub
parent 7ae33d05c9
commit cd2f5d5233
13 changed files with 232 additions and 196 deletions

View File

@@ -1,6 +1,7 @@
import styled from 'styled-components';
const StyledWrapper = styled.div`
width: 100%;
.path-display {
background: ${(props) => props.theme.requestTabPanel.url.bg};
border-radius: 4px;

View File

@@ -1,63 +1,34 @@
import React from 'react';
import { IconEdit, IconFolder, IconFile } from '@tabler/icons';
import { IconFolder, IconFile } from '@tabler/icons';
import path from 'utils/common/path';
import StyledWrapper from './StyledWrapper';
const PathDisplay = ({
collection,
item,
filename,
extension = '.bru',
showExtension = true,
toggleEditingFilename,
showDirectory = false
dirName = '',
baseName = ''
}) => {
const relativePath = item?.pathname && path.relative(collection?.pathname, showDirectory ? path.dirname(item?.pathname) : item?.pathname);
const pathSegments = relativePath?.split(path.sep).filter(Boolean);
const extName = path.extname(baseName)
const hasExtension = Boolean(extName);
const pathSegments = dirName?.split(path.sep).filter(Boolean);
return (
<StyledWrapper>
<div className="mt-4">
<div className="flex items-center justify-between mb-2">
<label className="block font-medium">Location</label>
<IconEdit
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditingFilename(true)}
/>
</div>
<div className="path-display">
<div className="path-layout flex">
<div className="icon-column flex">
{showExtension ? <IconFile size={16} /> : <IconFolder size={16} />}
</div>
<div className="path-container flex font-mono items-center">
<div className="path-segment collection-segment">
{collection?.name}
</div>
{pathSegments?.length > 0 && pathSegments?.map((segment, index) => (
<React.Fragment key={index}>
<span className="separator">/</span>
<div className="path-segment">
{segment}
</div>
</React.Fragment>
))}
{collection && (
<span className="separator">/</span>
)}
<span className="filename">
{filename}
{showExtension && filename?.length ? (
<span className="file-extension">{extension}</span>
) : null}
</span>
</div>
<div className="path-display mt-2">
<div className="path-layout flex">
<div className="icon-column flex">
{hasExtension ? <IconFile size={16} /> : <IconFolder size={16} />}
</div>
{pathSegments?.map((segment, index) => (
<React.Fragment key={index}>
<div className="path-segment">
{segment}
</div>
<span className="separator">/</span>
</React.Fragment>
))}
<span className="filename">
{baseName}
</span>
</div>
</div>
</StyledWrapper>

View File

@@ -9,18 +9,19 @@ import Modal from 'components/Modal';
import { sanitizeName, validateName, validateNameError } from 'utils/common/regex';
import PathDisplay from 'components/PathDisplay/index';
import { useState } from 'react';
import { IconArrowBackUp } from "@tabler/icons";
import { IconArrowBackUp, IconEdit } from "@tabler/icons";
const CloneCollection = ({ onClose, collection }) => {
const inputRef = useRef();
const dispatch = useDispatch();
const [isEditingFilename, toggleEditingFilename] = useState(false);
const [isEditing, toggleEditing] = useState(false);
const { name } = collection;
const formik = useFormik({
enableReinitialize: true,
initialValues: {
collectionName: '',
collectionFolderName: '',
collectionName: `${name} copy`,
collectionFolderName: `${sanitizeName(name)} copy`,
collectionLocation: ''
},
validationSchema: Yup.object({
@@ -31,7 +32,7 @@ const CloneCollection = ({ onClose, collection }) => {
collectionFolderName: Yup.string()
.min(1, 'must be at least 1 character')
.max(255, 'must be 255 characters or less')
.test('is-valid-dir-name', function(value) {
.test('is-valid-collection-name', function(value) {
const isValid = validateName(value);
return isValid ? true : this.createError({ message: validateNameError(value) });
})
@@ -92,7 +93,7 @@ const CloneCollection = ({ onClose, collection }) => {
className="block textbox mt-2 w-full"
onChange={(e) => {
formik.handleChange(e);
!isEditingFilename && formik.setFieldValue('collectionFolderName', sanitizeName(e.target.value));
!isEditing && formik.setFieldValue('collectionFolderName', sanitizeName(e.target.value));
}}
autoComplete="off"
autoCorrect="off"
@@ -128,41 +129,51 @@ const CloneCollection = ({ onClose, collection }) => {
Browse
</span>
</div>
{isEditingFilename ?
<>
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="block font-semibold">
Directory Name
</label>
<IconArrowBackUp
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditingFilename(false)}
/>
</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 ?
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="block font-semibold">
Folder Name
</label>
<IconArrowBackUp
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(false)}
/>
</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 || ''}
/>
</div>
:
<PathDisplay
filename={formik.values.collectionFolderName}
showExtension={false}
isEditingFilename={isEditingFilename}
toggleEditingFilename={toggleEditingFilename}
/>
<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>

View File

@@ -6,24 +6,23 @@ import Modal from 'components/Modal';
import { useDispatch } from 'react-redux';
import { isItemAFolder } from 'utils/tabs';
import { cloneItem } from 'providers/ReduxStore/slices/collections/actions';
import { IconArrowBackUp } from '@tabler/icons';
import * as path from 'path';
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';
const CloneCollectionItem = ({ collection, item, onClose }) => {
const dispatch = useDispatch();
const isFolder = isItemAFolder(item);
const inputRef = useRef();
const [isEditingFilename, toggleEditingFilename] = useState(false);
const [isEditing, toggleEditing] = useState(false);
const itemName = item?.name;
const itemType = item?.type;
const itemFilename = item?.filename ? path.parse(item?.filename).name : '';
const formik = useFormik({
enableReinitialize: true,
initialValues: {
name: itemName,
filename: sanitizeName(itemFilename)
name: `${itemName} copy`,
filename: `${sanitizeName(itemName)} copy`
},
validationSchema: Yup.object({
name: Yup.string()
@@ -34,7 +33,7 @@ const CloneCollectionItem = ({ collection, item, onClose }) => {
.min(1, 'must be at least 1 character')
.max(255, 'must be 255 characters or less')
.required('name is required')
.test('is-valid-filename', function(value) {
.test('is-valid-name', function(value) {
const isValid = validateName(value);
return isValid ? true : this.createError({ message: validateNameError(value) });
})
@@ -71,7 +70,7 @@ const CloneCollectionItem = ({ collection, item, onClose }) => {
<form className="bruno-form" onSubmit={e => e.preventDefault()}>
<div>
<label htmlFor="name" className="block font-semibold">
{isFolder ? 'Folder' : 'Request'} Name
Name
</label>
<input
id="collection-item-name"
@@ -86,23 +85,23 @@ const CloneCollectionItem = ({ collection, item, onClose }) => {
spellCheck="false"
onChange={e => {
formik.setFieldValue('name', e.target.value);
!isEditingFilename && formik.setFieldValue('filename', sanitizeName(e.target.value));
!isEditing && formik.setFieldValue('filename', sanitizeName(e.target.value));
}}
value={formik.values.name || ''}
/>
{formik.touched.name && formik.errors.name ? <div className="text-red-500">{formik.errors.name}</div> : null}
</div>
{isEditingFilename ? (
{isEditing ? (
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="block font-semibold">
{isFolder ? 'Directory' : 'File'} Name
{isFolder ? 'Folder' : 'File'} Name
</label>
<IconArrowBackUp
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditingFilename(false)}
onClick={() => toggleEditing(false)}
/>
</div>
<div className='relative flex flex-row gap-1 items-center justify-between'>
@@ -123,15 +122,25 @@ const CloneCollectionItem = ({ collection, item, onClose }) => {
</div>
</div>
) : (
<PathDisplay
collection={collection}
item={item}
filename={formik.values.filename}
showExtension={itemType !== 'folder'}
isEditingFilename={isEditingFilename}
toggleEditingFilename={toggleEditingFilename}
showDirectory={true}
/>
<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
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>

View File

@@ -1,6 +1,6 @@
import React from 'react';
import Modal from 'components/Modal';
import * as path from 'path';
import path from 'utils/common/path';
const CollectionItemInfo = ({ collection, item, onClose }) => {
const { pathname: collectionPathname } = collection;

View File

@@ -6,7 +6,7 @@ import { useDispatch } from 'react-redux';
import { isItemAFolder } from 'utils/tabs';
import { renameItem, saveRequest } from 'providers/ReduxStore/slices/collections/actions';
import path from 'utils/common/path';
import { IconArrowBackUp } from '@tabler/icons';
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';
@@ -16,7 +16,7 @@ const RenameCollectionItem = ({ collection, item, onClose }) => {
const dispatch = useDispatch();
const isFolder = isItemAFolder(item);
const inputRef = useRef();
const [isEditingFilename, toggleEditingFilename] = useState(false);
const [isEditing, toggleEditing] = useState(false);
const itemName = item?.name;
const itemType = item?.type;
const itemFilename = item?.filename ? path.parse(item?.filename).name : '';
@@ -35,7 +35,7 @@ const RenameCollectionItem = ({ collection, item, onClose }) => {
.min(1, 'must be at least 1 character')
.max(255, 'must be 255 characters or less')
.required('name is required')
.test('is-valid-filename', function(value) {
.test('is-valid-name', function(value) {
const isValid = validateName(value);
return isValid ? true : this.createError({ message: validateNameError(value) });
})
@@ -90,7 +90,7 @@ const RenameCollectionItem = ({ collection, item, onClose }) => {
<form className="bruno-form" onSubmit={e => {e.preventDefault()}}>
<div className='flex flex-col mt-2'>
<label htmlFor="name" className="block font-semibold">
{isFolder ? 'Folder' : 'Request'} Name
Name
</label>
<input
id="collection-item-name"
@@ -104,24 +104,24 @@ const RenameCollectionItem = ({ collection, item, onClose }) => {
spellCheck="false"
onChange={e => {
formik.setFieldValue('name', e.target.value);
!isEditingFilename && formik.setFieldValue('filename', sanitizeName(e.target.value));
!isEditing && formik.setFieldValue('filename', sanitizeName(e.target.value));
}}
value={formik.values.name || ''}
/>
{formik.touched.name && formik.errors.name ? <div className="text-red-500">{formik.errors.name}</div> : null}
</div>
{isEditingFilename ? (
{isEditing ? (
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="block font-semibold">
{isFolder ? 'Directory' : 'File'} Name
{isFolder ? 'Folder' : 'File'} Name
</label>
<IconArrowBackUp
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditingFilename(false)}
onClick={() => toggleEditing(false)}
/>
</div>
<div className='relative flex flex-row gap-1 items-center justify-between'>
@@ -142,15 +142,25 @@ const RenameCollectionItem = ({ collection, item, onClose }) => {
</div>
</div>
) : (
<PathDisplay
collection={collection}
item={item}
filename={formik.values.filename}
showExtension={itemType !== 'folder'}
isEditingFilename={isEditingFilename}
toggleEditingFilename={toggleEditingFilename}
showDirectory={true}
/>
<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
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>

View File

@@ -24,7 +24,6 @@ import toast from 'react-hot-toast';
import StyledWrapper from './StyledWrapper';
import NetworkError from 'components/ResponsePane/NetworkError/index';
import CollectionItemInfo from './CollectionItemInfo/index';
import { findItemInCollection } from 'utils/collections';
import CollectionItemIcon from './CollectionItemIcon';
import { scrollToTheActiveTab } from 'utils/tabs';

View File

@@ -9,13 +9,13 @@ import Modal from 'components/Modal';
import { sanitizeName, validateName, validateNameError } from 'utils/common/regex';
import PathDisplay from 'components/PathDisplay/index';
import { useState } from 'react';
import { IconArrowBackUp } from '@tabler/icons';
import { IconArrowBackUp, IconEdit } from '@tabler/icons';
import Help from 'components/Help';
const CreateCollection = ({ onClose }) => {
const inputRef = useRef();
const dispatch = useDispatch();
const [isEditingFilename, toggleEditingFilename] = useState(false);
const [isEditing, toggleEditing] = useState(false);
const formik = useFormik({
enableReinitialize: true,
@@ -32,7 +32,7 @@ const CreateCollection = ({ onClose }) => {
collectionFolderName: Yup.string()
.min(1, 'must be at least 1 character')
.max(255, 'must be 255 characters or less')
.test('is-valid-dir-name', function(value) {
.test('is-valid-collection-name', function(value) {
const isValid = validateName(value);
return isValid ? true : this.createError({ message: validateNameError(value) });
})
@@ -86,7 +86,7 @@ const CreateCollection = ({ onClose }) => {
className="block textbox mt-2 w-full"
onChange={(e) => {
formik.handleChange(e);
!isEditingFilename && formik.setFieldValue('collectionFolderName', sanitizeName(e.target.value));
!isEditing && formik.setFieldValue('collectionFolderName', sanitizeName(e.target.value));
}}
autoComplete="off"
autoCorrect="off"
@@ -130,41 +130,51 @@ const CreateCollection = ({ onClose }) => {
Browse
</span>
</div>
{isEditingFilename ?
<>
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="block font-semibold">
Directory Name
</label>
<IconArrowBackUp
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditingFilename(false)}
/>
</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 ?
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="block font-semibold">
Folder Name
</label>
<IconArrowBackUp
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditing(false)}
/>
</div>
</>
:
<PathDisplay
filename={formik.values.collectionFolderName}
showExtension={false}
isEditingFilename={isEditingFilename}
toggleEditingFilename={toggleEditingFilename}
/>
<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>
:
<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>

View File

@@ -5,14 +5,15 @@ import * as Yup from 'yup';
import Modal from 'components/Modal';
import { useDispatch } from 'react-redux';
import { newFolder } from 'providers/ReduxStore/slices/collections/actions';
import { IconArrowBackUp } from '@tabler/icons';
import { IconArrowBackUp, IconEdit} from '@tabler/icons';
import { sanitizeName, validateName, validateNameError } from 'utils/common/regex';
import PathDisplay from 'components/PathDisplay';
import PathDisplay from 'components/PathDisplay/index';
import path from "utils/common/path";
const NewFolder = ({ collection, item, onClose }) => {
const dispatch = useDispatch();
const inputRef = useRef();
const [isEditingFilename, toggleEditingFilename] = useState(false);
const [isEditing, toggleEditing] = useState(false);
const formik = useFormik({
enableReinitialize: true,
@@ -65,7 +66,7 @@ const NewFolder = ({ collection, item, onClose }) => {
<form className="bruno-form" onSubmit={formik.handleSubmit}>
<div>
<label htmlFor="folderName" className="block font-semibold">
Folder Name
Name
</label>
<input
id="collection-name"
@@ -79,7 +80,7 @@ const NewFolder = ({ collection, item, onClose }) => {
spellCheck="false"
onChange={e => {
formik.setFieldValue('folderName', e.target.value);
!isEditingFilename && formik.setFieldValue('directoryName', sanitizeName(e.target.value));
!isEditing && formik.setFieldValue('directoryName', sanitizeName(e.target.value));
}}
value={formik.values.folderName || ''}
/>
@@ -88,17 +89,17 @@ const NewFolder = ({ collection, item, onClose }) => {
) : null}
</div>
{isEditingFilename ? (
{isEditing ? (
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="directoryName" className="block font-semibold">
Directory Name
Folder Name
</label>
<IconArrowBackUp
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditingFilename(false)}
onClick={() => toggleEditing(false)}
/>
</div>
<div className='relative flex flex-row gap-1 items-center justify-between'>
@@ -118,14 +119,25 @@ const NewFolder = ({ collection, item, onClose }) => {
</div>
</div>
) : (
<PathDisplay
collection={collection}
item={item}
filename={formik.values.directoryName}
showExtension={false}
isEditingFilename={isEditingFilename}
toggleEditingFilename={toggleEditingFilename}
/>
<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
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>

View File

@@ -2,6 +2,7 @@ import React, { useRef, useEffect, useCallback, forwardRef, useState } from 'rea
import { useFormik } from 'formik';
import * as Yup from 'yup';
import toast from 'react-hot-toast';
import path from 'utils/common/path';
import { uuid } from 'utils/common';
import Modal from 'components/Modal';
import { useDispatch } from 'react-redux';
@@ -11,7 +12,7 @@ import { addTab } from 'providers/ReduxStore/slices/tabs';
import HttpMethodSelector from 'components/RequestPane/QueryUrl/HttpMethodSelector';
import { getDefaultRequestPaneTab } from 'utils/collections';
import { getRequestFromCurlCommand } from 'utils/curl';
import { IconArrowBackUp, IconCaretDown } from '@tabler/icons';
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';
@@ -57,7 +58,7 @@ const NewRequest = ({ collection, item, isEphemeral, onClose }) => {
setCurlRequestTypeDetected(type);
};
const [isEditingFilename, toggleEditingFilename] = useState(false);
const [isEditing, toggleEditing] = useState(false);
const getRequestType = (collectionPresets) => {
if (!collectionPresets || !collectionPresets.requestType) {
@@ -309,7 +310,7 @@ const NewRequest = ({ collection, item, isEphemeral, onClose }) => {
spellCheck="false"
onChange={e => {
formik.setFieldValue('requestName', e.target.value);
!isEditingFilename && formik.setFieldValue('filename', sanitizeName(e.target.value));
!isEditing && formik.setFieldValue('filename', sanitizeName(e.target.value));
}}
value={formik.values.requestName || ''}
/>
@@ -317,7 +318,7 @@ const NewRequest = ({ collection, item, isEphemeral, onClose }) => {
<div className="text-red-500">{formik.errors.requestName}</div>
) : null}
</div>
{isEditingFilename ? (
{isEditing ? (
<div className="mt-4">
<div className="flex items-center justify-between">
<label htmlFor="filename" className="block font-semibold">
@@ -327,7 +328,7 @@ const NewRequest = ({ collection, item, isEphemeral, onClose }) => {
className="cursor-pointer opacity-50 hover:opacity-80"
size={16}
strokeWidth={1.5}
onClick={() => toggleEditingFilename(false)}
onClick={() => toggleEditing(false)}
/>
</div>
<div className='relative flex flex-row gap-1 items-center justify-between'>
@@ -348,13 +349,25 @@ const NewRequest = ({ collection, item, isEphemeral, onClose }) => {
</div>
</div>
) : (
<PathDisplay
collection={collection}
item={item}
filename={formik.values.filename}
isEditingFilename={isEditingFilename}
toggleEditingFilename={toggleEditingFilename}
/>
<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
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>

View File

@@ -187,6 +187,6 @@ export const stringifyIfNot = v => typeof v === 'string' ? v : String(v);
export const getEncoding = (headers) => {
// Parse the charset from content type: https://stackoverflow.com/a/33192813
const charsetMatch = /charset=([^()<>@,;:"/[\]?.=\s]*)/i.exec(headers['content-type'] || '');
const charsetMatch = /charset=([^()<>@,;:"/[\]?.=\s]*)/i.exec(headers?.['content-type'] || '');
return charsetMatch?.[1];
}

View File

@@ -2,7 +2,7 @@ const invalidCharacters = /[<>:"/\\|?*\x00-\x1F]/g; // replace invalid character
const reservedDeviceNames = /^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9])$/i;
const firstCharacter = /^[^.\s\-\<>:"/\\|?*\x00-\x1F]/; // no dot, space, or hyphen at start
const middleCharacters = /^[^<>:"/\\|?*\x00-\x1F]*$/; // no invalid characters
const lastCharacter = /[^.\s]$/; // no dot or space at end, hyphen allowed
const lastCharacter = /^[^.\s\-\<>:"/\\|?*\x00-\x1F]/; // no dot or space at end, hyphen allowed
export const variableNameRegex = /^[\w-.]*$/;
@@ -29,6 +29,7 @@ export const validateName = (name) => {
export const validateNameError = (name) => {
if (!name) return "Name cannot be empty.";
if (name.length > 255) {
return "Name cannot exceed 255 characters.";
}

View File

@@ -9,7 +9,6 @@
import parseCurlCommand from './parse-curl';
import * as querystring from 'query-string';
import * as jsesc from 'jsesc';
import * as path from 'path';
function getContentType(headers = {}) {
const contentType = Object.keys(headers).find((key) => key.toLowerCase() === 'content-type');