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:
nitin
2024-08-05 20:51:27 +05:30
committed by GitHub
parent c7ba6d4e9f
commit ed0102ec58
2 changed files with 66 additions and 13 deletions

View File

@ -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"

View File

@ -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>