Allow renaming names from uploaded files (#6358)
Hello @Bonapara,
Done with issue #6317. I had to create a new component, EditableField
([Component](56bf16b82b (diff-3a2362dbe6e21e46c55a673c80460bc201c62b36790b5df28b4c1f9f27377f59))),
because the existing InputText component has a fixed height
([link](https://github.com/twentyhq/twenty/blob/main/packages/twenty-front/src/modules/ui/input/components/TextInputV2.tsx#L55)),
which causes the attachment row to increase in size everytime clicked on
rename.
I’ve also updated the colors for the box border and box shadow as
specified in Figma.
Please let me know your thoughts.
Thanks
https://github.com/user-attachments/assets/d667269d-070e-4968-b63c-2ba9605de055
---------
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
@ -1,4 +1,9 @@
|
|||||||
import { IconDotsVertical, IconDownload, IconTrash } from 'twenty-ui';
|
import {
|
||||||
|
IconDotsVertical,
|
||||||
|
IconDownload,
|
||||||
|
IconPencil,
|
||||||
|
IconTrash,
|
||||||
|
} from 'twenty-ui';
|
||||||
|
|
||||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||||
@ -10,12 +15,14 @@ import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
|||||||
type AttachmentDropdownProps = {
|
type AttachmentDropdownProps = {
|
||||||
onDownload: () => void;
|
onDownload: () => void;
|
||||||
onDelete: () => void;
|
onDelete: () => void;
|
||||||
|
onRename: () => void;
|
||||||
scopeKey: string;
|
scopeKey: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AttachmentDropdown = ({
|
export const AttachmentDropdown = ({
|
||||||
onDownload,
|
onDownload,
|
||||||
onDelete,
|
onDelete,
|
||||||
|
onRename,
|
||||||
scopeKey,
|
scopeKey,
|
||||||
}: AttachmentDropdownProps) => {
|
}: AttachmentDropdownProps) => {
|
||||||
const dropdownId = `${scopeKey}-settings-field-active-action-dropdown`;
|
const dropdownId = `${scopeKey}-settings-field-active-action-dropdown`;
|
||||||
@ -32,6 +39,11 @@ export const AttachmentDropdown = ({
|
|||||||
closeDropdown();
|
closeDropdown();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRename = () => {
|
||||||
|
onRename();
|
||||||
|
closeDropdown();
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown
|
<Dropdown
|
||||||
dropdownId={dropdownId}
|
dropdownId={dropdownId}
|
||||||
@ -46,6 +58,11 @@ export const AttachmentDropdown = ({
|
|||||||
LeftIcon={IconDownload}
|
LeftIcon={IconDownload}
|
||||||
onClick={handleDownload}
|
onClick={handleDownload}
|
||||||
/>
|
/>
|
||||||
|
<MenuItem
|
||||||
|
text="Rename"
|
||||||
|
LeftIcon={IconPencil}
|
||||||
|
onClick={handleRename}
|
||||||
|
/>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
text="Delete"
|
text="Delete"
|
||||||
accent="danger"
|
accent="danger"
|
||||||
|
|||||||
@ -1,18 +1,20 @@
|
|||||||
import { useMemo } from 'react';
|
|
||||||
import { useTheme } from '@emotion/react';
|
|
||||||
import styled from '@emotion/styled';
|
|
||||||
import { IconCalendar } from 'twenty-ui';
|
|
||||||
|
|
||||||
import { AttachmentDropdown } from '@/activities/files/components/AttachmentDropdown';
|
import { AttachmentDropdown } from '@/activities/files/components/AttachmentDropdown';
|
||||||
import { AttachmentIcon } from '@/activities/files/components/AttachmentIcon';
|
import { AttachmentIcon } from '@/activities/files/components/AttachmentIcon';
|
||||||
import { Attachment } from '@/activities/files/types/Attachment';
|
import { Attachment } from '@/activities/files/types/Attachment';
|
||||||
import { downloadFile } from '@/activities/files/utils/downloadFile';
|
import { downloadFile } from '@/activities/files/utils/downloadFile';
|
||||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||||
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
|
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
|
||||||
|
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||||
import {
|
import {
|
||||||
FieldContext,
|
FieldContext,
|
||||||
GenericFieldContextType,
|
GenericFieldContextType,
|
||||||
} from '@/object-record/record-field/contexts/FieldContext';
|
} from '@/object-record/record-field/contexts/FieldContext';
|
||||||
|
import { TextInput } from '@/ui/input/components/TextInput';
|
||||||
|
import { useTheme } from '@emotion/react';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
|
import { useMemo, useState } from 'react';
|
||||||
|
import { IconCalendar } from 'twenty-ui';
|
||||||
|
|
||||||
import { formatToHumanReadableDate } from '~/utils/date-utils';
|
import { formatToHumanReadableDate } from '~/utils/date-utils';
|
||||||
import { getFileAbsoluteURI } from '~/utils/file/getFileAbsoluteURI';
|
import { getFileAbsoluteURI } from '~/utils/file/getFileAbsoluteURI';
|
||||||
|
|
||||||
@ -23,8 +25,8 @@ const StyledRow = styled.div`
|
|||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
padding: ${({ theme }) => theme.spacing(2)};
|
padding: ${({ theme }) => theme.spacing(2)};
|
||||||
|
height: 32px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledLeftContent = styled.div`
|
const StyledLeftContent = styled.div`
|
||||||
@ -57,6 +59,9 @@ const StyledLink = styled.a`
|
|||||||
|
|
||||||
export const AttachmentRow = ({ attachment }: { attachment: Attachment }) => {
|
export const AttachmentRow = ({ attachment }: { attachment: Attachment }) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
|
const [attachmentName, setAttachmentName] = useState(attachment.name);
|
||||||
|
|
||||||
const fieldContext = useMemo(
|
const fieldContext = useMemo(
|
||||||
() => ({ recoilScopeId: attachment?.id ?? '' }),
|
() => ({ recoilScopeId: attachment?.id ?? '' }),
|
||||||
[attachment?.id],
|
[attachment?.id],
|
||||||
@ -70,17 +75,47 @@ export const AttachmentRow = ({ attachment }: { attachment: Attachment }) => {
|
|||||||
deleteOneAttachment(attachment.id);
|
deleteOneAttachment(attachment.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { updateOneRecord: updateOneAttachment } = useUpdateOneRecord({
|
||||||
|
objectNameSingular: CoreObjectNameSingular.Attachment,
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleRename = () => {
|
||||||
|
setIsEditing(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOnBlur = () => {
|
||||||
|
setIsEditing(false);
|
||||||
|
updateOneAttachment({
|
||||||
|
idToUpdate: attachment.id,
|
||||||
|
updateOneRecordInput: { name: attachmentName },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOnChange = (newName: string) => {
|
||||||
|
setAttachmentName(newName);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FieldContext.Provider value={fieldContext as GenericFieldContextType}>
|
<FieldContext.Provider value={fieldContext as GenericFieldContextType}>
|
||||||
<StyledRow>
|
<StyledRow>
|
||||||
<StyledLeftContent>
|
<StyledLeftContent>
|
||||||
<AttachmentIcon attachmentType={attachment.type} />
|
<AttachmentIcon attachmentType={attachment.type} />
|
||||||
<StyledLink
|
{isEditing ? (
|
||||||
href={getFileAbsoluteURI(attachment.fullPath)}
|
<TextInput
|
||||||
target="__blank"
|
value={attachmentName}
|
||||||
>
|
onChange={handleOnChange}
|
||||||
{attachment.name}
|
onBlur={handleOnBlur}
|
||||||
</StyledLink>
|
autoFocus
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<StyledLink
|
||||||
|
href={getFileAbsoluteURI(attachment.fullPath)}
|
||||||
|
target="__blank"
|
||||||
|
>
|
||||||
|
{attachment.name}
|
||||||
|
</StyledLink>
|
||||||
|
)}
|
||||||
</StyledLeftContent>
|
</StyledLeftContent>
|
||||||
<StyledRightContent>
|
<StyledRightContent>
|
||||||
<StyledCalendarIconContainer>
|
<StyledCalendarIconContainer>
|
||||||
@ -93,6 +128,7 @@ export const AttachmentRow = ({ attachment }: { attachment: Attachment }) => {
|
|||||||
onDownload={() => {
|
onDownload={() => {
|
||||||
downloadFile(attachment.fullPath, attachment.name);
|
downloadFile(attachment.fullPath, attachment.name);
|
||||||
}}
|
}}
|
||||||
|
onRename={handleRename}
|
||||||
/>
|
/>
|
||||||
</StyledRightContent>
|
</StyledRightContent>
|
||||||
</StyledRow>
|
</StyledRow>
|
||||||
|
|||||||
Reference in New Issue
Block a user