Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: request/folder names should be independent of the actual file/directory name #3094

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4904098
Update package.json
lohxt1 Aug 22, 2024
97a2baa
Update package.json
lohxt1 Aug 22, 2024
b1ca2ed
Update package.json
lohxt1 Aug 22, 2024
9d66d22
Update package.json
lohxt1 Aug 22, 2024
c60b428
Merge branch 'usebruno:main' into main
lohxt1 Aug 23, 2024
b5166bd
Merge branch 'usebruno:main' into main
lohxt1 Aug 23, 2024
96ed098
Merge branch 'usebruno:main' into main
lohxt1 Aug 24, 2024
e17fdcb
Merge branch 'usebruno:main' into main
lohxt1 Aug 26, 2024
defa05e
Merge branch 'usebruno:main' into main
lohxt1 Aug 26, 2024
00b1447
Merge branch 'usebruno:main' into main
lohxt1 Aug 27, 2024
f670920
Merge branch 'usebruno:main' into main
lohxt1 Aug 28, 2024
92529a1
Merge branch 'usebruno:main' into main
lohxt1 Aug 29, 2024
07a2bd9
Merge branch 'usebruno:main' into main
lohxt1 Sep 2, 2024
f9686a9
revert jest command
lohxt1 Sep 3, 2024
873f106
Merge branch 'usebruno:main' into main
lohxt1 Sep 4, 2024
cddfeac
Merge branch 'usebruno:main' into main
lohxt1 Sep 10, 2024
51f98c7
draft: request/folder name seperate from file/directory name
lohxt1 Sep 13, 2024
caf8ff5
feat: updates
lohxt1 Sep 13, 2024
7c19633
feat: updates
lohxt1 Sep 18, 2024
5d197b1
feat: updates
lohxt1 Sep 20, 2024
b95cc16
feat: added tests
lohxt1 Sep 20, 2024
1473f5e
feat: added comment for regex
lohxt1 Sep 20, 2024
f2bc753
feat: tests update
lohxt1 Sep 26, 2024
7e16d0e
Merge branch 'main' into feat/file-name--request-name--2
lohxt1 Nov 11, 2024
89b1114
fix: updates
lohxt1 Nov 14, 2024
932a801
Merge branch 'main' of lohxt1:lohxt1/bruno into feat/file-name--reque…
lohxt1 Feb 22, 2025
1ba9eb3
update rename fns logic
lohxt1 Feb 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 28 additions & 20 deletions packages/bruno-app/src/components/Modal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ const ModalFooter = ({
handleCancel,
confirmDisabled,
hideCancel,
hideFooter
hideFooter,
customFooter
}) => {
confirmText = confirmText || 'Save';
cancelText = cancelText || 'Cancel';
Expand All @@ -35,22 +36,27 @@ const ModalFooter = ({
}

return (
<div className="flex justify-end p-4 bruno-modal-footer">
<span className={hideCancel ? 'hidden' : 'mr-2'}>
<button type="button" onClick={handleCancel} className="btn btn-md btn-close">
{cancelText}
</button>
</span>
<span>
<button
type="submit"
className="submit btn btn-md btn-secondary"
disabled={confirmDisabled}
onClick={handleSubmit}
>
{confirmText}
</button>
</span>
<div className={`flex p-4 bruno-modal-footer ${customFooter ? 'justify-between' : 'justify-end'}`}>
<div>
{customFooter}
</div>
<div className='flex w-fit'>
<span className={hideCancel ? 'hidden' : 'mr-2'}>
<button type="button" onClick={handleCancel} className="btn btn-md btn-close">
{cancelText}
</button>
</span>
<span>
<button
type="submit"
className="submit btn btn-md btn-secondary"
disabled={confirmDisabled}
onClick={handleSubmit}
>
{confirmText}
</button>
</span>
</div>
</div>
);
};
Expand All @@ -71,7 +77,8 @@ const Modal = ({
disableCloseOnOutsideClick,
disableEscapeKey,
onClick,
closeModalFadeTimeout = 500
closeModalFadeTimeout = 500,
customFooter
}) => {
const modalRef = useRef(null);
const [isClosing, setIsClosing] = useState(false);
Expand Down Expand Up @@ -136,6 +143,7 @@ const Modal = ({
confirmDisabled={confirmDisabled}
hideCancel={hideCancel}
hideFooter={hideFooter}
customFooter={customFooter}
/>
</div>

Expand All @@ -146,8 +154,8 @@ const Modal = ({
disableCloseOnOutsideClick
? null
: () => {
closeModal({ type: 'backdrop' });
}
closeModal({ type: 'backdrop' });
}
}
/>
</StyledWrapper>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import styled from 'styled-components';

const Wrapper = styled.div`
.highlight {
color: ${(props) => props.theme.colors.text.yellow};
}
`;

export default Wrapper;
Original file line number Diff line number Diff line change
@@ -1,29 +1,47 @@
import React, { useRef, useEffect } from 'react';
import React, { useState, useRef, useEffect } from 'react';
import toast from 'react-hot-toast';
import { useFormik } from 'formik';
import * as Yup from 'yup';
import Modal from 'components/Modal';
import { useDispatch } from 'react-redux';
import { isItemAFolder } from 'utils/tabs';
import { cloneItem } from 'providers/ReduxStore/slices/collections/actions';
import { IconEdit, IconFile } from '@tabler/icons';
import * as path from 'path';
import { sanitizeName, validateName } from 'utils/common/regex';
import StyledWrapper from './StyledWrapper';

const CloneCollectionItem = ({ collection, item, onClose }) => {
const dispatch = useDispatch();
const isFolder = isItemAFolder(item);
const inputRef = useRef();
const [isEditingFilename, toggleEditingFilename] = 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: item.name
name: itemName,
filename: sanitizeName(itemFilename)
},
validationSchema: Yup.object({
name: Yup.string()
.min(1, 'must be at least 1 character')
.max(50, 'must be 50 characters or less')
.required('name is required'),
filename: Yup.string()
.min(1, 'must be at least 1 character')
.max(50, 'must be 50 characters or less')
.required('name is required')
.test('is-valid-filename', function(value) {
const isValid = validateName(value);
return isValid ? true : this.createError({ message: validateNameError(value) });
})
.test('not-reserved', `The file names "collection" and "folder" are reserved in bruno`, value => !['collection', 'folder'].includes(value))
}),
onSubmit: (values) => {
dispatch(cloneItem(values.name, item.uid, collection.uid))
dispatch(cloneItem(values.name, values.filename, item.uid, collection.uid))
.then(() => {
toast.success('Request cloned!');
onClose();
Expand All @@ -42,13 +60,29 @@ const CloneCollectionItem = ({ collection, item, onClose }) => {

const onSubmit = () => formik.handleSubmit();

const filename = formik.values.filename;
const name = formik.values.name;
const doNamesDiffer = filename !== name;

console.log("clone item", filename, itemFilename);

const filenameFooter = !isEditingFilename && filename ?
<div className={`flex flex-row gap-2 items-center w-full h-full`}>
<p className={`cursor-default whitespace-nowrap overflow-hidden text-ellipsis max-w-64 ${doNamesDiffer? 'highlight': 'opacity-50'}`} title={filename}>{filename}{itemType !== 'folder' ? '.bru' : ''}</p>
<IconEdit className="cursor-pointer opacity-50 hover:opacity-80" size={20} strokeWidth={1.5} onClick={() => toggleEditingFilename(v => !v)} />
</div>
:
<></>

return (
<StyledWrapper>
<Modal
size="sm"
size="md"
title={`Clone ${isFolder ? 'Folder' : 'Request'}`}
confirmText="Clone"
handleConfirm={onSubmit}
handleCancel={onClose}
customFooter={filenameFooter}
>
<form className="bruno-form" onSubmit={e => e.preventDefault()}>
<div>
Expand All @@ -66,13 +100,47 @@ const CloneCollectionItem = ({ collection, item, onClose }) => {
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
onChange={formik.handleChange}
onChange={e => {
formik.setFieldValue('name', e.target.value);
!isEditingFilename && 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>
{formik.touched.filename && formik.errors.filename ? <div className="text-red-500">{formik.errors.filename}</div> : null}
{
isEditingFilename ?
<div className="mt-4">
<label htmlFor="filename" className="block font-semibold">
{isFolder ? 'Directory' : 'File'} Name
</label>
<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>
{formik.touched.filename && formik.errors.filename ? (
<div className="text-red-500">{formik.errors.filename}</div>
) : null}
</div>
:
<></>
}
</form>
</Modal>
</StyledWrapper>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import Modal from 'components/Modal';
import * as path from 'path';

const CollectionItemInfo = ({ collection, item, onClose }) => {
const { pathname: collectionPathname } = collection;
const { name, filename, pathname, type } = item;
return (
<Modal
size="md"
title={`Info`}
handleCancel={onClose}
hideCancel={true}
hideFooter={true}
>
<div className="w-fit flex flex-col h-full">
<table className="w-full border-collapse">
<tbody>
<tr className="">
<td className="py-2 px-2 text-right opacity-50">Name&nbsp;:</td>
<td className="py-2 px-2">{name}</td>
</tr>
<tr className="">
<td className="py-2 px-2 text-right opacity-50">{type=='folder' ? 'Directory Name' : 'Filename'}&nbsp;:</td>
<td className="py-2 px-2 break-all">{filename}</td>
</tr>
<tr className="">
<td className="py-2 px-2 text-right opacity-50">Pathname&nbsp;:</td>
<td className="py-2 px-2 break-all">{path.relative(collectionPathname, pathname)}</td>
</tr>
</tbody>
</table>
</div>
</Modal>
);
};

export default CollectionItemInfo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import styled from 'styled-components';

const Wrapper = styled.div`
.highlight {
color: ${(props) => props.theme.colors.text.yellow};
}
`;

export default Wrapper;
Loading
Loading