Persist table cell values on cell close (#655)
* Persist table cell values on cell close * Apply to all cells
This commit is contained in:
@ -1,3 +1,5 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { CellCommentChip } from '@/comments/components/table/CellCommentChip';
|
import { CellCommentChip } from '@/comments/components/table/CellCommentChip';
|
||||||
import { useOpenTimelineRightDrawer } from '@/comments/hooks/useOpenTimelineRightDrawer';
|
import { useOpenTimelineRightDrawer } from '@/comments/hooks/useOpenTimelineRightDrawer';
|
||||||
import { EditableCellChip } from '@/ui/components/editable-cell/types/EditableChip';
|
import { EditableCellChip } from '@/ui/components/editable-cell/types/EditableChip';
|
||||||
@ -21,6 +23,8 @@ export function CompanyEditableNameChipCell({ company }: OwnProps) {
|
|||||||
const openCommentRightDrawer = useOpenTimelineRightDrawer();
|
const openCommentRightDrawer = useOpenTimelineRightDrawer();
|
||||||
const [updateCompany] = useUpdateCompanyMutation();
|
const [updateCompany] = useUpdateCompanyMutation();
|
||||||
|
|
||||||
|
const [internalValue, setInternalValue] = useState(company.name ?? '');
|
||||||
|
|
||||||
function handleCommentClick(event: React.MouseEvent<HTMLDivElement>) {
|
function handleCommentClick(event: React.MouseEvent<HTMLDivElement>) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@ -33,20 +37,17 @@ export function CompanyEditableNameChipCell({ company }: OwnProps) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setInternalValue(company.name ?? '');
|
||||||
|
}, [company.name]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditableCellChip
|
<EditableCellChip
|
||||||
value={company.name ?? ''}
|
value={internalValue}
|
||||||
placeholder="Name"
|
placeholder="Name"
|
||||||
picture={getLogoUrlFromDomainName(company.domainName)}
|
picture={getLogoUrlFromDomainName(company.domainName)}
|
||||||
id={company.id}
|
id={company.id}
|
||||||
changeHandler={(value: string) => {
|
changeHandler={setInternalValue}
|
||||||
updateCompany({
|
|
||||||
variables: {
|
|
||||||
id: company.id,
|
|
||||||
name: value,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
ChipComponent={CompanyChip}
|
ChipComponent={CompanyChip}
|
||||||
rightEndContents={[
|
rightEndContents={[
|
||||||
<CellCommentChip
|
<CellCommentChip
|
||||||
@ -54,6 +55,15 @@ export function CompanyEditableNameChipCell({ company }: OwnProps) {
|
|||||||
onClick={handleCommentClick}
|
onClick={handleCommentClick}
|
||||||
/>,
|
/>,
|
||||||
]}
|
]}
|
||||||
|
onSubmit={() =>
|
||||||
|
updateCompany({
|
||||||
|
variables: {
|
||||||
|
id: company.id,
|
||||||
|
name: internalValue,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onCancel={() => setInternalValue(company.name ?? '')}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { companyAddressFamilyState } from '@/companies/states/companyAddressFamilyState';
|
import { companyAddressFamilyState } from '@/companies/states/companyAddressFamilyState';
|
||||||
@ -14,19 +15,24 @@ export function EditableCompanyAddressCell() {
|
|||||||
companyAddressFamilyState(currentRowEntityId ?? ''),
|
companyAddressFamilyState(currentRowEntityId ?? ''),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [internalValue, setInternalValue] = useState(address ?? '');
|
||||||
|
useEffect(() => {
|
||||||
|
setInternalValue(address ?? '');
|
||||||
|
}, [address]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditableCellText
|
<EditableCellText
|
||||||
value={address ?? ''}
|
value={internalValue}
|
||||||
onChange={async (newAddress: string) => {
|
onChange={setInternalValue}
|
||||||
if (!currentRowEntityId) return;
|
onSubmit={() =>
|
||||||
|
updateCompany({
|
||||||
await updateCompany({
|
|
||||||
variables: {
|
variables: {
|
||||||
id: currentRowEntityId,
|
id: currentRowEntityId,
|
||||||
address: newAddress,
|
address: internalValue,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
}}
|
}
|
||||||
|
onCancel={() => setInternalValue(address ?? '')}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { companyDomainNameFamilyState } from '@/companies/states/companyDomainNameFamilyState';
|
import { companyDomainNameFamilyState } from '@/companies/states/companyDomainNameFamilyState';
|
||||||
@ -13,20 +14,24 @@ export function EditableCompanyDomainNameCell() {
|
|||||||
const name = useRecoilValue(
|
const name = useRecoilValue(
|
||||||
companyDomainNameFamilyState(currentRowEntityId ?? ''),
|
companyDomainNameFamilyState(currentRowEntityId ?? ''),
|
||||||
);
|
);
|
||||||
|
const [internalValue, setInternalValue] = useState(name ?? '');
|
||||||
|
useEffect(() => {
|
||||||
|
setInternalValue(name ?? '');
|
||||||
|
}, [name]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditableCellText
|
<EditableCellText
|
||||||
value={name ?? ''}
|
value={internalValue}
|
||||||
onChange={async (domainName: string) => {
|
onChange={setInternalValue}
|
||||||
if (!currentRowEntityId) return;
|
onSubmit={() =>
|
||||||
|
updateCompany({
|
||||||
await updateCompany({
|
|
||||||
variables: {
|
variables: {
|
||||||
id: currentRowEntityId,
|
id: currentRowEntityId,
|
||||||
domainName: domainName,
|
domainName: internalValue,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
}}
|
}
|
||||||
|
onCancel={() => setInternalValue(name ?? '')}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { companyEmployeesFamilyState } from '@/companies/states/companyEmployeesFamilyState';
|
import { companyEmployeesFamilyState } from '@/companies/states/companyEmployeesFamilyState';
|
||||||
@ -14,20 +15,26 @@ export function EditableCompanyEmployeesCell() {
|
|||||||
companyEmployeesFamilyState(currentRowEntityId ?? ''),
|
companyEmployeesFamilyState(currentRowEntityId ?? ''),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [internalValue, setInternalValue] = useState(employees ?? '');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setInternalValue(employees ?? '');
|
||||||
|
}, [employees]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// TODO: Create an EditableCellNumber component
|
// TODO: Create an EditableCellNumber component
|
||||||
<EditableCellText
|
<EditableCellText
|
||||||
value={employees ?? ''}
|
value={internalValue}
|
||||||
onChange={async (newEmployees: string) => {
|
onChange={setInternalValue}
|
||||||
if (!currentRowEntityId) return;
|
onSubmit={() =>
|
||||||
|
updateCompany({
|
||||||
await updateCompany({
|
|
||||||
variables: {
|
variables: {
|
||||||
id: currentRowEntityId,
|
id: currentRowEntityId,
|
||||||
employees: parseInt(newEmployees),
|
employees: parseInt(internalValue),
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
}}
|
}
|
||||||
|
onCancel={() => setInternalValue(employees ?? '')}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,8 @@ type OwnProps = {
|
|||||||
| null
|
| null
|
||||||
| undefined;
|
| undefined;
|
||||||
onChange: (firstName: string, lastName: string) => void;
|
onChange: (firstName: string, lastName: string) => void;
|
||||||
|
onSubmit?: () => void;
|
||||||
|
onCancel?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const NoEditModeContainer = styled.div`
|
const NoEditModeContainer = styled.div`
|
||||||
@ -28,7 +30,12 @@ const RightContainer = styled.div`
|
|||||||
margin-left: ${(props) => props.theme.spacing(1)};
|
margin-left: ${(props) => props.theme.spacing(1)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export function EditablePeopleFullName({ person, onChange }: OwnProps) {
|
export function EditablePeopleFullName({
|
||||||
|
person,
|
||||||
|
onChange,
|
||||||
|
onSubmit,
|
||||||
|
onCancel,
|
||||||
|
}: OwnProps) {
|
||||||
const openCommentRightDrawer = useOpenTimelineRightDrawer();
|
const openCommentRightDrawer = useOpenTimelineRightDrawer();
|
||||||
|
|
||||||
function handleDoubleTextChange(
|
function handleDoubleTextChange(
|
||||||
@ -61,6 +68,8 @@ export function EditablePeopleFullName({ person, onChange }: OwnProps) {
|
|||||||
firstValuePlaceholder="First name"
|
firstValuePlaceholder="First name"
|
||||||
secondValuePlaceholder="Last name"
|
secondValuePlaceholder="Last name"
|
||||||
onChange={handleDoubleTextChange}
|
onChange={handleDoubleTextChange}
|
||||||
|
onSubmit={onSubmit}
|
||||||
|
onCancel={onCancel}
|
||||||
nonEditModeContent={
|
nonEditModeContent={
|
||||||
<NoEditModeContainer>
|
<NoEditModeContainer>
|
||||||
<PersonChip
|
<PersonChip
|
||||||
|
|||||||
@ -72,7 +72,7 @@ export function PeopleCompanyCreateCell({ people }: OwnProps) {
|
|||||||
secondValuePlaceholder="Name"
|
secondValuePlaceholder="Name"
|
||||||
onChange={handleDoubleTextChange}
|
onChange={handleDoubleTextChange}
|
||||||
onSubmit={() => handleCompanyCreate(companyName, companyDomainName)}
|
onSubmit={() => handleCompanyCreate(companyName, companyDomainName)}
|
||||||
onExit={() => setIsCreating(false)}
|
onCancel={() => setIsCreating(false)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { peopleCityFamilyState } from '@/people/states/peopleCityFamilyState';
|
import { peopleCityFamilyState } from '@/people/states/peopleCityFamilyState';
|
||||||
@ -12,19 +13,25 @@ export function EditablePeopleCityCell() {
|
|||||||
|
|
||||||
const city = useRecoilValue(peopleCityFamilyState(currentRowEntityId ?? ''));
|
const city = useRecoilValue(peopleCityFamilyState(currentRowEntityId ?? ''));
|
||||||
|
|
||||||
|
const [internalValue, setInternalValue] = useState(city ?? '');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setInternalValue(city ?? '');
|
||||||
|
}, [city]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditableCellPhone
|
<EditableCellPhone
|
||||||
value={city ?? ''}
|
value={internalValue}
|
||||||
onChange={async (newCity: string) => {
|
onChange={setInternalValue}
|
||||||
if (!currentRowEntityId) return;
|
onSubmit={() =>
|
||||||
|
updatePerson({
|
||||||
await updatePerson({
|
|
||||||
variables: {
|
variables: {
|
||||||
id: currentRowEntityId,
|
id: currentRowEntityId,
|
||||||
city: newCity,
|
city: internalValue,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
}}
|
}
|
||||||
|
onCancel={() => setInternalValue(city ?? '')}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { peopleEmailFamilyState } from '@/people/states/peopleEmailFamilyState';
|
import { peopleEmailFamilyState } from '@/people/states/peopleEmailFamilyState';
|
||||||
@ -14,19 +15,25 @@ export function EditablePeopleEmailCell() {
|
|||||||
peopleEmailFamilyState(currentRowEntityId ?? ''),
|
peopleEmailFamilyState(currentRowEntityId ?? ''),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [internalValue, setInternalValue] = useState(email ?? '');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setInternalValue(email ?? '');
|
||||||
|
}, [email]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditableCellText
|
<EditableCellText
|
||||||
value={email ?? ''}
|
value={internalValue}
|
||||||
onChange={async (newEmail: string) => {
|
onChange={setInternalValue}
|
||||||
if (!currentRowEntityId) return;
|
onSubmit={() =>
|
||||||
|
updatePerson({
|
||||||
await updatePerson({
|
|
||||||
variables: {
|
variables: {
|
||||||
id: currentRowEntityId,
|
id: currentRowEntityId,
|
||||||
email: newEmail,
|
email: internalValue,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
}}
|
}
|
||||||
|
onCancel={() => setInternalValue(email ?? '')}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { EditablePeopleFullName } from '@/people/components/EditablePeopleFullName';
|
import { EditablePeopleFullName } from '@/people/components/EditablePeopleFullName';
|
||||||
@ -14,24 +15,38 @@ export function EditablePeopleFullNameCell() {
|
|||||||
peopleNameCellFamilyState(currentRowEntityId ?? ''),
|
peopleNameCellFamilyState(currentRowEntityId ?? ''),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [internalFirstName, setInternalFirstName] = useState(firstName ?? '');
|
||||||
|
const [internalLastName, setInternalLastName] = useState(lastName ?? '');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setInternalFirstName(firstName ?? '');
|
||||||
|
setInternalLastName(lastName ?? '');
|
||||||
|
}, [firstName, lastName]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditablePeopleFullName
|
<EditablePeopleFullName
|
||||||
person={{
|
person={{
|
||||||
id: currentRowEntityId ?? undefined,
|
id: currentRowEntityId ?? undefined,
|
||||||
_commentThreadCount: commentCount ?? undefined,
|
_commentThreadCount: commentCount ?? undefined,
|
||||||
firstName: firstName ?? undefined,
|
firstName: internalFirstName,
|
||||||
lastName: lastName ?? undefined,
|
lastName: internalLastName,
|
||||||
}}
|
}}
|
||||||
onChange={async (firstName: string, lastName: string) => {
|
onChange={(firstName, lastName) => {
|
||||||
if (!currentRowEntityId) return;
|
setInternalFirstName(firstName);
|
||||||
|
setInternalLastName(lastName);
|
||||||
await updatePerson({
|
}}
|
||||||
|
onSubmit={() =>
|
||||||
|
updatePerson({
|
||||||
variables: {
|
variables: {
|
||||||
id: currentRowEntityId,
|
id: currentRowEntityId,
|
||||||
firstName,
|
firstName: internalFirstName,
|
||||||
lastName,
|
lastName: internalLastName,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
}
|
||||||
|
onCancel={() => {
|
||||||
|
setInternalFirstName(firstName ?? '');
|
||||||
|
setInternalLastName(lastName ?? '');
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { peoplePhoneFamilyState } from '@/people/states/peoplePhoneFamilyState';
|
import { peoplePhoneFamilyState } from '@/people/states/peoplePhoneFamilyState';
|
||||||
@ -13,19 +14,26 @@ export function EditablePeoplePhoneCell() {
|
|||||||
const phone = useRecoilValue(
|
const phone = useRecoilValue(
|
||||||
peoplePhoneFamilyState(currentRowEntityId ?? ''),
|
peoplePhoneFamilyState(currentRowEntityId ?? ''),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [internalValue, setInternalValue] = useState(phone ?? '');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setInternalValue(phone ?? '');
|
||||||
|
}, [phone]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditableCellPhone
|
<EditableCellPhone
|
||||||
value={phone ?? ''}
|
value={internalValue}
|
||||||
onChange={async (newPhone: string) => {
|
onChange={setInternalValue}
|
||||||
if (!currentRowEntityId) return;
|
onSubmit={() =>
|
||||||
|
updatePerson({
|
||||||
await updatePerson({
|
|
||||||
variables: {
|
variables: {
|
||||||
id: currentRowEntityId,
|
id: currentRowEntityId,
|
||||||
phone: newPhone,
|
phone: internalValue,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
}}
|
}
|
||||||
|
onCancel={() => setInternalValue(phone ?? '')}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,8 @@ type OwnProps = {
|
|||||||
editModeHorizontalAlign?: 'left' | 'right';
|
editModeHorizontalAlign?: 'left' | 'right';
|
||||||
editModeVerticalPosition?: 'over' | 'below';
|
editModeVerticalPosition?: 'over' | 'below';
|
||||||
editHotkeysScope?: HotkeysScope;
|
editHotkeysScope?: HotkeysScope;
|
||||||
|
onSubmit?: () => void;
|
||||||
|
onCancel?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function EditableCell({
|
export function EditableCell({
|
||||||
@ -34,6 +36,8 @@ export function EditableCell({
|
|||||||
editModeContent,
|
editModeContent,
|
||||||
nonEditModeContent,
|
nonEditModeContent,
|
||||||
editHotkeysScope,
|
editHotkeysScope,
|
||||||
|
onSubmit,
|
||||||
|
onCancel,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
const { isCurrentCellInEditMode } = useCurrentCellEditMode();
|
const { isCurrentCellInEditMode } = useCurrentCellEditMode();
|
||||||
|
|
||||||
@ -45,6 +49,8 @@ export function EditableCell({
|
|||||||
<EditableCellEditMode
|
<EditableCellEditMode
|
||||||
editModeHorizontalAlign={editModeHorizontalAlign}
|
editModeHorizontalAlign={editModeHorizontalAlign}
|
||||||
editModeVerticalPosition={editModeVerticalPosition}
|
editModeVerticalPosition={editModeVerticalPosition}
|
||||||
|
onSubmit={onSubmit}
|
||||||
|
onCancel={onCancel}
|
||||||
>
|
>
|
||||||
{editModeContent}
|
{editModeContent}
|
||||||
</EditableCellEditMode>
|
</EditableCellEditMode>
|
||||||
|
|||||||
@ -1,13 +1,9 @@
|
|||||||
import { ReactElement, useRef } from 'react';
|
import { ReactElement, useRef } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys';
|
|
||||||
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
|
||||||
import { useListenClickOutsideArrayOfRef } from '@/ui/hooks/useListenClickOutsideArrayOfRef';
|
|
||||||
import { useMoveSoftFocus } from '@/ui/tables/hooks/useMoveSoftFocus';
|
|
||||||
import { overlayBackground } from '@/ui/themes/effects';
|
import { overlayBackground } from '@/ui/themes/effects';
|
||||||
|
|
||||||
import { useEditableCell } from './hooks/useEditableCell';
|
import { useRegisterCloseCellHandlers } from './hooks/useRegisterCloseCellHandlers';
|
||||||
|
|
||||||
export const EditableCellEditModeContainer = styled.div<OwnProps>`
|
export const EditableCellEditModeContainer = styled.div<OwnProps>`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -33,60 +29,20 @@ type OwnProps = {
|
|||||||
editModeHorizontalAlign?: 'left' | 'right';
|
editModeHorizontalAlign?: 'left' | 'right';
|
||||||
editModeVerticalPosition?: 'over' | 'below';
|
editModeVerticalPosition?: 'over' | 'below';
|
||||||
onOutsideClick?: () => void;
|
onOutsideClick?: () => void;
|
||||||
|
onCancel?: () => void;
|
||||||
|
onSubmit?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function EditableCellEditMode({
|
export function EditableCellEditMode({
|
||||||
editModeHorizontalAlign,
|
editModeHorizontalAlign,
|
||||||
editModeVerticalPosition,
|
editModeVerticalPosition,
|
||||||
children,
|
children,
|
||||||
|
onCancel,
|
||||||
|
onSubmit,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
const wrapperRef = useRef(null);
|
const wrapperRef = useRef(null);
|
||||||
|
|
||||||
const { closeEditableCell } = useEditableCell();
|
useRegisterCloseCellHandlers(wrapperRef, onSubmit, onCancel);
|
||||||
const { moveRight, moveLeft, moveDown } = useMoveSoftFocus();
|
|
||||||
|
|
||||||
useListenClickOutsideArrayOfRef([wrapperRef], () => {
|
|
||||||
closeEditableCell();
|
|
||||||
});
|
|
||||||
|
|
||||||
useScopedHotkeys(
|
|
||||||
'enter',
|
|
||||||
() => {
|
|
||||||
closeEditableCell();
|
|
||||||
moveDown();
|
|
||||||
},
|
|
||||||
InternalHotkeysScope.CellEditMode,
|
|
||||||
[closeEditableCell],
|
|
||||||
);
|
|
||||||
|
|
||||||
useScopedHotkeys(
|
|
||||||
'esc',
|
|
||||||
() => {
|
|
||||||
closeEditableCell();
|
|
||||||
},
|
|
||||||
InternalHotkeysScope.CellEditMode,
|
|
||||||
[closeEditableCell],
|
|
||||||
);
|
|
||||||
|
|
||||||
useScopedHotkeys(
|
|
||||||
'tab',
|
|
||||||
() => {
|
|
||||||
closeEditableCell();
|
|
||||||
moveRight();
|
|
||||||
},
|
|
||||||
InternalHotkeysScope.CellEditMode,
|
|
||||||
[closeEditableCell, moveRight],
|
|
||||||
);
|
|
||||||
|
|
||||||
useScopedHotkeys(
|
|
||||||
'shift+tab',
|
|
||||||
() => {
|
|
||||||
closeEditableCell();
|
|
||||||
moveLeft();
|
|
||||||
},
|
|
||||||
InternalHotkeysScope.CellEditMode,
|
|
||||||
[closeEditableCell, moveRight],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EditableCellEditModeContainer
|
<EditableCellEditModeContainer
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import { useSetHotkeysScope } from '@/hotkeys/hooks/useSetHotkeysScope';
|
|||||||
import { HotkeysScope } from '@/hotkeys/types/internal/HotkeysScope';
|
import { HotkeysScope } from '@/hotkeys/types/internal/HotkeysScope';
|
||||||
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
||||||
import { useCloseCurrentCellInEditMode } from '@/ui/tables/hooks/useClearCellInEditMode';
|
import { useCloseCurrentCellInEditMode } from '@/ui/tables/hooks/useClearCellInEditMode';
|
||||||
import { isSoftFocusActiveState } from '@/ui/tables/states/isSoftFocusActiveState';
|
|
||||||
import { isSomeInputInEditModeState } from '@/ui/tables/states/isSomeInputInEditModeState';
|
import { isSomeInputInEditModeState } from '@/ui/tables/states/isSomeInputInEditModeState';
|
||||||
|
|
||||||
import { useCurrentCellEditMode } from './useCurrentCellEditMode';
|
import { useCurrentCellEditMode } from './useCurrentCellEditMode';
|
||||||
@ -30,7 +29,6 @@ export function useEditableCell() {
|
|||||||
|
|
||||||
if (!isSomeInputInEditMode) {
|
if (!isSomeInputInEditMode) {
|
||||||
set(isSomeInputInEditModeState, true);
|
set(isSomeInputInEditModeState, true);
|
||||||
set(isSoftFocusActiveState, false);
|
|
||||||
|
|
||||||
setCurrentCellInEditMode();
|
setCurrentCellInEditMode();
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,66 @@
|
|||||||
|
import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys';
|
||||||
|
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
||||||
|
import { useListenClickOutsideArrayOfRef } from '@/ui/hooks/useListenClickOutsideArrayOfRef';
|
||||||
|
import { useMoveSoftFocus } from '@/ui/tables/hooks/useMoveSoftFocus';
|
||||||
|
|
||||||
|
import { useCurrentCellEditMode } from './useCurrentCellEditMode';
|
||||||
|
import { useEditableCell } from './useEditableCell';
|
||||||
|
|
||||||
|
export function useRegisterCloseCellHandlers(
|
||||||
|
wrapperRef: React.RefObject<HTMLDivElement>,
|
||||||
|
onSubmit?: () => void,
|
||||||
|
onCancel?: () => void,
|
||||||
|
) {
|
||||||
|
const { closeEditableCell } = useEditableCell();
|
||||||
|
const { isCurrentCellInEditMode } = useCurrentCellEditMode();
|
||||||
|
useListenClickOutsideArrayOfRef([wrapperRef], () => {
|
||||||
|
if (isCurrentCellInEditMode) {
|
||||||
|
onSubmit?.();
|
||||||
|
closeEditableCell();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const { moveRight, moveLeft, moveDown } = useMoveSoftFocus();
|
||||||
|
|
||||||
|
useScopedHotkeys(
|
||||||
|
'enter',
|
||||||
|
() => {
|
||||||
|
onSubmit?.();
|
||||||
|
closeEditableCell();
|
||||||
|
moveDown();
|
||||||
|
},
|
||||||
|
InternalHotkeysScope.CellEditMode,
|
||||||
|
[closeEditableCell, onSubmit, moveDown],
|
||||||
|
);
|
||||||
|
|
||||||
|
useScopedHotkeys(
|
||||||
|
'esc',
|
||||||
|
() => {
|
||||||
|
closeEditableCell();
|
||||||
|
onCancel?.();
|
||||||
|
},
|
||||||
|
InternalHotkeysScope.CellEditMode,
|
||||||
|
[closeEditableCell, onCancel],
|
||||||
|
);
|
||||||
|
|
||||||
|
useScopedHotkeys(
|
||||||
|
'tab',
|
||||||
|
() => {
|
||||||
|
onSubmit?.();
|
||||||
|
closeEditableCell();
|
||||||
|
moveRight();
|
||||||
|
},
|
||||||
|
InternalHotkeysScope.CellEditMode,
|
||||||
|
[closeEditableCell, onSubmit, moveRight],
|
||||||
|
);
|
||||||
|
|
||||||
|
useScopedHotkeys(
|
||||||
|
'shift+tab',
|
||||||
|
() => {
|
||||||
|
onSubmit?.();
|
||||||
|
closeEditableCell();
|
||||||
|
moveLeft();
|
||||||
|
},
|
||||||
|
InternalHotkeysScope.CellEditMode,
|
||||||
|
[closeEditableCell, onSubmit, moveRight],
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -14,6 +14,8 @@ type OwnProps = {
|
|||||||
secondValuePlaceholder: string;
|
secondValuePlaceholder: string;
|
||||||
nonEditModeContent: ReactElement;
|
nonEditModeContent: ReactElement;
|
||||||
onChange: (firstValue: string, secondValue: string) => void;
|
onChange: (firstValue: string, secondValue: string) => void;
|
||||||
|
onSubmit?: () => void;
|
||||||
|
onCancel?: () => void;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -23,6 +25,8 @@ export function EditableCellDoubleText({
|
|||||||
firstValuePlaceholder,
|
firstValuePlaceholder,
|
||||||
secondValuePlaceholder,
|
secondValuePlaceholder,
|
||||||
onChange,
|
onChange,
|
||||||
|
onSubmit,
|
||||||
|
onCancel,
|
||||||
nonEditModeContent,
|
nonEditModeContent,
|
||||||
loading,
|
loading,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
@ -50,6 +54,8 @@ export function EditableCellDoubleText({
|
|||||||
firstValuePlaceholder={firstValuePlaceholder}
|
firstValuePlaceholder={firstValuePlaceholder}
|
||||||
secondValuePlaceholder={secondValuePlaceholder}
|
secondValuePlaceholder={secondValuePlaceholder}
|
||||||
onChange={handleOnChange}
|
onChange={handleOnChange}
|
||||||
|
onSubmit={onSubmit}
|
||||||
|
onCancel={onCancel}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
nonEditModeContent={loading ? <CellSkeleton /> : nonEditModeContent}
|
nonEditModeContent={loading ? <CellSkeleton /> : nonEditModeContent}
|
||||||
|
|||||||
@ -15,8 +15,8 @@ type OwnProps = {
|
|||||||
firstValuePlaceholder: string;
|
firstValuePlaceholder: string;
|
||||||
secondValuePlaceholder: string;
|
secondValuePlaceholder: string;
|
||||||
onChange: (firstValue: string, secondValue: string) => void;
|
onChange: (firstValue: string, secondValue: string) => void;
|
||||||
onSubmit?: (firstValue: string, secondValue: string) => void;
|
onSubmit?: () => void;
|
||||||
onExit?: () => void;
|
onCancel?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
const StyledContainer = styled.div`
|
||||||
@ -37,7 +37,7 @@ export function EditableCellDoubleTextEditMode({
|
|||||||
secondValuePlaceholder,
|
secondValuePlaceholder,
|
||||||
onChange,
|
onChange,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
onExit,
|
onCancel,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
const [focusPosition, setFocusPosition] = useState<'left' | 'right'>('left');
|
const [focusPosition, setFocusPosition] = useState<'left' | 'right'>('left');
|
||||||
|
|
||||||
@ -57,9 +57,7 @@ export function EditableCellDoubleTextEditMode({
|
|||||||
() => {
|
() => {
|
||||||
closeCell();
|
closeCell();
|
||||||
moveDown();
|
moveDown();
|
||||||
if (onSubmit) {
|
onSubmit?.();
|
||||||
onSubmit(firstValue, secondValue);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
InternalHotkeysScope.CellDoubleTextInput,
|
InternalHotkeysScope.CellDoubleTextInput,
|
||||||
[closeCell],
|
[closeCell],
|
||||||
@ -68,9 +66,7 @@ export function EditableCellDoubleTextEditMode({
|
|||||||
useScopedHotkeys(
|
useScopedHotkeys(
|
||||||
Key.Escape,
|
Key.Escape,
|
||||||
() => {
|
() => {
|
||||||
if (onExit) {
|
onCancel?.();
|
||||||
onExit();
|
|
||||||
}
|
|
||||||
closeCell();
|
closeCell();
|
||||||
},
|
},
|
||||||
InternalHotkeysScope.CellDoubleTextInput,
|
InternalHotkeysScope.CellDoubleTextInput,
|
||||||
@ -84,9 +80,7 @@ export function EditableCellDoubleTextEditMode({
|
|||||||
setFocusPosition('right');
|
setFocusPosition('right');
|
||||||
secondValueInputRef.current?.focus();
|
secondValueInputRef.current?.focus();
|
||||||
} else {
|
} else {
|
||||||
if (onExit) {
|
onSubmit?.();
|
||||||
onExit();
|
|
||||||
}
|
|
||||||
closeCell();
|
closeCell();
|
||||||
moveRight();
|
moveRight();
|
||||||
}
|
}
|
||||||
@ -102,6 +96,7 @@ export function EditableCellDoubleTextEditMode({
|
|||||||
setFocusPosition('left');
|
setFocusPosition('left');
|
||||||
firstValueInputRef.current?.focus();
|
firstValueInputRef.current?.focus();
|
||||||
} else {
|
} else {
|
||||||
|
onSubmit?.();
|
||||||
closeCell();
|
closeCell();
|
||||||
moveLeft();
|
moveLeft();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,9 +9,17 @@ type OwnProps = {
|
|||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
value: string;
|
value: string;
|
||||||
onChange: (updated: string) => void;
|
onChange: (updated: string) => void;
|
||||||
|
onSubmit?: () => void;
|
||||||
|
onCancel?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function EditableCellPhone({ value, placeholder, onChange }: OwnProps) {
|
export function EditableCellPhone({
|
||||||
|
value,
|
||||||
|
placeholder,
|
||||||
|
onChange,
|
||||||
|
onSubmit,
|
||||||
|
onCancel,
|
||||||
|
}: OwnProps) {
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const [inputValue, setInputValue] = useState(value);
|
const [inputValue, setInputValue] = useState(value);
|
||||||
|
|
||||||
@ -34,6 +42,8 @@ export function EditableCellPhone({ value, placeholder, onChange }: OwnProps) {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
nonEditModeContent={<InplaceInputPhoneDisplayMode value={inputValue} />}
|
nonEditModeContent={<InplaceInputPhoneDisplayMode value={inputValue} />}
|
||||||
|
onSubmit={onSubmit}
|
||||||
|
onCancel={onCancel}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,8 @@ type OwnProps = {
|
|||||||
onChange: (newValue: string) => void;
|
onChange: (newValue: string) => void;
|
||||||
editModeHorizontalAlign?: 'left' | 'right';
|
editModeHorizontalAlign?: 'left' | 'right';
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
|
onSubmit?: () => void;
|
||||||
|
onCancel?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function EditableCellText({
|
export function EditableCellText({
|
||||||
@ -20,6 +22,8 @@ export function EditableCellText({
|
|||||||
onChange,
|
onChange,
|
||||||
editModeHorizontalAlign,
|
editModeHorizontalAlign,
|
||||||
loading,
|
loading,
|
||||||
|
onCancel,
|
||||||
|
onSubmit,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
const [internalValue, setInternalValue] = useState(value);
|
const [internalValue, setInternalValue] = useState(value);
|
||||||
|
|
||||||
@ -41,6 +45,8 @@ export function EditableCellText({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
onSubmit={onSubmit}
|
||||||
|
onCancel={onCancel}
|
||||||
nonEditModeContent={
|
nonEditModeContent={
|
||||||
loading ? (
|
loading ? (
|
||||||
<CellSkeleton />
|
<CellSkeleton />
|
||||||
|
|||||||
@ -28,6 +28,8 @@ export type EditableChipProps = {
|
|||||||
commentThreadCount?: number;
|
commentThreadCount?: number;
|
||||||
onCommentClick?: (event: React.MouseEvent<HTMLDivElement>) => void;
|
onCommentClick?: (event: React.MouseEvent<HTMLDivElement>) => void;
|
||||||
rightEndContents?: ReactNode[];
|
rightEndContents?: ReactNode[];
|
||||||
|
onSubmit?: () => void;
|
||||||
|
onCancel?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: refactor
|
// TODO: refactor
|
||||||
@ -58,6 +60,8 @@ export function EditableCellChip({
|
|||||||
editModeHorizontalAlign,
|
editModeHorizontalAlign,
|
||||||
ChipComponent,
|
ChipComponent,
|
||||||
rightEndContents,
|
rightEndContents,
|
||||||
|
onSubmit,
|
||||||
|
onCancel,
|
||||||
}: EditableChipProps) {
|
}: EditableChipProps) {
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const [inputValue, setInputValue] = useState(value);
|
const [inputValue, setInputValue] = useState(value);
|
||||||
@ -87,6 +91,8 @@ export function EditableCellChip({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
onSubmit={onSubmit}
|
||||||
|
onCancel={onCancel}
|
||||||
nonEditModeContent={
|
nonEditModeContent={
|
||||||
<NoEditModeContainer>
|
<NoEditModeContainer>
|
||||||
<ChipComponent id={id} name={inputValue} picture={picture} />
|
<ChipComponent id={id} name={inputValue} picture={picture} />
|
||||||
|
|||||||
@ -31,6 +31,10 @@ export function useLeaveTableFocus() {
|
|||||||
.getLoadable(currentHotkeysScopeState)
|
.getLoadable(currentHotkeysScopeState)
|
||||||
.valueOrThrow();
|
.valueOrThrow();
|
||||||
|
|
||||||
|
if (isSomeInputInEditMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isSoftFocusActive && !isSomeInputInEditMode) {
|
if (!isSoftFocusActive && !isSomeInputInEditMode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user