Rework atom naming (#18240)
## Summary - **Enhanced the `matching-state-variable` ESLint rule** to enforce consistent naming for `ComponentState`, `FamilyState`, and `ComponentFamilyState` hooks — previously it only covered `useAtomState` and `useAtomStateValue` - **The rule now checks 12 hooks** across three categories: value hooks (`useAtomComponentStateValue`, `useAtomFamilyStateValue`, etc.), state hooks (`useAtomComponentState`, `useAtomComponentFamilyState`), and setter hooks (`useSetAtomState`, `useSetAtomComponentState`, `useSetAtomFamilyState`, `useSetAtomComponentFamilyState`) - **Fixed all 225 resulting lint violations** across 151 files, renaming variables to match their state atom names (e.g. `currentViewId` → `contextStoreCurrentViewId`, `selectedRecord` → `recordStore`). Cases where the same state is accessed with different family keys/instance IDs are suppressed with `eslint-disable-next-line`. ## Naming convention | Hook | State argument | Valid | Invalid | |------|---------------|-------|---------| | `useAtomStateValue` | `fooState` | `const foo = ...` | `const bar = ...` | | `useAtomComponentStateValue` | `fooComponentState` | `const foo = ...` | `const bar = ...` | | `useAtomFamilyStateValue` | `fooFamilyState` | `const foo = ...` | `const bar = ...` | | `useAtomComponentFamilyStateValue` | `fooComponentFamilyState` | `const foo = ...` | `const bar = ...` | | `useAtomState` | `fooState` | `const [foo, setFoo] = ...` | `const [bar, setBar] = ...` | | `useAtomComponentState` | `fooComponentState` | `const [foo, setFoo] = ...` | `const [bar, setBar] = ...` | | `useAtomComponentFamilyState` | `fooComponentFamilyState` | `const [foo, setFoo] = ...` | `const [bar, setBar] = ...` | | `useSetAtomState` | `fooState` | `const setFoo = ...` | `const setBar = ...` | | `useSetAtomComponentState` | `fooComponentState` | `const setFoo = ...` | `const setBar = ...` | | `useSetAtomFamilyState` | `fooFamilyState` | `const setFoo = ...` | `const setBar = ...` | | `useSetAtomComponentFamilyState` | `fooComponentFamilyState` | `const setFoo = ...` | `const setBar = ...` |
This commit is contained in:
@@ -5,58 +5,131 @@ const ruleTester = new TSESLint.RuleTester();
|
||||
|
||||
ruleTester.run(RULE_NAME, rule, {
|
||||
valid: [
|
||||
// useAtomState / useAtomStateValue (existing)
|
||||
{
|
||||
code: 'const variable = useAtomStateValue(variableState);',
|
||||
},
|
||||
{
|
||||
code: 'const [variable, setVariable] = useAtomState(variableState);',
|
||||
},
|
||||
// Component/Family hooks are not checked by this rule
|
||||
|
||||
// useAtomComponentStateValue / useAtomComponentState
|
||||
{
|
||||
code: 'const anything = useAtomComponentStateValue(variableComponentState);',
|
||||
code: 'const variable = useAtomComponentStateValue(variableComponentState);',
|
||||
},
|
||||
{
|
||||
code: 'const anything = useAtomFamilyStateValue(variableFamilyState);',
|
||||
code: 'const [variable, setVariable] = useAtomComponentState(variableComponentState);',
|
||||
},
|
||||
|
||||
// useAtomFamilyStateValue
|
||||
{
|
||||
code: 'const variable = useAtomFamilyStateValue(variableFamilyState, key);',
|
||||
},
|
||||
|
||||
// useAtomComponentFamilyStateValue / useAtomComponentFamilyState
|
||||
{
|
||||
code: 'const variable = useAtomComponentFamilyStateValue(variableComponentFamilyState, key);',
|
||||
},
|
||||
{
|
||||
code: 'const [anything, setAnything] = useAtomComponentFamilyState(variableComponentFamilyState);',
|
||||
code: 'const [variable, setVariable] = useAtomComponentFamilyState(variableComponentFamilyState, key);',
|
||||
},
|
||||
|
||||
// Setter hooks
|
||||
{
|
||||
code: 'const setVariable = useSetAtomState(variableState);',
|
||||
},
|
||||
{
|
||||
code: 'const setVariable = useSetAtomComponentState(variableComponentState);',
|
||||
},
|
||||
{
|
||||
code: 'const setVariable = useSetAtomFamilyState(variableFamilyState, key);',
|
||||
},
|
||||
{
|
||||
code: 'const setVariable = useSetAtomComponentFamilyState(variableComponentFamilyState, key);',
|
||||
},
|
||||
],
|
||||
invalid: [
|
||||
// useAtomStateValue - wrong variable name
|
||||
{
|
||||
code: 'const myValue = useAtomStateValue(variableState);',
|
||||
errors: [
|
||||
{
|
||||
messageId: 'invalidVariableName',
|
||||
},
|
||||
],
|
||||
errors: [{ messageId: 'invalidVariableName' }],
|
||||
},
|
||||
|
||||
// useAtomState - wrong variable and setter
|
||||
{
|
||||
code: 'const [myValue, setMyValue] = useAtomState(variableState);',
|
||||
errors: [
|
||||
{
|
||||
messageId: 'invalidVariableName',
|
||||
},
|
||||
{
|
||||
messageId: 'invalidSetterName',
|
||||
},
|
||||
{ messageId: 'invalidVariableName' },
|
||||
{ messageId: 'invalidSetterName' },
|
||||
],
|
||||
},
|
||||
{
|
||||
code: 'const [myValue] = useAtomState(variableState);',
|
||||
errors: [
|
||||
{
|
||||
messageId: 'invalidVariableName',
|
||||
},
|
||||
],
|
||||
errors: [{ messageId: 'invalidVariableName' }],
|
||||
},
|
||||
{
|
||||
code: 'const [, setMyValue] = useAtomState(variableState);',
|
||||
errors: [{ messageId: 'invalidSetterName' }],
|
||||
},
|
||||
|
||||
// useAtomComponentStateValue - wrong variable name
|
||||
{
|
||||
code: 'const myValue = useAtomComponentStateValue(variableComponentState);',
|
||||
errors: [{ messageId: 'invalidVariableName' }],
|
||||
},
|
||||
|
||||
// useAtomComponentState - wrong variable and setter
|
||||
{
|
||||
code: 'const [myValue, setMyValue] = useAtomComponentState(variableComponentState);',
|
||||
errors: [
|
||||
{
|
||||
messageId: 'invalidSetterName',
|
||||
},
|
||||
{ messageId: 'invalidVariableName' },
|
||||
{ messageId: 'invalidSetterName' },
|
||||
],
|
||||
},
|
||||
|
||||
// useAtomFamilyStateValue - wrong variable name
|
||||
{
|
||||
code: 'const myValue = useAtomFamilyStateValue(variableFamilyState, key);',
|
||||
errors: [{ messageId: 'invalidVariableName' }],
|
||||
},
|
||||
|
||||
// useAtomComponentFamilyStateValue - wrong variable name
|
||||
{
|
||||
code: 'const myValue = useAtomComponentFamilyStateValue(variableComponentFamilyState, key);',
|
||||
errors: [{ messageId: 'invalidVariableName' }],
|
||||
},
|
||||
|
||||
// useAtomComponentFamilyState - wrong variable and setter
|
||||
{
|
||||
code: 'const [myValue, setMyValue] = useAtomComponentFamilyState(variableComponentFamilyState, key);',
|
||||
errors: [
|
||||
{ messageId: 'invalidVariableName' },
|
||||
{ messageId: 'invalidSetterName' },
|
||||
],
|
||||
},
|
||||
|
||||
// useSetAtomState - wrong setter name
|
||||
{
|
||||
code: 'const myValue = useSetAtomState(variableState);',
|
||||
errors: [{ messageId: 'invalidSetterName' }],
|
||||
},
|
||||
|
||||
// useSetAtomComponentState - wrong setter name
|
||||
{
|
||||
code: 'const myValue = useSetAtomComponentState(variableComponentState);',
|
||||
errors: [{ messageId: 'invalidSetterName' }],
|
||||
},
|
||||
|
||||
// useSetAtomFamilyState - wrong setter name
|
||||
{
|
||||
code: 'const myValue = useSetAtomFamilyState(variableFamilyState, key);',
|
||||
errors: [{ messageId: 'invalidSetterName' }],
|
||||
},
|
||||
|
||||
// useSetAtomComponentFamilyState - wrong setter name
|
||||
{
|
||||
code: 'const myValue = useSetAtomComponentFamilyState(variableComponentFamilyState, key);',
|
||||
errors: [{ messageId: 'invalidSetterName' }],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -8,6 +8,37 @@ import { isIdentifier } from '@typescript-eslint/utils/ast-utils';
|
||||
// NOTE: The rule will be available in ESLint configs as "@nx/workspace-matching-state-variable"
|
||||
export const RULE_NAME = 'matching-state-variable';
|
||||
|
||||
const VALUE_HOOKS = [
|
||||
'useAtomStateValue',
|
||||
'useAtomComponentStateValue',
|
||||
'useAtomFamilyStateValue',
|
||||
'useAtomComponentFamilyStateValue',
|
||||
];
|
||||
|
||||
const STATE_HOOKS = [
|
||||
'useAtomState',
|
||||
'useAtomComponentState',
|
||||
'useAtomComponentFamilyState',
|
||||
];
|
||||
|
||||
const SETTER_HOOKS = [
|
||||
'useSetAtomState',
|
||||
'useSetAtomComponentState',
|
||||
'useSetAtomFamilyState',
|
||||
'useSetAtomComponentFamilyState',
|
||||
];
|
||||
|
||||
const ALL_HOOKS = [...VALUE_HOOKS, ...STATE_HOOKS, ...SETTER_HOOKS];
|
||||
|
||||
const SUFFIX_PATTERN =
|
||||
/(ComponentFamilyState|ComponentState|ScopedFamilyState|FamilyState|ScopedState|ScopedSelector|Selector|State)$/;
|
||||
|
||||
const getExpectedBaseName = (stateArgName: string): string =>
|
||||
stateArgName.replace(SUFFIX_PATTERN, '');
|
||||
|
||||
const getExpectedSetterName = (baseName: string): string =>
|
||||
`set${baseName.charAt(0).toUpperCase()}${baseName.slice(1)}`;
|
||||
|
||||
export const rule = ESLintUtils.RuleCreator(() => __filename)({
|
||||
name: RULE_NAME,
|
||||
meta: {
|
||||
@@ -30,104 +61,148 @@ export const rule = ESLintUtils.RuleCreator(() => __filename)({
|
||||
return {
|
||||
VariableDeclarator: (node: TSESTree.VariableDeclarator) => {
|
||||
if (
|
||||
node?.init?.type === AST_NODE_TYPES.CallExpression &&
|
||||
isIdentifier(node.init.callee) &&
|
||||
['useAtomState', 'useAtomStateValue'].includes(
|
||||
node.init.callee.name,
|
||||
)
|
||||
node?.init?.type !== AST_NODE_TYPES.CallExpression ||
|
||||
!isIdentifier(node.init.callee) ||
|
||||
!ALL_HOOKS.includes(node.init.callee.name)
|
||||
) {
|
||||
const stateNameBase = isIdentifier(node.init.arguments[0])
|
||||
? node.init.arguments[0].name
|
||||
: undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!stateNameBase) {
|
||||
return;
|
||||
}
|
||||
const hookName = node.init.callee.name;
|
||||
|
||||
const expectedVariableNameBase = stateNameBase.replace(
|
||||
/(State|Selector|ScopedState|ScopedFamilyState|ScopedSelector)$/,
|
||||
'',
|
||||
);
|
||||
const stateNameBase = isIdentifier(node.init.arguments[0])
|
||||
? node.init.arguments[0].name
|
||||
: undefined;
|
||||
|
||||
if (!stateNameBase) {
|
||||
return;
|
||||
}
|
||||
|
||||
const expectedVariableNameBase = getExpectedBaseName(stateNameBase);
|
||||
|
||||
if (SETTER_HOOKS.includes(hookName)) {
|
||||
if (isIdentifier(node.id)) {
|
||||
const actualVariableName = node.id.name;
|
||||
const actualName = node.id.name;
|
||||
const expectedSetterName =
|
||||
getExpectedSetterName(expectedVariableNameBase);
|
||||
|
||||
if (actualVariableName !== expectedVariableNameBase) {
|
||||
if (actualName !== expectedSetterName) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'invalidVariableName',
|
||||
messageId: 'invalidSetterName',
|
||||
data: {
|
||||
actualName: actualVariableName,
|
||||
expectedName: expectedVariableNameBase,
|
||||
hookName: stateNameBase,
|
||||
callee: node.init.callee.name,
|
||||
},
|
||||
fix: (fixer) => {
|
||||
return fixer.replaceText(node.id, expectedVariableNameBase);
|
||||
actualName,
|
||||
expectedName: expectedSetterName,
|
||||
},
|
||||
fix: (fixer) => fixer.replaceText(node.id, expectedSetterName),
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.id.type === AST_NODE_TYPES.ArrayPattern) {
|
||||
const actualVariableName =
|
||||
node.id.elements?.[0]?.type === AST_NODE_TYPES.Identifier
|
||||
? node.id.elements[0].name
|
||||
: undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
actualVariableName &&
|
||||
actualVariableName !== expectedVariableNameBase
|
||||
) {
|
||||
if (VALUE_HOOKS.includes(hookName)) {
|
||||
if (isIdentifier(node.id)) {
|
||||
const actualName = node.id.name;
|
||||
|
||||
if (actualName !== expectedVariableNameBase) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'invalidVariableName',
|
||||
data: {
|
||||
actual: actualVariableName,
|
||||
expected: expectedVariableNameBase,
|
||||
callee: node.init.callee.name,
|
||||
actualName,
|
||||
expectedName: expectedVariableNameBase,
|
||||
hookName: stateNameBase,
|
||||
callee: hookName,
|
||||
},
|
||||
fix: (fixer) =>
|
||||
fixer.replaceText(node.id, expectedVariableNameBase),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (isIdentifier(node.id)) {
|
||||
const actualVariableName = node.id.name;
|
||||
|
||||
if (actualVariableName !== expectedVariableNameBase) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'invalidVariableName',
|
||||
data: {
|
||||
actualName: actualVariableName,
|
||||
expectedName: expectedVariableNameBase,
|
||||
hookName: stateNameBase,
|
||||
callee: hookName,
|
||||
},
|
||||
fix: (fixer) =>
|
||||
fixer.replaceText(node.id, expectedVariableNameBase),
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.id.type === AST_NODE_TYPES.ArrayPattern) {
|
||||
const actualVariableName =
|
||||
node.id.elements?.[0]?.type === AST_NODE_TYPES.Identifier
|
||||
? node.id.elements[0].name
|
||||
: undefined;
|
||||
|
||||
if (
|
||||
actualVariableName &&
|
||||
actualVariableName !== expectedVariableNameBase
|
||||
) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'invalidVariableName',
|
||||
data: {
|
||||
actualName: actualVariableName,
|
||||
expectedName: expectedVariableNameBase,
|
||||
hookName: stateNameBase,
|
||||
callee: hookName,
|
||||
},
|
||||
fix: (fixer) => {
|
||||
if (node.id.type === AST_NODE_TYPES.ArrayPattern) {
|
||||
return fixer.replaceText(
|
||||
node.id.elements[0] as TSESTree.Node,
|
||||
expectedVariableNameBase,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (isIdentifier(node.id.elements[1])) {
|
||||
const actualSetterName = node.id.elements[1].name;
|
||||
const expectedSetterName =
|
||||
getExpectedSetterName(expectedVariableNameBase);
|
||||
|
||||
if (actualSetterName !== expectedSetterName) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'invalidSetterName',
|
||||
data: {
|
||||
hookName: stateNameBase,
|
||||
actualName: actualSetterName,
|
||||
expectedName: expectedSetterName,
|
||||
},
|
||||
fix: (fixer) => {
|
||||
if (node.id.type === AST_NODE_TYPES.ArrayPattern) {
|
||||
return fixer.replaceText(
|
||||
node.id.elements[0] as TSESTree.Node,
|
||||
expectedVariableNameBase,
|
||||
node.id.elements[1]!,
|
||||
expectedSetterName,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (isIdentifier(node.id.elements[1])) {
|
||||
const actualSetterName = node.id.elements[1].name;
|
||||
const expectedSetterName = `set${expectedVariableNameBase
|
||||
.charAt(0)
|
||||
.toUpperCase()}${expectedVariableNameBase.slice(1)}`;
|
||||
|
||||
if (actualSetterName !== expectedSetterName) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'invalidSetterName',
|
||||
data: {
|
||||
hookName: stateNameBase,
|
||||
actualName: actualSetterName,
|
||||
expectedName: expectedSetterName,
|
||||
},
|
||||
fix: (fixer) => {
|
||||
if (node.id.type === AST_NODE_TYPES.ArrayPattern) {
|
||||
return fixer.replaceText(
|
||||
node.id.elements[1]!,
|
||||
expectedSetterName,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+2
-2
@@ -26,7 +26,7 @@ export const ActionOpenSidePanelPage = ({
|
||||
|
||||
const { navigateCommandMenu } = useNavigateCommandMenu();
|
||||
|
||||
const setCommandMenuSearchState = useSetAtomState(commandMenuSearchState);
|
||||
const setCommandMenuSearch = useSetAtomState(commandMenuSearchState);
|
||||
|
||||
if (!actionConfig) {
|
||||
return null;
|
||||
@@ -42,7 +42,7 @@ export const ActionOpenSidePanelPage = ({
|
||||
});
|
||||
|
||||
if (shouldResetSearchState) {
|
||||
setCommandMenuSearchState('');
|
||||
setCommandMenuSearch('');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+2
-2
@@ -31,7 +31,7 @@ export const ActionDropdownItem = ({
|
||||
SelectableListComponentInstanceContext,
|
||||
);
|
||||
|
||||
const isSelected = useAtomComponentFamilyStateValue(
|
||||
const isSelectedItemId = useAtomComponentFamilyStateValue(
|
||||
isSelectedItemIdComponentFamilyState,
|
||||
action.key,
|
||||
selectableListInstanceId,
|
||||
@@ -40,7 +40,7 @@ export const ActionDropdownItem = ({
|
||||
return (
|
||||
<SelectableListItem itemId={action.key} onEnter={handleClick}>
|
||||
<MenuItem
|
||||
focused={isSelected}
|
||||
focused={isSelectedItemId}
|
||||
key={action.key}
|
||||
LeftIcon={action.Icon}
|
||||
onClick={handleClick}
|
||||
|
||||
+4
-4
@@ -13,17 +13,17 @@ export const CreateNewViewNoSelectionRecord = () => {
|
||||
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
|
||||
const { openDropdown } = useOpenDropdown();
|
||||
|
||||
const currentViewId = useAtomComponentStateValue(
|
||||
const contextStoreCurrentViewId = useAtomComponentStateValue(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
);
|
||||
|
||||
if (!currentViewId) {
|
||||
if (!contextStoreCurrentViewId) {
|
||||
throw new Error('Current view ID is not defined');
|
||||
}
|
||||
|
||||
const recordIndexId = getRecordIndexIdFromObjectNamePluralAndViewId(
|
||||
objectMetadataItem.namePlural,
|
||||
currentViewId,
|
||||
contextStoreCurrentViewId,
|
||||
);
|
||||
|
||||
const setViewPickerReferenceViewId = useSetAtomComponentState(
|
||||
@@ -34,7 +34,7 @@ export const CreateNewViewNoSelectionRecord = () => {
|
||||
const { setViewPickerMode } = useViewPickerMode(recordIndexId);
|
||||
|
||||
const handleAddViewButtonClick = () => {
|
||||
setViewPickerReferenceViewId(currentViewId);
|
||||
setViewPickerReferenceViewId(contextStoreCurrentViewId);
|
||||
setViewPickerMode('create-empty');
|
||||
openDropdown({
|
||||
dropdownComponentInstanceIdFromProps: VIEW_PICKER_DROPDOWN_ID,
|
||||
|
||||
+3
-3
@@ -12,17 +12,17 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
export const HideDeletedRecordsNoSelectionRecordAction = () => {
|
||||
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
|
||||
|
||||
const currentViewId = useAtomComponentStateValue(
|
||||
const contextStoreCurrentViewId = useAtomComponentStateValue(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
);
|
||||
|
||||
if (!currentViewId) {
|
||||
if (!contextStoreCurrentViewId) {
|
||||
throw new Error('Current view ID is not defined');
|
||||
}
|
||||
|
||||
const recordIndexId = getRecordIndexIdFromObjectNamePluralAndViewId(
|
||||
objectMetadataItem.namePlural,
|
||||
currentViewId,
|
||||
contextStoreCurrentViewId,
|
||||
);
|
||||
|
||||
const { toggleSoftDeleteFilterState } = useHandleToggleTrashColumnFilter({
|
||||
|
||||
+3
-3
@@ -8,17 +8,17 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
|
||||
export const SeeDeletedRecordsNoSelectionRecordAction = () => {
|
||||
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
|
||||
|
||||
const currentViewId = useAtomComponentStateValue(
|
||||
const contextStoreCurrentViewId = useAtomComponentStateValue(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
);
|
||||
|
||||
if (!currentViewId) {
|
||||
if (!contextStoreCurrentViewId) {
|
||||
throw new Error('Current view ID is not defined');
|
||||
}
|
||||
|
||||
const recordIndexId = getRecordIndexIdFromObjectNamePluralAndViewId(
|
||||
objectMetadataItem.namePlural,
|
||||
currentViewId,
|
||||
contextStoreCurrentViewId,
|
||||
);
|
||||
|
||||
const { handleToggleTrashColumnFilter, toggleSoftDeleteFilterState } =
|
||||
|
||||
+2
-2
@@ -35,7 +35,7 @@ export const useRunWorkflowRecordActions = ({
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
const isPageInEditMode = useAtomComponentStateValue(
|
||||
const contextStoreIsPageInEditMode = useAtomComponentStateValue(
|
||||
contextStoreIsPageInEditModeComponentState,
|
||||
);
|
||||
|
||||
@@ -138,7 +138,7 @@ export const useRunWorkflowRecordActions = ({
|
||||
position: index,
|
||||
Icon,
|
||||
isPinned:
|
||||
!isPageInEditMode &&
|
||||
!contextStoreIsPageInEditMode &&
|
||||
activeWorkflowVersion.trigger?.settings?.isPinned,
|
||||
shouldBeRegistered: () => true,
|
||||
component: (
|
||||
|
||||
+3
-6
@@ -13,17 +13,14 @@ export const AddToFavoritesSingleRecordAction = () => {
|
||||
|
||||
const { createFavorite } = useCreateFavorite();
|
||||
|
||||
const selectedRecord = useAtomFamilyStateValue(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
|
||||
|
||||
const handleClick = () => {
|
||||
if (!isDefined(selectedRecord)) {
|
||||
if (!isDefined(recordStore)) {
|
||||
return;
|
||||
}
|
||||
|
||||
createFavorite(selectedRecord, objectMetadataItem.nameSingular);
|
||||
createFavorite(recordStore, objectMetadataItem.nameSingular);
|
||||
};
|
||||
|
||||
return <Action onClick={handleClick} />;
|
||||
|
||||
+4
-7
@@ -7,19 +7,16 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
export const ExportNoteActionSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
|
||||
const selectedRecord = useAtomFamilyStateValue(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
|
||||
|
||||
const filename = `${(selectedRecord?.title || 'Untitled Note').replace(/[<>:"/\\|?*]/g, '-')}`;
|
||||
const filename = `${(recordStore?.title || 'Untitled Note').replace(/[<>:"/\\|?*]/g, '-')}`;
|
||||
|
||||
const handleClick = async () => {
|
||||
if (!isDefined(selectedRecord)) {
|
||||
if (!isDefined(recordStore)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const initialBody = selectedRecord.bodyV2?.blocknote;
|
||||
const initialBody = recordStore.bodyV2?.blocknote;
|
||||
|
||||
let parsedBody = [];
|
||||
|
||||
|
||||
+2
-5
@@ -9,12 +9,9 @@ import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAto
|
||||
export const CancelDashboardSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
|
||||
const selectedRecord = useAtomFamilyStateValue(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
|
||||
|
||||
const pageLayoutId = selectedRecord?.pageLayoutId;
|
||||
const pageLayoutId = recordStore?.pageLayoutId;
|
||||
|
||||
const { closeCommandMenu } = useCommandMenu();
|
||||
|
||||
|
||||
+2
-5
@@ -8,12 +8,9 @@ import { useResetLocationHash } from 'twenty-ui/utilities';
|
||||
export const EditDashboardSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
|
||||
const selectedRecord = useAtomFamilyStateValue(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
|
||||
|
||||
const pageLayoutId = selectedRecord?.pageLayoutId;
|
||||
const pageLayoutId = recordStore?.pageLayoutId;
|
||||
|
||||
const { setIsPageLayoutInEditMode } =
|
||||
useSetIsPageLayoutInEditMode(pageLayoutId);
|
||||
|
||||
+2
-5
@@ -9,12 +9,9 @@ import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAto
|
||||
export const SaveDashboardSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
|
||||
const selectedRecord = useAtomFamilyStateValue(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
|
||||
|
||||
const pageLayoutId = selectedRecord?.pageLayoutId;
|
||||
const pageLayoutId = recordStore?.pageLayoutId;
|
||||
|
||||
const { savePageLayout } = useSavePageLayout(pageLayoutId);
|
||||
|
||||
|
||||
+3
-3
@@ -8,9 +8,9 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SeeVersionWorkflowRunSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
const workflowRun = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
|
||||
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
|
||||
|
||||
if (!isDefined(workflowRun) || !isDefined(workflowRun?.workflowVersion?.id)) {
|
||||
if (!isDefined(recordStore) || !isDefined(recordStore?.workflowVersion?.id)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ export const SeeVersionWorkflowRunSingleRecordAction = () => {
|
||||
to={AppPath.RecordShowPage}
|
||||
params={{
|
||||
objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
|
||||
objectRecordId: workflowRun.workflowVersion.id,
|
||||
objectRecordId: recordStore.workflowVersion.id,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
+3
-3
@@ -8,9 +8,9 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SeeWorkflowWorkflowRunSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
const workflowRun = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
|
||||
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
|
||||
|
||||
if (!isDefined(workflowRun) || !isDefined(workflowRun?.workflow?.id)) {
|
||||
if (!isDefined(recordStore) || !isDefined(recordStore?.workflow?.id)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ export const SeeWorkflowWorkflowRunSingleRecordAction = () => {
|
||||
to={AppPath.RecordShowPage}
|
||||
params={{
|
||||
objectNameSingular: CoreObjectNameSingular.Workflow,
|
||||
objectRecordId: workflowRun.workflow.id,
|
||||
objectRecordId: recordStore.workflow.id,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
+3
-6
@@ -27,7 +27,7 @@ const SeeRunsWorkflowVersionSingleRecordActionContent = ({
|
||||
selectedRecordIds: [workflowWithCurrentVersion?.id],
|
||||
},
|
||||
},
|
||||
workflowVersion: {
|
||||
recordStore: {
|
||||
[ViewFilterOperand.IS]: {
|
||||
selectedRecordIds: [recordId],
|
||||
},
|
||||
@@ -40,12 +40,9 @@ const SeeRunsWorkflowVersionSingleRecordActionContent = ({
|
||||
|
||||
export const SeeRunsWorkflowVersionSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
const workflowVersion = useAtomFamilyStateValue(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
|
||||
|
||||
const workflowId = workflowVersion?.workflow?.id;
|
||||
const workflowId = recordStore?.workflow?.id;
|
||||
|
||||
if (!isDefined(workflowId)) {
|
||||
return null;
|
||||
|
||||
+3
-6
@@ -33,18 +33,15 @@ const SeeVersionsWorkflowVersionSingleRecordActionContent = ({
|
||||
|
||||
export const SeeVersionsWorkflowVersionSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
const workflowVersion = useAtomFamilyStateValue(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
|
||||
|
||||
if (!isDefined(workflowVersion) || !isDefined(workflowVersion.workflowId)) {
|
||||
if (!isDefined(recordStore) || !isDefined(recordStore.workflowId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<SeeVersionsWorkflowVersionSingleRecordActionContent
|
||||
workflowId={workflowVersion.workflowId}
|
||||
workflowId={recordStore.workflowId}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
+2
-5
@@ -7,17 +7,14 @@ import { AppPath } from 'twenty-shared/types';
|
||||
|
||||
export const SeeWorkflowWorkflowVersionSingleRecordAction = () => {
|
||||
const recordId = useSelectedRecordIdOrThrow();
|
||||
const workflowVersion = useAtomFamilyStateValue(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
|
||||
|
||||
return (
|
||||
<ActionLink
|
||||
to={AppPath.RecordShowPage}
|
||||
params={{
|
||||
objectNameSingular: CoreObjectNameSingular.Workflow,
|
||||
objectRecordId: workflowVersion?.workflow?.id,
|
||||
objectRecordId: recordStore?.workflow?.id,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@ import { useIcons } from 'twenty-ui/display';
|
||||
export const useRunWorkflowRecordAgnosticActions = () => {
|
||||
const { getIcon } = useIcons();
|
||||
|
||||
const isPageInEditMode = useAtomComponentStateValue(
|
||||
const contextStoreIsPageInEditMode = useAtomComponentStateValue(
|
||||
contextStoreIsPageInEditModeComponentState,
|
||||
);
|
||||
|
||||
@@ -50,7 +50,7 @@ export const useRunWorkflowRecordAgnosticActions = () => {
|
||||
shortLabel: name,
|
||||
position: index,
|
||||
isPinned:
|
||||
!isPageInEditMode &&
|
||||
!contextStoreIsPageInEditMode &&
|
||||
activeWorkflowVersion.trigger?.settings?.isPinned,
|
||||
Icon,
|
||||
shouldBeRegistered: () => true,
|
||||
|
||||
+3
-3
@@ -49,7 +49,7 @@ export const RecordIndexActionMenuDropdown = () => {
|
||||
const dropdownId = getActionMenuDropdownIdFromActionMenuId(actionMenuId);
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
|
||||
const actionMenuDropdownPosition = useAtomComponentStateValue(
|
||||
const recordIndexActionMenuDropdownPosition = useAtomComponentStateValue(
|
||||
recordIndexActionMenuDropdownPositionComponentState,
|
||||
dropdownId,
|
||||
);
|
||||
@@ -73,8 +73,8 @@ export const RecordIndexActionMenuDropdown = () => {
|
||||
dropdownPlacement="bottom-start"
|
||||
dropdownStrategy="absolute"
|
||||
dropdownOffset={{
|
||||
x: actionMenuDropdownPosition.x ?? 0,
|
||||
y: actionMenuDropdownPosition.y ?? 0,
|
||||
x: recordIndexActionMenuDropdownPosition.x ?? 0,
|
||||
y: recordIndexActionMenuDropdownPosition.y ?? 0,
|
||||
}}
|
||||
dropdownComponents={
|
||||
<DropdownContent>
|
||||
|
||||
+7
-7
@@ -52,7 +52,7 @@ export const RecordShowRightDrawerOpenRecordButton = ({
|
||||
targetObjectId: recordId,
|
||||
});
|
||||
|
||||
const activeTabIdInRightDrawer = useAtomComponentStateValue(
|
||||
const activeTabId = useAtomComponentStateValue(
|
||||
activeTabIdComponentState,
|
||||
tabListComponentId,
|
||||
);
|
||||
@@ -61,7 +61,7 @@ export const RecordShowRightDrawerOpenRecordButton = ({
|
||||
targetObjectId: recordId,
|
||||
});
|
||||
|
||||
const setActiveTabIdInRecordPage = useSetAtomComponentState(
|
||||
const setActiveTabId = useSetAtomComponentState(
|
||||
activeTabIdComponentState,
|
||||
tabListComponentIdInRecordPage,
|
||||
);
|
||||
@@ -83,14 +83,14 @@ export const RecordShowRightDrawerOpenRecordButton = ({
|
||||
|
||||
const handleOpenRecord = useCallback(() => {
|
||||
const tabIdToOpen =
|
||||
activeTabIdInRightDrawer === 'home'
|
||||
activeTabId === 'home'
|
||||
? objectNameSingular === CoreObjectNameSingular.Note ||
|
||||
objectNameSingular === CoreObjectNameSingular.Task
|
||||
? 'richText'
|
||||
: 'timeline'
|
||||
: activeTabIdInRightDrawer;
|
||||
: activeTabId;
|
||||
|
||||
setActiveTabIdInRecordPage(tabIdToOpen);
|
||||
setActiveTabId(tabIdToOpen);
|
||||
|
||||
const parentView = store.get(parentViewState);
|
||||
|
||||
@@ -110,14 +110,14 @@ export const RecordShowRightDrawerOpenRecordButton = ({
|
||||
closeCommandMenu();
|
||||
}, [
|
||||
actionMenuId,
|
||||
activeTabIdInRightDrawer,
|
||||
activeTabId,
|
||||
closeCommandMenu,
|
||||
closeDropdown,
|
||||
navigate,
|
||||
objectNameSingular,
|
||||
parentViewState,
|
||||
recordId,
|
||||
setActiveTabIdInRecordPage,
|
||||
setActiveTabId,
|
||||
store,
|
||||
]);
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ export const useRegisteredActions = (
|
||||
contextStoreCurrentViewTypeComponentState,
|
||||
);
|
||||
|
||||
const isFullTabWidgetInEditMode = useAtomComponentStateValue(
|
||||
const contextStoreIsPageInEditMode = useAtomComponentStateValue(
|
||||
contextStoreIsPageInEditModeComponentState,
|
||||
);
|
||||
|
||||
@@ -58,7 +58,7 @@ export const useRegisteredActions = (
|
||||
const permissionMap = usePermissionFlagMap();
|
||||
|
||||
const actionsToRegister = Object.values(actionsConfig).filter((action) => {
|
||||
if (isFullTabWidgetInEditMode) {
|
||||
if (contextStoreIsPageInEditMode) {
|
||||
return (
|
||||
isDefined(action.availableOn) &&
|
||||
action.availableOn.includes(ActionViewType.PAGE_EDIT_MODE)
|
||||
|
||||
+2
-2
@@ -98,7 +98,7 @@ export const useShouldActionBeRegisteredParams = ({
|
||||
useAtomComponentStateValue(contextStoreCurrentViewTypeComponentState) ===
|
||||
ContextStoreViewType.ShowPage;
|
||||
|
||||
const numberOfSelectedRecords = useAtomComponentStateValue(
|
||||
const contextStoreNumberOfSelectedRecords = useAtomComponentStateValue(
|
||||
contextStoreNumberOfSelectedRecordsComponentState,
|
||||
);
|
||||
|
||||
@@ -159,7 +159,7 @@ export const useShouldActionBeRegisteredParams = ({
|
||||
isShowPage,
|
||||
isSelectAll,
|
||||
selectedRecord,
|
||||
numberOfSelectedRecords,
|
||||
numberOfSelectedRecords: contextStoreNumberOfSelectedRecords,
|
||||
viewType: viewType ?? undefined,
|
||||
getTargetObjectReadPermission: getObjectReadPermission,
|
||||
getTargetObjectWritePermission: getObjectWritePermission,
|
||||
|
||||
+3
-3
@@ -140,7 +140,7 @@ describe('useActivityTargetObjectRecords', () => {
|
||||
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
const setRecordFromStore = useSetAtomFamilyState(
|
||||
const setRecordStore = useSetAtomFamilyState(
|
||||
recordStoreFamilyState,
|
||||
task.id,
|
||||
);
|
||||
@@ -151,14 +151,14 @@ describe('useActivityTargetObjectRecords', () => {
|
||||
|
||||
return {
|
||||
activityTargetObjectRecords,
|
||||
setRecordFromStore,
|
||||
setRecordStore,
|
||||
};
|
||||
},
|
||||
{ wrapper: Wrapper },
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.setRecordFromStore(task);
|
||||
result.current.setRecordStore(task);
|
||||
});
|
||||
|
||||
const activityTargetObjectRecords =
|
||||
|
||||
+3
-3
@@ -66,7 +66,7 @@ export const useUpdateActivityTargetFromCell = ({
|
||||
: isNoteTargetMigrated;
|
||||
|
||||
const store = useStore();
|
||||
const setActivityFromStore = useSetAtomFamilyState(
|
||||
const setRecordStore = useSetAtomFamilyState(
|
||||
recordStoreFamilyState,
|
||||
activityId,
|
||||
);
|
||||
@@ -194,7 +194,7 @@ export const useUpdateActivityTargetFromCell = ({
|
||||
await createOneActivityTarget(activityTargetInput);
|
||||
}
|
||||
|
||||
setActivityFromStore((currentActivity) => {
|
||||
setRecordStore((currentActivity) => {
|
||||
if (!isDefined(currentActivity)) {
|
||||
return null;
|
||||
}
|
||||
@@ -212,7 +212,7 @@ export const useUpdateActivityTargetFromCell = ({
|
||||
createOneActivityTarget,
|
||||
deleteOneActivityTarget,
|
||||
isMorphRelation,
|
||||
setActivityFromStore,
|
||||
setRecordStore,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
+3
-6
@@ -103,10 +103,7 @@ export const EventRow = ({
|
||||
|
||||
const { recordId } = useContext(TimelineActivityContext);
|
||||
|
||||
const recordFromStore = useAtomFamilyStateValue(
|
||||
recordStoreFamilyState,
|
||||
recordId,
|
||||
);
|
||||
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
|
||||
|
||||
const beautifiedCreatedAt = beautifyPastDateRelativeToNow(
|
||||
event.createdAt,
|
||||
@@ -120,7 +117,7 @@ export const EventRow = ({
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isUndefinedOrNull(recordFromStore)) {
|
||||
if (isUndefinedOrNull(recordStore)) {
|
||||
return null;
|
||||
}
|
||||
if (isUndefinedOrNull(mainObjectMetadataItem)) {
|
||||
@@ -129,7 +126,7 @@ export const EventRow = ({
|
||||
|
||||
const labelIdentifier = getObjectRecordIdentifier({
|
||||
objectMetadataItem: mainObjectMetadataItem,
|
||||
record: recordFromStore,
|
||||
record: recordStore,
|
||||
allowRequestsToTwentyIcons,
|
||||
});
|
||||
|
||||
|
||||
+3
-3
@@ -17,7 +17,7 @@ export const EventFieldDiffValueEffect = ({
|
||||
mainObjectMetadataItem: ObjectMetadataItem;
|
||||
fieldMetadataItem: FieldMetadataItem;
|
||||
}) => {
|
||||
const setEntity = useSetAtomFamilyState(
|
||||
const setRecordStore = useSetAtomFamilyState(
|
||||
recordStoreFamilyState,
|
||||
diffArtificialRecordStoreId,
|
||||
);
|
||||
@@ -31,13 +31,13 @@ export const EventFieldDiffValueEffect = ({
|
||||
[fieldMetadataItem.name]: diffRecord,
|
||||
};
|
||||
|
||||
setEntity(forgedObjectRecord);
|
||||
setRecordStore(forgedObjectRecord);
|
||||
}, [
|
||||
diffRecord,
|
||||
diffArtificialRecordStoreId,
|
||||
fieldMetadataItem.name,
|
||||
mainObjectMetadataItem.nameSingular,
|
||||
setEntity,
|
||||
setRecordStore,
|
||||
]);
|
||||
|
||||
return <></>;
|
||||
|
||||
@@ -277,12 +277,12 @@ const ThinkingToolStepRow = ({
|
||||
? unwrappedResult.data.result
|
||||
: unwrappedOutput;
|
||||
const toolTabListComponentInstanceId = `ai-thinking-tool-tabs-${part.toolCallId ?? rawToolName}-${rowIndex}`;
|
||||
const activeToolTabId = useAtomComponentStateValue(
|
||||
const activeTabId = useAtomComponentStateValue(
|
||||
activeTabIdComponentState,
|
||||
toolTabListComponentInstanceId,
|
||||
);
|
||||
const activeTab: ToolDetailsTab =
|
||||
activeToolTabId === 'input' ? 'input' : 'output';
|
||||
activeTabId === 'input' ? 'input' : 'output';
|
||||
const toolTabs = [
|
||||
{ id: 'output', title: t`Output` },
|
||||
{ id: 'input', title: t`Input` },
|
||||
|
||||
@@ -11,12 +11,12 @@ export const useAgentChatScrollToBottom = () => {
|
||||
AI_CHAT_SCROLL_WRAPPER_ID,
|
||||
);
|
||||
|
||||
const scrollBottom = useAtomComponentStateValue(
|
||||
const scrollWrapperScrollBottom = useAtomComponentStateValue(
|
||||
scrollWrapperScrollBottomComponentState,
|
||||
AI_CHAT_SCROLL_WRAPPER_ID,
|
||||
);
|
||||
|
||||
const isNearBottom = scrollBottom <= SCROLL_BOTTOM_THRESHOLD_PX;
|
||||
const isNearBottom = scrollWrapperScrollBottom <= SCROLL_BOTTOM_THRESHOLD_PX;
|
||||
|
||||
const scrollToBottom = () => {
|
||||
const { scrollWrapperElement } = getScrollWrapperElement();
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@ export const TwoFactorAuthenticationSetupEffect = () => {
|
||||
const { origin } = useOrigin();
|
||||
const loginToken = useAtomStateValue(loginTokenState);
|
||||
const qrCode = useAtomStateValue(qrCodeState);
|
||||
const setQrCodeState = useSetAtomState(qrCodeState);
|
||||
const setQrCode = useSetAtomState(qrCodeState);
|
||||
|
||||
const { t } = useLingui();
|
||||
|
||||
@@ -52,7 +52,7 @@ export const TwoFactorAuthenticationSetupEffect = () => {
|
||||
if (!initiateOTPProvisioningResult.data?.initiateOTPProvisioning.uri)
|
||||
return;
|
||||
|
||||
setQrCodeState(
|
||||
setQrCode(
|
||||
initiateOTPProvisioningResult.data?.initiateOTPProvisioning.uri,
|
||||
);
|
||||
} catch {
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ export const CustomSlashMenuListItem = ({
|
||||
}: CustomSlashMenuListItemProps) => {
|
||||
const { resetSelectedItem } = useSelectableList(SLASH_MENU_LIST_ID);
|
||||
|
||||
const isSelectedItem = useAtomComponentFamilyStateValue(
|
||||
const isSelectedItemId = useAtomComponentFamilyStateValue(
|
||||
isSelectedItemIdComponentFamilyState,
|
||||
item.title,
|
||||
);
|
||||
@@ -28,7 +28,7 @@ export const CustomSlashMenuListItem = ({
|
||||
return (
|
||||
<SelectableListItem itemId={item.title} onEnter={handleClick}>
|
||||
<MenuItemSuggestion
|
||||
selected={isSelectedItem}
|
||||
selected={isSelectedItemId}
|
||||
onClick={handleClick}
|
||||
LeftIcon={item.Icon}
|
||||
text={item.title}
|
||||
|
||||
@@ -75,19 +75,19 @@ export const useClientConfig = (): UseClientConfigResult => {
|
||||
|
||||
const setLabPublicFeatureFlags = useSetAtomState(labPublicFeatureFlagsState);
|
||||
|
||||
const setMicrosoftMessagingEnabled = useSetAtomState(
|
||||
const setIsMicrosoftMessagingEnabled = useSetAtomState(
|
||||
isMicrosoftMessagingEnabledState,
|
||||
);
|
||||
|
||||
const setMicrosoftCalendarEnabled = useSetAtomState(
|
||||
const setIsMicrosoftCalendarEnabled = useSetAtomState(
|
||||
isMicrosoftCalendarEnabledState,
|
||||
);
|
||||
|
||||
const setGoogleMessagingEnabled = useSetAtomState(
|
||||
const setIsGoogleMessagingEnabled = useSetAtomState(
|
||||
isGoogleMessagingEnabledState,
|
||||
);
|
||||
|
||||
const setGoogleCalendarEnabled = useSetAtomState(
|
||||
const setIsGoogleCalendarEnabled = useSetAtomState(
|
||||
isGoogleCalendarEnabledState,
|
||||
);
|
||||
|
||||
@@ -178,10 +178,10 @@ export const useClientConfig = (): UseClientConfigResult => {
|
||||
});
|
||||
setCanManageFeatureFlags(clientConfig?.canManageFeatureFlags);
|
||||
setLabPublicFeatureFlags(clientConfig?.publicFeatureFlags);
|
||||
setMicrosoftMessagingEnabled(clientConfig?.isMicrosoftMessagingEnabled);
|
||||
setMicrosoftCalendarEnabled(clientConfig?.isMicrosoftCalendarEnabled);
|
||||
setGoogleMessagingEnabled(clientConfig?.isGoogleMessagingEnabled);
|
||||
setGoogleCalendarEnabled(clientConfig?.isGoogleCalendarEnabled);
|
||||
setIsMicrosoftMessagingEnabled(clientConfig?.isMicrosoftMessagingEnabled);
|
||||
setIsMicrosoftCalendarEnabled(clientConfig?.isMicrosoftCalendarEnabled);
|
||||
setIsGoogleMessagingEnabled(clientConfig?.isGoogleMessagingEnabled);
|
||||
setIsGoogleCalendarEnabled(clientConfig?.isGoogleCalendarEnabled);
|
||||
setIsAttachmentPreviewEnabled(clientConfig?.isAttachmentPreviewEnabled);
|
||||
setIsConfigVariablesInDbEnabled(
|
||||
clientConfig?.isConfigVariablesInDbEnabled,
|
||||
@@ -222,8 +222,8 @@ export const useClientConfig = (): UseClientConfigResult => {
|
||||
setChromeExtensionId,
|
||||
setClientConfigApiStatus,
|
||||
setDomainConfiguration,
|
||||
setGoogleCalendarEnabled,
|
||||
setGoogleMessagingEnabled,
|
||||
setIsGoogleCalendarEnabled,
|
||||
setIsGoogleMessagingEnabled,
|
||||
setIsAnalyticsEnabled,
|
||||
setIsAttachmentPreviewEnabled,
|
||||
setIsConfigVariablesInDbEnabled,
|
||||
@@ -235,8 +235,8 @@ export const useClientConfig = (): UseClientConfigResult => {
|
||||
setIsClickHouseConfigured,
|
||||
setIsCloudflareIntegrationEnabled,
|
||||
setLabPublicFeatureFlags,
|
||||
setMicrosoftCalendarEnabled,
|
||||
setMicrosoftMessagingEnabled,
|
||||
setIsMicrosoftCalendarEnabled,
|
||||
setIsMicrosoftMessagingEnabled,
|
||||
setSentryConfig,
|
||||
setSupportChat,
|
||||
setAllowRequestsToTwentyIcons,
|
||||
|
||||
+9
-8
@@ -94,17 +94,17 @@ export const useCommandMenuItemFrontComponentActions = () => {
|
||||
useOpenFrontComponentInCommandMenu();
|
||||
const mountHeadlessFrontComponent = useMountHeadlessFrontComponent();
|
||||
|
||||
const isPageInEditMode = useAtomComponentStateValue(
|
||||
const contextStoreIsPageInEditMode = useAtomComponentStateValue(
|
||||
contextStoreIsPageInEditModeComponentState,
|
||||
);
|
||||
|
||||
const { actionMenuType } = useContext(ActionMenuContext);
|
||||
|
||||
const currentObjectMetadataItemId = useAtomComponentStateValue(
|
||||
const contextStoreCurrentObjectMetadataItemId = useAtomComponentStateValue(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
);
|
||||
|
||||
const targetedRecordsRule = useAtomComponentStateValue(
|
||||
const contextStoreTargetedRecordsRule = useAtomComponentStateValue(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
@@ -126,13 +126,14 @@ export const useCommandMenuItemFrontComponentActions = () => {
|
||||
) ?? [];
|
||||
|
||||
const selectedRecordCount =
|
||||
targetedRecordsRule.mode === 'selection'
|
||||
? targetedRecordsRule.selectedRecordIds.length
|
||||
contextStoreTargetedRecordsRule.mode === 'selection'
|
||||
? contextStoreTargetedRecordsRule.selectedRecordIds.length
|
||||
: 0;
|
||||
|
||||
const objectMatches = (item: CommandMenuItemWithFrontComponent) =>
|
||||
!isDefined(item.availabilityObjectMetadataId) ||
|
||||
item.availabilityObjectMetadataId === currentObjectMetadataItemId;
|
||||
item.availabilityObjectMetadataId ===
|
||||
contextStoreCurrentObjectMetadataItemId;
|
||||
|
||||
const globalItems = frontComponentItems.filter(
|
||||
(item) => item.availabilityType === CommandMenuItemAvailabilityType.GLOBAL,
|
||||
@@ -152,7 +153,7 @@ export const useCommandMenuItemFrontComponentActions = () => {
|
||||
item,
|
||||
scope: ActionScope.Global,
|
||||
index,
|
||||
isPinned: !isPageInEditMode && item.isPinned,
|
||||
isPinned: !contextStoreIsPageInEditMode && item.isPinned,
|
||||
getIcon,
|
||||
openFrontComponentInCommandMenu,
|
||||
mountHeadlessFrontComponent,
|
||||
@@ -164,7 +165,7 @@ export const useCommandMenuItemFrontComponentActions = () => {
|
||||
item,
|
||||
scope: ActionScope.RecordSelection,
|
||||
index,
|
||||
isPinned: !isPageInEditMode && item.isPinned,
|
||||
isPinned: !contextStoreIsPageInEditMode && item.isPinned,
|
||||
getIcon,
|
||||
openFrontComponentInCommandMenu,
|
||||
mountHeadlessFrontComponent,
|
||||
|
||||
@@ -39,17 +39,18 @@ export const CommandMenu = () => {
|
||||
commandMenuSearch,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line twenty/matching-state-variable
|
||||
const previousContextStoreCurrentObjectMetadataItemId =
|
||||
useAtomComponentStateValue(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
'command-menu-previous',
|
||||
);
|
||||
|
||||
const objectMetadataItemId = useAtomComponentStateValue(
|
||||
const contextStoreCurrentObjectMetadataItemId = useAtomComponentStateValue(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
);
|
||||
const currentObjectMetadataItem = objectMetadataItems.find(
|
||||
(item) => item.id === objectMetadataItemId,
|
||||
(item) => item.id === contextStoreCurrentObjectMetadataItemId,
|
||||
);
|
||||
|
||||
const commandGroups: ActionGroupConfig[] = [
|
||||
|
||||
@@ -29,7 +29,7 @@ type CommandMenuContainerProps = {
|
||||
export const CommandMenuContainer = ({
|
||||
children,
|
||||
}: CommandMenuContainerProps) => {
|
||||
const objectMetadataItemId = useAtomComponentStateValue(
|
||||
const contextStoreCurrentObjectMetadataItemId = useAtomComponentStateValue(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
COMMAND_MENU_COMPONENT_INSTANCE_ID,
|
||||
);
|
||||
@@ -38,17 +38,18 @@ export const CommandMenuContainer = ({
|
||||
const objectMetadataItems = useAtomStateValue(objectMetadataItemsState);
|
||||
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
(objectMetadataItem) => objectMetadataItem.id === objectMetadataItemId,
|
||||
(objectMetadataItem) =>
|
||||
objectMetadataItem.id === contextStoreCurrentObjectMetadataItemId,
|
||||
);
|
||||
|
||||
const currentViewId = useAtomComponentStateValue(
|
||||
const contextStoreCurrentViewId = useAtomComponentStateValue(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
COMMAND_MENU_COMPONENT_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const recordIndexId = getRecordIndexIdFromObjectNamePluralAndViewId(
|
||||
objectMetadataItem?.namePlural ?? '',
|
||||
currentViewId ?? '',
|
||||
contextStoreCurrentViewId ?? '',
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -27,11 +27,13 @@ export const CommandMenuFolderInfo = () => {
|
||||
const { t } = useLingui();
|
||||
const { getIcon } = useIcons();
|
||||
const commandMenuPageInfo = useAtomStateValue(commandMenuPageInfoState);
|
||||
const [shouldFocusTitleInput, setShouldFocusTitleInput] =
|
||||
useAtomComponentState(
|
||||
commandMenuShouldFocusTitleInputComponentState,
|
||||
commandMenuPageInfo.instanceId,
|
||||
);
|
||||
const [
|
||||
commandMenuShouldFocusTitleInput,
|
||||
setCommandMenuShouldFocusTitleInput,
|
||||
] = useAtomComponentState(
|
||||
commandMenuShouldFocusTitleInputComponentState,
|
||||
commandMenuPageInfo.instanceId,
|
||||
);
|
||||
const selectedNavigationMenuItemInEditMode = useAtomStateValue(
|
||||
selectedNavigationMenuItemInEditModeState,
|
||||
);
|
||||
@@ -106,8 +108,8 @@ export const CommandMenuFolderInfo = () => {
|
||||
onClickOutside={handleSave}
|
||||
onTab={handleSave}
|
||||
onShiftTab={handleSave}
|
||||
shouldFocus={shouldFocusTitleInput}
|
||||
onFocus={() => setShouldFocusTitleInput(false)}
|
||||
shouldFocus={commandMenuShouldFocusTitleInput}
|
||||
onFocus={() => setCommandMenuShouldFocusTitleInput(false)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
+4
-2
@@ -41,7 +41,9 @@ export const CommandMenuItemWithAddToNavigationDrag = ({
|
||||
dragIndex,
|
||||
}: CommandMenuItemWithAddToNavigationDragProps) => {
|
||||
const { t } = useLingui();
|
||||
const setRegistry = useSetAtomState(addToNavPayloadRegistryState);
|
||||
const setAddToNavPayloadRegistry = useSetAtomState(
|
||||
addToNavPayloadRegistryState,
|
||||
);
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
|
||||
const contextualDescription = isHovered
|
||||
@@ -59,7 +61,7 @@ export const CommandMenuItemWithAddToNavigationDrag = ({
|
||||
|
||||
const registerPayload = () => {
|
||||
if (dragIndex !== undefined) {
|
||||
setRegistry((prev) => new Map(prev).set(id, payload));
|
||||
setAddToNavPayloadRegistry((prev) => new Map(prev).set(id, payload));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -19,11 +19,13 @@ export const CommandMenuLinkInfo = () => {
|
||||
const theme = useTheme();
|
||||
const { t } = useLingui();
|
||||
const commandMenuPageInfo = useAtomStateValue(commandMenuPageInfoState);
|
||||
const [shouldFocusTitleInput, setShouldFocusTitleInput] =
|
||||
useAtomComponentState(
|
||||
commandMenuShouldFocusTitleInputComponentState,
|
||||
commandMenuPageInfo.instanceId,
|
||||
);
|
||||
const [
|
||||
commandMenuShouldFocusTitleInput,
|
||||
setCommandMenuShouldFocusTitleInput,
|
||||
] = useAtomComponentState(
|
||||
commandMenuShouldFocusTitleInputComponentState,
|
||||
commandMenuPageInfo.instanceId,
|
||||
);
|
||||
const selectedNavigationMenuItemInEditMode = useAtomStateValue(
|
||||
selectedNavigationMenuItemInEditModeState,
|
||||
);
|
||||
@@ -84,8 +86,8 @@ export const CommandMenuLinkInfo = () => {
|
||||
onClickOutside={handleSave}
|
||||
onTab={handleSave}
|
||||
onShiftTab={handleSave}
|
||||
shouldFocus={shouldFocusTitleInput}
|
||||
onFocus={() => setShouldFocusTitleInput(false)}
|
||||
shouldFocus={commandMenuShouldFocusTitleInput}
|
||||
onFocus={() => setCommandMenuShouldFocusTitleInput(false)}
|
||||
/>
|
||||
}
|
||||
label={t`link`}
|
||||
|
||||
+3
-3
@@ -7,16 +7,16 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const CommandMenuPageLayoutInfo = () => {
|
||||
const objectMetadataId = useAtomComponentStateValue(
|
||||
const contextStoreCurrentObjectMetadataItemId = useAtomComponentStateValue(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
);
|
||||
|
||||
if (!isDefined(objectMetadataId)) {
|
||||
if (!isDefined(contextStoreCurrentObjectMetadataItemId)) {
|
||||
throw new Error('Object metadata ID is not defined');
|
||||
}
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItemById({
|
||||
objectId: objectMetadataId,
|
||||
objectId: contextStoreCurrentObjectMetadataItemId,
|
||||
});
|
||||
|
||||
const isDashboardContext =
|
||||
|
||||
+13
-11
@@ -30,17 +30,19 @@ export const CommandMenuPageLayoutInfoContent = ({
|
||||
const commandMenuPage = useAtomStateValue(commandMenuPageState);
|
||||
const commandMenuPageInfo = useAtomStateValue(commandMenuPageInfoState);
|
||||
|
||||
const [shouldFocusTitleInput, setShouldFocusTitleInput] =
|
||||
useAtomComponentState(
|
||||
commandMenuShouldFocusTitleInputComponentState,
|
||||
commandMenuPageInfo.instanceId,
|
||||
);
|
||||
const [
|
||||
commandMenuShouldFocusTitleInput,
|
||||
setCommandMenuShouldFocusTitleInput,
|
||||
] = useAtomComponentState(
|
||||
commandMenuShouldFocusTitleInputComponentState,
|
||||
commandMenuPageInfo.instanceId,
|
||||
);
|
||||
|
||||
const handleTitleInputOpen = () => {
|
||||
setShouldFocusTitleInput(false);
|
||||
setCommandMenuShouldFocusTitleInput(false);
|
||||
};
|
||||
|
||||
const draftPageLayout = useAtomComponentStateValue(
|
||||
const pageLayoutDraft = useAtomComponentStateValue(
|
||||
pageLayoutDraftComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
@@ -50,7 +52,7 @@ export const CommandMenuPageLayoutInfoContent = ({
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const [openTabId] = useAtomComponentState(
|
||||
const [pageLayoutTabSettingsOpenTabId] = useAtomComponentState(
|
||||
pageLayoutTabSettingsOpenTabIdComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
@@ -63,9 +65,9 @@ export const CommandMenuPageLayoutInfoContent = ({
|
||||
|
||||
const headerInfo = usePageLayoutHeaderInfo({
|
||||
commandMenuPage,
|
||||
draftPageLayout,
|
||||
draftPageLayout: pageLayoutDraft,
|
||||
pageLayoutEditingWidgetId,
|
||||
openTabId,
|
||||
openTabId: pageLayoutTabSettingsOpenTabId,
|
||||
editedTitle,
|
||||
});
|
||||
|
||||
@@ -136,7 +138,7 @@ export const CommandMenuPageLayoutInfoContent = ({
|
||||
onClickOutside={saveTitle}
|
||||
onTab={saveTitle}
|
||||
onShiftTab={saveTitle}
|
||||
shouldFocus={shouldFocusTitleInput}
|
||||
shouldFocus={commandMenuShouldFocusTitleInput}
|
||||
onFocus={handleTitleInputOpen}
|
||||
/>
|
||||
}
|
||||
|
||||
+5
-5
@@ -39,7 +39,7 @@ export const CommandMenuWorkflowStepInfo = ({
|
||||
|
||||
const workflowId = useCommandMenuWorkflowIdOrThrow();
|
||||
|
||||
const workflowStepId = useAtomComponentStateValue(
|
||||
const commandMenuWorkflowStepId = useAtomComponentStateValue(
|
||||
commandMenuWorkflowStepIdComponentState,
|
||||
commandMenuPageInstanceId,
|
||||
);
|
||||
@@ -71,13 +71,13 @@ export const CommandMenuWorkflowStepInfo = ({
|
||||
id: undefined,
|
||||
};
|
||||
|
||||
const isTriggerStep = workflowStepId === TRIGGER_STEP_ID;
|
||||
const isTriggerStep = commandMenuWorkflowStepId === TRIGGER_STEP_ID;
|
||||
|
||||
const stepDefinition =
|
||||
isDefined(workflowStepId) && isDefined(trigger)
|
||||
isDefined(commandMenuWorkflowStepId) && isDefined(trigger)
|
||||
? isTriggerStep || isDefined(steps)
|
||||
? getStepDefinitionOrThrow({
|
||||
stepId: workflowStepId,
|
||||
stepId: commandMenuWorkflowStepId,
|
||||
trigger,
|
||||
steps,
|
||||
})
|
||||
@@ -109,7 +109,7 @@ export const CommandMenuWorkflowStepInfo = ({
|
||||
|
||||
if (
|
||||
!isDefined(workflowId) ||
|
||||
!isDefined(workflowStepId) ||
|
||||
!isDefined(commandMenuWorkflowStepId) ||
|
||||
!isDefined(workflowWithCurrentVersion?.currentVersion) ||
|
||||
!isDefined(stepDefinition) ||
|
||||
!isDefined(stepDefinition.definition)
|
||||
|
||||
+18
-15
@@ -60,19 +60,20 @@ const renderHooks = () => {
|
||||
viewableRecordNameSingularComponentState,
|
||||
'mocked-uuid',
|
||||
);
|
||||
const currentObjectMetadataItemId = useAtomComponentStateValue(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
'mocked-uuid',
|
||||
);
|
||||
const targetedRecordsRule = useAtomComponentStateValue(
|
||||
const contextStoreCurrentObjectMetadataItemId =
|
||||
useAtomComponentStateValue(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
'mocked-uuid',
|
||||
);
|
||||
const contextStoreTargetedRecordsRule = useAtomComponentStateValue(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
'mocked-uuid',
|
||||
);
|
||||
const numberOfSelectedRecords = useAtomComponentStateValue(
|
||||
const contextStoreNumberOfSelectedRecords = useAtomComponentStateValue(
|
||||
contextStoreNumberOfSelectedRecordsComponentState,
|
||||
'mocked-uuid',
|
||||
);
|
||||
const currentViewType = useAtomComponentStateValue(
|
||||
const contextStoreCurrentViewType = useAtomComponentStateValue(
|
||||
contextStoreCurrentViewTypeComponentState,
|
||||
'mocked-uuid',
|
||||
);
|
||||
@@ -82,10 +83,10 @@ const renderHooks = () => {
|
||||
openRecordInCommandMenu,
|
||||
viewableRecordId,
|
||||
viewableRecordNameSingular,
|
||||
currentObjectMetadataItemId,
|
||||
targetedRecordsRule,
|
||||
numberOfSelectedRecords,
|
||||
currentViewType,
|
||||
contextStoreCurrentObjectMetadataItemId,
|
||||
contextStoreTargetedRecordsRule,
|
||||
contextStoreNumberOfSelectedRecords,
|
||||
contextStoreCurrentViewType,
|
||||
getIcon,
|
||||
};
|
||||
},
|
||||
@@ -116,15 +117,17 @@ describe('useOpenRecordInCommandMenu', () => {
|
||||
|
||||
expect(result.current.viewableRecordId).toBe(recordId);
|
||||
expect(result.current.viewableRecordNameSingular).toBe(objectNameSingular);
|
||||
expect(result.current.currentObjectMetadataItemId).toBe(
|
||||
expect(result.current.contextStoreCurrentObjectMetadataItemId).toBe(
|
||||
personMockObjectMetadataItem.id,
|
||||
);
|
||||
expect(result.current.targetedRecordsRule).toEqual({
|
||||
expect(result.current.contextStoreTargetedRecordsRule).toEqual({
|
||||
mode: 'selection',
|
||||
selectedRecordIds: [recordId],
|
||||
});
|
||||
expect(result.current.numberOfSelectedRecords).toBe(1);
|
||||
expect(result.current.currentViewType).toBe(ContextStoreViewType.ShowPage);
|
||||
expect(result.current.contextStoreNumberOfSelectedRecords).toBe(1);
|
||||
expect(result.current.contextStoreCurrentViewType).toBe(
|
||||
ContextStoreViewType.ShowPage,
|
||||
);
|
||||
|
||||
const commandMenuNavigationMorphItemsByPage = jotaiStore.get(
|
||||
commandMenuNavigationMorphItemsByPageState.atom,
|
||||
|
||||
+28
-22
@@ -60,44 +60,44 @@ describe('useSetGlobalCommandMenuContext', () => {
|
||||
const { setGlobalCommandMenuContext } =
|
||||
useSetGlobalCommandMenuContext();
|
||||
|
||||
const targetedRecordsRule = useAtomComponentStateValue(
|
||||
const contextStoreTargetedRecordsRule = useAtomComponentStateValue(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
COMMAND_MENU_COMPONENT_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const numberOfSelectedRecords = useAtomComponentStateValue(
|
||||
const contextStoreNumberOfSelectedRecords = useAtomComponentStateValue(
|
||||
contextStoreNumberOfSelectedRecordsComponentState,
|
||||
COMMAND_MENU_COMPONENT_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const filters = useAtomComponentStateValue(
|
||||
const contextStoreFilters = useAtomComponentStateValue(
|
||||
contextStoreFiltersComponentState,
|
||||
COMMAND_MENU_COMPONENT_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const filterGroups = useAtomComponentStateValue(
|
||||
const contextStoreFilterGroups = useAtomComponentStateValue(
|
||||
contextStoreFilterGroupsComponentState,
|
||||
COMMAND_MENU_COMPONENT_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const anyFieldFilterValue = useAtomComponentStateValue(
|
||||
const contextStoreAnyFieldFilterValue = useAtomComponentStateValue(
|
||||
contextStoreAnyFieldFilterValueComponentState,
|
||||
COMMAND_MENU_COMPONENT_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const currentViewType = useAtomComponentStateValue(
|
||||
const contextStoreCurrentViewType = useAtomComponentStateValue(
|
||||
contextStoreCurrentViewTypeComponentState,
|
||||
COMMAND_MENU_COMPONENT_INSTANCE_ID,
|
||||
);
|
||||
|
||||
return {
|
||||
setGlobalCommandMenuContext,
|
||||
targetedRecordsRule,
|
||||
numberOfSelectedRecords,
|
||||
filters,
|
||||
filterGroups,
|
||||
currentViewType,
|
||||
anyFieldFilterValue,
|
||||
contextStoreTargetedRecordsRule,
|
||||
contextStoreNumberOfSelectedRecords,
|
||||
contextStoreFilters,
|
||||
contextStoreFilterGroups,
|
||||
contextStoreCurrentViewType,
|
||||
contextStoreAnyFieldFilterValue,
|
||||
};
|
||||
},
|
||||
{
|
||||
@@ -105,14 +105,16 @@ describe('useSetGlobalCommandMenuContext', () => {
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.current.targetedRecordsRule).toEqual({
|
||||
expect(result.current.contextStoreTargetedRecordsRule).toEqual({
|
||||
mode: 'selection',
|
||||
selectedRecordIds: [peopleMock[0].id, peopleMock[1].id],
|
||||
});
|
||||
expect(result.current.numberOfSelectedRecords).toBe(2);
|
||||
expect(result.current.filters).toEqual([]);
|
||||
expect(result.current.anyFieldFilterValue).toEqual('');
|
||||
expect(result.current.currentViewType).toBe(ContextStoreViewType.Table);
|
||||
expect(result.current.contextStoreNumberOfSelectedRecords).toBe(2);
|
||||
expect(result.current.contextStoreFilters).toEqual([]);
|
||||
expect(result.current.contextStoreAnyFieldFilterValue).toEqual('');
|
||||
expect(result.current.contextStoreCurrentViewType).toBe(
|
||||
ContextStoreViewType.Table,
|
||||
);
|
||||
const commandMenuPageInfo = jotaiStore.get(commandMenuPageInfoState.atom);
|
||||
expect(commandMenuPageInfo).toEqual({
|
||||
title: undefined,
|
||||
@@ -128,14 +130,16 @@ describe('useSetGlobalCommandMenuContext', () => {
|
||||
result.current.setGlobalCommandMenuContext();
|
||||
});
|
||||
|
||||
expect(result.current.targetedRecordsRule).toEqual({
|
||||
expect(result.current.contextStoreTargetedRecordsRule).toEqual({
|
||||
mode: 'selection',
|
||||
selectedRecordIds: [],
|
||||
});
|
||||
expect(result.current.numberOfSelectedRecords).toBe(0);
|
||||
expect(result.current.filters).toEqual([]);
|
||||
expect(result.current.anyFieldFilterValue).toEqual('');
|
||||
expect(result.current.currentViewType).toBe(ContextStoreViewType.Table);
|
||||
expect(result.current.contextStoreNumberOfSelectedRecords).toBe(0);
|
||||
expect(result.current.contextStoreFilters).toEqual([]);
|
||||
expect(result.current.contextStoreAnyFieldFilterValue).toEqual('');
|
||||
expect(result.current.contextStoreCurrentViewType).toBe(
|
||||
ContextStoreViewType.Table,
|
||||
);
|
||||
const commandMenuPageInfoAfter = jotaiStore.get(
|
||||
commandMenuPageInfoState.atom,
|
||||
);
|
||||
@@ -156,11 +160,13 @@ describe('useSetGlobalCommandMenuContext', () => {
|
||||
const { setGlobalCommandMenuContext } =
|
||||
useSetGlobalCommandMenuContext();
|
||||
|
||||
// eslint-disable-next-line twenty/matching-state-variable
|
||||
const previousTargetedRecordsRule = useAtomComponentStateValue(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
COMMAND_MENU_PREVIOUS_COMPONENT_INSTANCE_ID,
|
||||
);
|
||||
|
||||
// eslint-disable-next-line twenty/matching-state-variable
|
||||
const previousNumberOfSelectedRecords = useAtomComponentStateValue(
|
||||
contextStoreNumberOfSelectedRecordsComponentState,
|
||||
COMMAND_MENU_PREVIOUS_COMPONENT_INSTANCE_ID,
|
||||
|
||||
+24
-26
@@ -2,7 +2,6 @@ import { renderHook } from '@testing-library/react';
|
||||
|
||||
import { COMMAND_MENU_COMPONENT_INSTANCE_ID } from '@/command-menu/constants/CommandMenuComponentInstanceId';
|
||||
import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandMenu';
|
||||
import { viewableRecordIdComponentState } from '@/command-menu/pages/record-page/states/viewableRecordIdComponentState';
|
||||
import { viewableRecordNameSingularComponentState } from '@/command-menu/pages/record-page/states/viewableRecordNameSingularComponentState';
|
||||
import { commandMenuWorkflowIdComponentState } from '@/command-menu/pages/workflow/states/commandMenuWorkflowIdComponentState';
|
||||
import { commandMenuWorkflowVersionIdComponentState } from '@/command-menu/pages/workflow/states/commandMenuWorkflowVersionIdComponentState';
|
||||
@@ -65,35 +64,32 @@ const renderHooks = () => {
|
||||
openWorkflowViewStepInCommandMenu,
|
||||
} = useWorkflowCommandMenu();
|
||||
|
||||
const _viewableRecordId = useAtomComponentStateValue(
|
||||
viewableRecordIdComponentState,
|
||||
'mocked-uuid',
|
||||
);
|
||||
const viewableRecordNameSingular = useAtomComponentStateValue(
|
||||
viewableRecordNameSingularComponentState,
|
||||
'mocked-uuid',
|
||||
);
|
||||
const currentObjectMetadataItemId = useAtomComponentStateValue(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
'mocked-uuid',
|
||||
);
|
||||
const targetedRecordsRule = useAtomComponentStateValue(
|
||||
const contextStoreCurrentObjectMetadataItemId =
|
||||
useAtomComponentStateValue(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
'mocked-uuid',
|
||||
);
|
||||
const contextStoreTargetedRecordsRule = useAtomComponentStateValue(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
'mocked-uuid',
|
||||
);
|
||||
const numberOfSelectedRecords = useAtomComponentStateValue(
|
||||
const contextStoreNumberOfSelectedRecords = useAtomComponentStateValue(
|
||||
contextStoreNumberOfSelectedRecordsComponentState,
|
||||
'mocked-uuid',
|
||||
);
|
||||
const currentViewType = useAtomComponentStateValue(
|
||||
const contextStoreCurrentViewType = useAtomComponentStateValue(
|
||||
contextStoreCurrentViewTypeComponentState,
|
||||
'mocked-uuid',
|
||||
);
|
||||
const workflowId = useAtomComponentStateValue(
|
||||
const commandMenuWorkflowId = useAtomComponentStateValue(
|
||||
commandMenuWorkflowIdComponentState,
|
||||
'mocked-uuid',
|
||||
);
|
||||
const workflowVersionId = useAtomComponentStateValue(
|
||||
const commandMenuWorkflowVersionId = useAtomComponentStateValue(
|
||||
commandMenuWorkflowVersionIdComponentState,
|
||||
'mocked-uuid',
|
||||
);
|
||||
@@ -105,13 +101,13 @@ const renderHooks = () => {
|
||||
openWorkflowEditStepInCommandMenu,
|
||||
openWorkflowEditStepTypeInCommandMenu,
|
||||
openWorkflowViewStepInCommandMenu,
|
||||
workflowId,
|
||||
workflowVersionId,
|
||||
commandMenuWorkflowId,
|
||||
commandMenuWorkflowVersionId,
|
||||
viewableRecordNameSingular,
|
||||
currentObjectMetadataItemId,
|
||||
targetedRecordsRule,
|
||||
numberOfSelectedRecords,
|
||||
currentViewType,
|
||||
contextStoreCurrentObjectMetadataItemId,
|
||||
contextStoreTargetedRecordsRule,
|
||||
contextStoreNumberOfSelectedRecords,
|
||||
contextStoreCurrentViewType,
|
||||
getIcon,
|
||||
};
|
||||
},
|
||||
@@ -134,7 +130,7 @@ describe('useWorkflowCommandMenu', () => {
|
||||
result.current.openWorkflowTriggerTypeInCommandMenu('test-workflow-id');
|
||||
});
|
||||
|
||||
expect(result.current.workflowId).toBe('test-workflow-id');
|
||||
expect(result.current.commandMenuWorkflowId).toBe('test-workflow-id');
|
||||
|
||||
expect(mockNavigateCommandMenu).toHaveBeenCalledWith({
|
||||
page: CommandMenuPages.WorkflowTriggerSelectType,
|
||||
@@ -151,7 +147,7 @@ describe('useWorkflowCommandMenu', () => {
|
||||
result.current.openWorkflowCreateStepInCommandMenu('test-workflow-id');
|
||||
});
|
||||
|
||||
expect(result.current.workflowId).toBe('test-workflow-id');
|
||||
expect(result.current.commandMenuWorkflowId).toBe('test-workflow-id');
|
||||
|
||||
expect(mockNavigateCommandMenu).toHaveBeenCalledWith({
|
||||
page: CommandMenuPages.WorkflowStepCreate,
|
||||
@@ -168,7 +164,7 @@ describe('useWorkflowCommandMenu', () => {
|
||||
result.current.openWorkflowEditStepTypeInCommandMenu('test-workflow-id');
|
||||
});
|
||||
|
||||
expect(result.current.workflowId).toBe('test-workflow-id');
|
||||
expect(result.current.commandMenuWorkflowId).toBe('test-workflow-id');
|
||||
|
||||
expect(mockNavigateCommandMenu).toHaveBeenCalledWith({
|
||||
page: CommandMenuPages.WorkflowStepEditType,
|
||||
@@ -189,7 +185,7 @@ describe('useWorkflowCommandMenu', () => {
|
||||
);
|
||||
});
|
||||
|
||||
expect(result.current.workflowId).toBe('test-workflow-id');
|
||||
expect(result.current.commandMenuWorkflowId).toBe('test-workflow-id');
|
||||
|
||||
expect(mockNavigateCommandMenu).toHaveBeenCalledWith({
|
||||
page: CommandMenuPages.WorkflowStepEdit,
|
||||
@@ -211,8 +207,10 @@ describe('useWorkflowCommandMenu', () => {
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.workflowId).toBe('test-workflow-id');
|
||||
expect(result.current.workflowVersionId).toBe('test-workflow-version-id');
|
||||
expect(result.current.commandMenuWorkflowId).toBe('test-workflow-id');
|
||||
expect(result.current.commandMenuWorkflowVersionId).toBe(
|
||||
'test-workflow-version-id',
|
||||
);
|
||||
|
||||
expect(mockNavigateCommandMenu).toHaveBeenCalledWith({
|
||||
page: CommandMenuPages.WorkflowStepView,
|
||||
|
||||
@@ -38,7 +38,7 @@ export const useCommandMenuHotKeys = () => {
|
||||
|
||||
const isAiEnabled = useIsFeatureEnabled(FeatureFlagKey.IS_AI_ENABLED);
|
||||
|
||||
const contextStoreTargetedRecordsRuleComponent = useAtomComponentStateValue(
|
||||
const contextStoreTargetedRecordsRule = useAtomComponentStateValue(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
COMMAND_MENU_COMPONENT_INSTANCE_ID,
|
||||
);
|
||||
@@ -101,9 +101,8 @@ export const useCommandMenuHotKeys = () => {
|
||||
if (
|
||||
commandMenuPage === CommandMenuPages.Root &&
|
||||
!(
|
||||
contextStoreTargetedRecordsRuleComponent.mode === 'selection' &&
|
||||
contextStoreTargetedRecordsRuleComponent.selectedRecordIds.length ===
|
||||
0
|
||||
contextStoreTargetedRecordsRule.mode === 'selection' &&
|
||||
contextStoreTargetedRecordsRule.selectedRecordIds.length === 0
|
||||
)
|
||||
) {
|
||||
setGlobalCommandMenuContext();
|
||||
@@ -116,7 +115,7 @@ export const useCommandMenuHotKeys = () => {
|
||||
dependencies: [
|
||||
commandMenuPage,
|
||||
commandMenuSearch,
|
||||
contextStoreTargetedRecordsRuleComponent,
|
||||
contextStoreTargetedRecordsRule,
|
||||
goBackFromCommandMenu,
|
||||
setGlobalCommandMenuContext,
|
||||
],
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ const StyledContainer = styled.div`
|
||||
export const CommandMenuPageLayoutChartSettings = () => {
|
||||
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
|
||||
|
||||
const draftPageLayout = useAtomComponentStateValue(
|
||||
const pageLayoutDraft = useAtomComponentStateValue(
|
||||
pageLayoutDraftComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
@@ -28,7 +28,7 @@ export const CommandMenuPageLayoutChartSettings = () => {
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const widgetInEditMode = draftPageLayout.tabs
|
||||
const widgetInEditMode = pageLayoutDraft.tabs
|
||||
.flatMap((tab) => tab.widgets)
|
||||
.find((widget) => widget.id === pageLayoutEditingWidgetId);
|
||||
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
export const CommandMenuPageLayoutGraphFilter = () => {
|
||||
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
|
||||
|
||||
const draftPageLayout = useAtomComponentStateValue(
|
||||
const pageLayoutDraft = useAtomComponentStateValue(
|
||||
pageLayoutDraftComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
@@ -21,7 +21,7 @@ export const CommandMenuPageLayoutGraphFilter = () => {
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const widgetInEditMode = draftPageLayout.tabs
|
||||
const widgetInEditMode = pageLayoutDraft.tabs
|
||||
.flatMap((tab) => tab.widgets)
|
||||
.find((widget) => widget.id === pageLayoutEditingWidgetId);
|
||||
|
||||
|
||||
+12
-9
@@ -26,26 +26,29 @@ export const CommandMenuPageLayoutTabSettings = () => {
|
||||
const { closeCommandMenu } = useCommandMenu();
|
||||
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
|
||||
|
||||
const draft = useAtomComponentStateValue(
|
||||
const pageLayoutDraft = useAtomComponentStateValue(
|
||||
pageLayoutDraftComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const [openTabId, setOpenTabId] = useAtomComponentState(
|
||||
pageLayoutTabSettingsOpenTabIdComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
const [pageLayoutTabSettingsOpenTabId, setPageLayoutTabSettingsOpenTabId] =
|
||||
useAtomComponentState(
|
||||
pageLayoutTabSettingsOpenTabIdComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const { moveLeft, moveRight } = useMovePageLayoutTab(pageLayoutId);
|
||||
const { deleteTab } = useDeletePageLayoutTab(pageLayoutId);
|
||||
const { duplicateTab } = useDuplicatePageLayoutTab(pageLayoutId);
|
||||
|
||||
if (!isDefined(openTabId)) {
|
||||
if (!isDefined(pageLayoutTabSettingsOpenTabId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tabsSorted = sortTabsByPosition(draft.tabs);
|
||||
const currentIndex = tabsSorted.findIndex((t) => t.id === openTabId);
|
||||
const tabsSorted = sortTabsByPosition(pageLayoutDraft.tabs);
|
||||
const currentIndex = tabsSorted.findIndex(
|
||||
(t) => t.id === pageLayoutTabSettingsOpenTabId,
|
||||
);
|
||||
if (currentIndex < 0) return null;
|
||||
const tab = tabsSorted[currentIndex];
|
||||
const canMoveLeft = currentIndex > 0;
|
||||
@@ -54,7 +57,7 @@ export const CommandMenuPageLayoutTabSettings = () => {
|
||||
|
||||
const handleDelete = () => {
|
||||
deleteTab(tab.id);
|
||||
setOpenTabId(null);
|
||||
setPageLayoutTabSettingsOpenTabId(null);
|
||||
closeCommandMenu();
|
||||
};
|
||||
|
||||
|
||||
+2
-2
@@ -84,13 +84,13 @@ export const CommandMenuPageLayoutWidgetTypeSelect = () => {
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const draftPageLayout = useAtomComponentStateValue(
|
||||
const pageLayoutDraft = useAtomComponentStateValue(
|
||||
pageLayoutDraftComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const existingWidget = isDefined(pageLayoutEditingWidgetId)
|
||||
? draftPageLayout.tabs
|
||||
? pageLayoutDraft.tabs
|
||||
.flatMap((tab) => tab.widgets)
|
||||
.find((widget) => widget.id === pageLayoutEditingWidgetId)
|
||||
: undefined;
|
||||
|
||||
+5
-5
@@ -23,21 +23,21 @@ export const WidgetSettingsFooter = ({
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
const { duplicateWidget } = useDuplicatePageLayoutWidget(pageLayoutId);
|
||||
const { deletePageLayoutWidget } = useDeletePageLayoutWidget(pageLayoutId);
|
||||
const editingWidgetId = useAtomComponentStateValue(
|
||||
const pageLayoutEditingWidgetId = useAtomComponentStateValue(
|
||||
pageLayoutEditingWidgetIdComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const handleDuplicateWidget = () => {
|
||||
if (isDefined(editingWidgetId)) {
|
||||
duplicateWidget(editingWidgetId);
|
||||
if (isDefined(pageLayoutEditingWidgetId)) {
|
||||
duplicateWidget(pageLayoutEditingWidgetId);
|
||||
}
|
||||
closeDropdown(dropdownId);
|
||||
};
|
||||
|
||||
const handleDeleteWidget = () => {
|
||||
if (isDefined(editingWidgetId)) {
|
||||
deletePageLayoutWidget(editingWidgetId);
|
||||
if (isDefined(pageLayoutEditingWidgetId)) {
|
||||
deletePageLayoutWidget(pageLayoutEditingWidgetId);
|
||||
}
|
||||
closeDropdown(dropdownId);
|
||||
};
|
||||
|
||||
+7
-7
@@ -4,22 +4,22 @@ import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAto
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
|
||||
export const usePageLayoutIdFromContextStoreTargetedRecord = () => {
|
||||
const targetedRecordsRule = useAtomComponentStateValue(
|
||||
const contextStoreTargetedRecordsRule = useAtomComponentStateValue(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
if (
|
||||
!(
|
||||
targetedRecordsRule.mode === 'selection' &&
|
||||
targetedRecordsRule.selectedRecordIds.length === 1
|
||||
contextStoreTargetedRecordsRule.mode === 'selection' &&
|
||||
contextStoreTargetedRecordsRule.selectedRecordIds.length === 1
|
||||
)
|
||||
) {
|
||||
throw new Error('Only one record should be selected');
|
||||
throw new Error('Only one recordStore should be selected');
|
||||
}
|
||||
|
||||
const recordId: string = targetedRecordsRule.selectedRecordIds[0];
|
||||
const recordId: string = contextStoreTargetedRecordsRule.selectedRecordIds[0];
|
||||
|
||||
const record = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
|
||||
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
|
||||
|
||||
return { pageLayoutId: record?.pageLayoutId };
|
||||
return { pageLayoutId: recordStore?.pageLayoutId };
|
||||
};
|
||||
|
||||
+6
-6
@@ -7,26 +7,26 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord =
|
||||
() => {
|
||||
const targetedRecordsRule = useAtomComponentStateValue(
|
||||
const contextStoreTargetedRecordsRule = useAtomComponentStateValue(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
const objectMetadataId = useAtomComponentStateValue(
|
||||
const contextStoreCurrentObjectMetadataItemId = useAtomComponentStateValue(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
);
|
||||
|
||||
if (!isDefined(objectMetadataId)) {
|
||||
if (!isDefined(contextStoreCurrentObjectMetadataItemId)) {
|
||||
throw new Error('Object metadata ID is not defined');
|
||||
}
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItemById({
|
||||
objectId: objectMetadataId ?? undefined,
|
||||
objectId: contextStoreCurrentObjectMetadataItemId ?? undefined,
|
||||
});
|
||||
|
||||
if (
|
||||
!(
|
||||
targetedRecordsRule.mode === 'selection' &&
|
||||
targetedRecordsRule.selectedRecordIds.length === 1
|
||||
contextStoreTargetedRecordsRule.mode === 'selection' &&
|
||||
contextStoreTargetedRecordsRule.selectedRecordIds.length === 1
|
||||
)
|
||||
) {
|
||||
throw new Error('Only one record should be selected');
|
||||
|
||||
+3
-3
@@ -12,7 +12,7 @@ export const useUpdateCurrentWidgetConfig = (pageLayoutIdFromProps: string) => {
|
||||
pageLayoutIdFromProps,
|
||||
);
|
||||
|
||||
const currentlyEditingWidgetId = useAtomComponentStateValue(
|
||||
const pageLayoutEditingWidgetId = useAtomComponentStateValue(
|
||||
pageLayoutEditingWidgetIdComponentState,
|
||||
pageLayoutIdFromProps,
|
||||
);
|
||||
@@ -33,7 +33,7 @@ export const useUpdateCurrentWidgetConfig = (pageLayoutIdFromProps: string) => {
|
||||
tabs: prev.tabs.map((tab) => ({
|
||||
...tab,
|
||||
widgets: tab.widgets.map((widget) =>
|
||||
widget.id === currentlyEditingWidgetId
|
||||
widget.id === pageLayoutEditingWidgetId
|
||||
? {
|
||||
...widget,
|
||||
objectMetadataId: objectMetadataId ?? widget.objectMetadataId,
|
||||
@@ -47,7 +47,7 @@ export const useUpdateCurrentWidgetConfig = (pageLayoutIdFromProps: string) => {
|
||||
})),
|
||||
});
|
||||
},
|
||||
[pageLayoutDraft, currentlyEditingWidgetId, store],
|
||||
[pageLayoutDraft, pageLayoutEditingWidgetId, store],
|
||||
);
|
||||
|
||||
return { updateCurrentWidgetConfig };
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@ import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pa
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
|
||||
export const useWidgetInEditMode = (pageLayoutId: string) => {
|
||||
const draftPageLayout = useAtomComponentStateValue(
|
||||
const pageLayoutDraft = useAtomComponentStateValue(
|
||||
pageLayoutDraftComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
@@ -13,7 +13,7 @@ export const useWidgetInEditMode = (pageLayoutId: string) => {
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const widgetInEditMode = draftPageLayout.tabs
|
||||
const widgetInEditMode = pageLayoutDraft.tabs
|
||||
.flatMap((tab) => tab.widgets)
|
||||
.find((widget) => widget.id === pageLayoutEditingWidgetId);
|
||||
|
||||
|
||||
+3
-3
@@ -3,14 +3,14 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useCommandMenuWorkflowIdOrThrow = () => {
|
||||
const workflowId = useAtomComponentStateValue(
|
||||
const commandMenuWorkflowId = useAtomComponentStateValue(
|
||||
commandMenuWorkflowIdComponentState,
|
||||
);
|
||||
if (!isDefined(workflowId)) {
|
||||
if (!isDefined(commandMenuWorkflowId)) {
|
||||
throw new Error(
|
||||
'Expected commandMenuWorkflowIdComponentState to be defined',
|
||||
);
|
||||
}
|
||||
|
||||
return workflowId;
|
||||
return commandMenuWorkflowId;
|
||||
};
|
||||
|
||||
+3
-3
@@ -3,14 +3,14 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useCommandMenuWorkflowRunIdOrThrow = () => {
|
||||
const workflowRunId = useAtomComponentStateValue(
|
||||
const commandMenuWorkflowRunId = useAtomComponentStateValue(
|
||||
commandMenuWorkflowRunIdComponentState,
|
||||
);
|
||||
if (!isDefined(workflowRunId)) {
|
||||
if (!isDefined(commandMenuWorkflowRunId)) {
|
||||
throw new Error(
|
||||
'Expected the commandMenuWorkflowRunIdComponentState to be defined.',
|
||||
);
|
||||
}
|
||||
|
||||
return workflowRunId;
|
||||
return commandMenuWorkflowRunId;
|
||||
};
|
||||
|
||||
+3
-3
@@ -3,14 +3,14 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useCommandMenuWorkflowVersionIdOrThrow = () => {
|
||||
const workflowVersionId = useAtomComponentStateValue(
|
||||
const commandMenuWorkflowVersionId = useAtomComponentStateValue(
|
||||
commandMenuWorkflowVersionIdComponentState,
|
||||
);
|
||||
if (!isDefined(workflowVersionId)) {
|
||||
if (!isDefined(commandMenuWorkflowVersionId)) {
|
||||
throw new Error(
|
||||
'Expected commandMenuWorkflowVersionIdComponentState to be defined',
|
||||
);
|
||||
}
|
||||
|
||||
return workflowVersionId;
|
||||
return commandMenuWorkflowVersionId;
|
||||
};
|
||||
|
||||
+2
-2
@@ -49,7 +49,7 @@ export const MainContextStoreProvider = () => {
|
||||
const viewIdQueryParam = searchParams.get('viewId');
|
||||
|
||||
const objectMetadataItems = useAtomStateValue(objectMetadataItemsState);
|
||||
const viewsEntry = useAtomFamilyStateValue(metadataStoreState, 'views');
|
||||
const metadataStore = useAtomFamilyStateValue(metadataStoreState, 'views');
|
||||
const coreViews = useAtomStateValue(coreViewsState);
|
||||
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
@@ -76,7 +76,7 @@ export const MainContextStoreProvider = () => {
|
||||
const shouldComputeContextStore =
|
||||
(isRecordIndexPage || isRecordShowPage || isSettingsPage) &&
|
||||
!showAuthModal &&
|
||||
viewsEntry.status === 'up-to-date';
|
||||
metadataStore.status === 'up-to-date';
|
||||
|
||||
if (!shouldComputeContextStore) {
|
||||
return null;
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomState
|
||||
export const useContextStoreObjectMetadataItem = (
|
||||
contextStoreInstanceId?: string,
|
||||
) => {
|
||||
const objectMetadataItemId = useAtomComponentStateValue(
|
||||
const contextStoreCurrentObjectMetadataItemId = useAtomComponentStateValue(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
contextStoreInstanceId,
|
||||
);
|
||||
@@ -15,7 +15,7 @@ export const useContextStoreObjectMetadataItem = (
|
||||
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
(objectMetadataItemToFind) =>
|
||||
objectMetadataItemToFind.id === objectMetadataItemId,
|
||||
objectMetadataItemToFind.id === contextStoreCurrentObjectMetadataItemId,
|
||||
);
|
||||
|
||||
return { objectMetadataItem };
|
||||
|
||||
+2
-2
@@ -5,13 +5,13 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
|
||||
export const useContextStoreObjectMetadataItemOrThrow = (
|
||||
contextStoreInstanceId?: string,
|
||||
) => {
|
||||
const objectMetadataItemId = useAtomComponentStateValue(
|
||||
const contextStoreCurrentObjectMetadataItemId = useAtomComponentStateValue(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
contextStoreInstanceId,
|
||||
);
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItemById({
|
||||
objectId: objectMetadataItemId ?? '',
|
||||
objectId: contextStoreCurrentObjectMetadataItemId ?? '',
|
||||
});
|
||||
|
||||
if (!objectMetadataItem) {
|
||||
|
||||
+2
-2
@@ -25,7 +25,7 @@ export const useGetPublicWorkspaceDataByDomain = () => {
|
||||
);
|
||||
const workspacePublicData = useAtomStateValue(workspacePublicDataState);
|
||||
const { redirectToDefaultDomain } = useRedirectToDefaultDomain();
|
||||
const setWorkspacePublicDataState = useSetAtomState(workspacePublicDataState);
|
||||
const setWorkspacePublicData = useSetAtomState(workspacePublicDataState);
|
||||
const clientConfigApiStatus = useAtomStateValue(clientConfigApiStatusState);
|
||||
|
||||
const { loading, data, error } = useGetPublicWorkspaceDataByDomainQuery({
|
||||
@@ -43,7 +43,7 @@ export const useGetPublicWorkspaceDataByDomain = () => {
|
||||
setWorkspaceAuthBypassProviders(
|
||||
data.getPublicWorkspaceDataByDomain.authBypassProviders ?? null,
|
||||
);
|
||||
setWorkspacePublicDataState(data.getPublicWorkspaceDataByDomain);
|
||||
setWorkspacePublicData(data.getPublicWorkspaceDataByDomain);
|
||||
},
|
||||
onError: (error) => {
|
||||
// Only redirect to default domain if it's a workspace not found error
|
||||
|
||||
+6
-4
@@ -68,13 +68,15 @@ export const CurrentWorkspaceMemberFavorites = ({
|
||||
openFavoriteFolderIdsState,
|
||||
);
|
||||
|
||||
const setCurrentFolderId = useSetAtomState(currentFavoriteFolderIdState);
|
||||
const setCurrentFavoriteFolderId = useSetAtomState(
|
||||
currentFavoriteFolderIdState,
|
||||
);
|
||||
|
||||
const isOpen = openFavoriteFolderIds.includes(folder.folderId);
|
||||
|
||||
const handleToggle = () => {
|
||||
if (isMobile) {
|
||||
setCurrentFolderId((prev) =>
|
||||
setCurrentFavoriteFolderId((prev) =>
|
||||
prev === folder.folderId ? null : folder.folderId,
|
||||
);
|
||||
} else {
|
||||
@@ -93,7 +95,7 @@ export const CurrentWorkspaceMemberFavorites = ({
|
||||
|
||||
const dropdownId = `favorite-folder-edit-${folder.folderId}`;
|
||||
|
||||
const isDropdownOpenComponent = useAtomComponentStateValue(
|
||||
const isDropdownOpen = useAtomComponentStateValue(
|
||||
isDropdownOpenComponentState,
|
||||
dropdownId,
|
||||
);
|
||||
@@ -190,7 +192,7 @@ export const CurrentWorkspaceMemberFavorites = ({
|
||||
onClick={handleToggle}
|
||||
rightOptions={rightOptions}
|
||||
className="navigation-drawer-item"
|
||||
isRightOptionsDropdownOpen={isDropdownOpenComponent}
|
||||
isRightOptionsDropdownOpen={isDropdownOpen}
|
||||
triggerEvent="CLICK"
|
||||
preventCollapseOnMobile={isMobile}
|
||||
/>
|
||||
|
||||
@@ -35,12 +35,14 @@ export const FavoritesBackButton = ({
|
||||
folderName,
|
||||
}: FavoritesBackButtonProps) => {
|
||||
const theme = useTheme();
|
||||
const setCurrentFolderId = useSetAtomState(currentFavoriteFolderIdState);
|
||||
const setCurrentFavoriteFolderId = useSetAtomState(
|
||||
currentFavoriteFolderIdState,
|
||||
);
|
||||
|
||||
const handleClick = (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setCurrentFolderId(null);
|
||||
setCurrentFavoriteFolderId(null);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
+4
-4
@@ -43,19 +43,19 @@ export const FavoriteFolderPicker = ({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const [favoriteFoldersSearchFilter] = useAtomComponentState(
|
||||
const [favoriteFolderSearchFilter] = useAtomComponentState(
|
||||
favoriteFolderSearchFilterComponentState,
|
||||
);
|
||||
|
||||
const filteredFolders = favoriteFolders.filter((folder) =>
|
||||
folder.name
|
||||
.toLowerCase()
|
||||
.includes(favoriteFoldersSearchFilter.toLowerCase()),
|
||||
.includes(favoriteFolderSearchFilter.toLowerCase()),
|
||||
);
|
||||
|
||||
const showNoFolderOption =
|
||||
!favoriteFoldersSearchFilter ||
|
||||
'no folder'.includes(favoriteFoldersSearchFilter.toLowerCase());
|
||||
!favoriteFolderSearchFilter ||
|
||||
'no folder'.includes(favoriteFolderSearchFilter.toLowerCase());
|
||||
|
||||
useHotkeysOnFocusedElement({
|
||||
keys: [Key.Escape],
|
||||
|
||||
+3
-3
@@ -32,7 +32,7 @@ export const FavoriteFolderPickerEffect = ({
|
||||
const { favoriteFolders } = usePrefetchedFavoritesFoldersData();
|
||||
|
||||
const { sortedFavorites: favorites } = useFavorites();
|
||||
const setCheckedState = useSetAtomComponentState(
|
||||
const setFavoriteFolderPickerChecked = useSetAtomComponentState(
|
||||
favoriteFolderPickerCheckedComponentState,
|
||||
);
|
||||
|
||||
@@ -74,8 +74,8 @@ export const FavoriteFolderPickerEffect = ({
|
||||
favorite.recordId === targetId && favorite.forWorkspaceMemberId,
|
||||
)
|
||||
.map((favorite) => favorite.favoriteFolderId || 'no-folder');
|
||||
setCheckedState(checkedFolderIds);
|
||||
}, [favorites, setCheckedState, record?.id]);
|
||||
setFavoriteFolderPickerChecked(checkedFolderIds);
|
||||
}, [favorites, setFavoriteFolderPickerChecked, record?.id]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
+4
-4
@@ -28,7 +28,7 @@ export const FavoriteFolderPickerList = ({
|
||||
toggleFolderSelection,
|
||||
}: FavoriteFolderPickerListProps) => {
|
||||
const { t } = useLingui();
|
||||
const [favoriteFoldersSearchFilter] = useAtomComponentState(
|
||||
const [favoriteFolderSearchFilter] = useAtomComponentState(
|
||||
favoriteFolderSearchFilterComponentState,
|
||||
);
|
||||
|
||||
@@ -39,12 +39,12 @@ export const FavoriteFolderPickerList = ({
|
||||
const filteredFolders = folders.filter((folder) =>
|
||||
folder.name
|
||||
.toLowerCase()
|
||||
.includes(favoriteFoldersSearchFilter.toLowerCase()),
|
||||
.includes(favoriteFolderSearchFilter.toLowerCase()),
|
||||
);
|
||||
|
||||
const showNoFolderOption =
|
||||
!favoriteFoldersSearchFilter ||
|
||||
'no folder'.includes(favoriteFoldersSearchFilter.toLowerCase());
|
||||
!favoriteFolderSearchFilter ||
|
||||
'no folder'.includes(favoriteFolderSearchFilter.toLowerCase());
|
||||
|
||||
return (
|
||||
<StyledItemsContainer>
|
||||
|
||||
+3
-3
@@ -5,11 +5,11 @@ import { useCallback } from 'react';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
|
||||
export const FavoriteFolderPickerSearchInput = () => {
|
||||
const [favoriteFoldersSearchFilter, setFavoriteFoldersSearchFilter] =
|
||||
const [favoriteFolderSearchFilter, setFavoriteFolderSearchFilter] =
|
||||
useAtomComponentState(favoriteFolderSearchFilterComponentState);
|
||||
|
||||
const debouncedSetSearchFilter = useDebouncedCallback(
|
||||
setFavoriteFoldersSearchFilter,
|
||||
setFavoriteFolderSearchFilter,
|
||||
100,
|
||||
{ leading: true },
|
||||
);
|
||||
@@ -23,7 +23,7 @@ export const FavoriteFolderPickerSearchInput = () => {
|
||||
|
||||
return (
|
||||
<DropdownMenuSearchInput
|
||||
value={favoriteFoldersSearchFilter}
|
||||
value={favoriteFolderSearchFilter}
|
||||
onChange={handleFilterChange}
|
||||
autoFocus
|
||||
/>
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ export const FrontComponentRenderer = ({
|
||||
const theme = useTheme();
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
|
||||
const setApplicationTokenPair = useSetAtomComponentState(
|
||||
const setFrontComponentApplicationTokenPair = useSetAtomComponentState(
|
||||
frontComponentApplicationTokenPairComponentState,
|
||||
frontComponentId,
|
||||
);
|
||||
@@ -53,7 +53,7 @@ export const FrontComponentRenderer = ({
|
||||
const tokenPair = completedData.frontComponent?.applicationTokenPair;
|
||||
|
||||
if (isDefined(tokenPair)) {
|
||||
setApplicationTokenPair(tokenPair);
|
||||
setFrontComponentApplicationTokenPair(tokenPair);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
+2
-2
@@ -31,7 +31,7 @@ export const useFrontComponentExecutionContext = ({
|
||||
frontComponentId,
|
||||
});
|
||||
const { navigateCommandMenu } = useNavigateCommandMenu();
|
||||
const setCommandMenuSearchState = useSetAtomState(commandMenuSearchState);
|
||||
const setCommandMenuSearch = useSetAtomState(commandMenuSearchState);
|
||||
const { getIcon } = useIcons();
|
||||
const unmountHeadlessFrontComponent = useUnmountHeadlessFrontComponent();
|
||||
const {
|
||||
@@ -65,7 +65,7 @@ export const useFrontComponentExecutionContext = ({
|
||||
});
|
||||
|
||||
if (shouldResetSearchState === true) {
|
||||
setCommandMenuSearchState('');
|
||||
setCommandMenuSearch('');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+2
-2
@@ -51,7 +51,7 @@ export const InformationBanner = ({
|
||||
onClose?: () => void;
|
||||
componentInstanceId: string;
|
||||
}) => {
|
||||
const informationBannerIsOpenComponent = useAtomComponentStateValue(
|
||||
const informationBannerIsOpen = useAtomComponentStateValue(
|
||||
informationBannerIsOpenComponentState,
|
||||
componentInstanceId,
|
||||
);
|
||||
@@ -62,7 +62,7 @@ export const InformationBanner = ({
|
||||
instanceId: componentInstanceId,
|
||||
}}
|
||||
>
|
||||
{informationBannerIsOpenComponent && (
|
||||
{informationBannerIsOpen && (
|
||||
<Banner variant={variant}>
|
||||
<StyledContent hasCloseButton={!!onClose}>
|
||||
<StyledText>{message}</StyledText>
|
||||
|
||||
+2
-2
@@ -25,7 +25,7 @@ export const useDismissReconnectAccountBanner = (
|
||||
client: apolloCoreClient,
|
||||
});
|
||||
|
||||
const setInformationBannerIsOpenComponent = useSetAtomComponentState(
|
||||
const setInformationBannerIsOpen = useSetAtomComponentState(
|
||||
informationBannerIsOpenComponentState,
|
||||
componentInstanceId,
|
||||
);
|
||||
@@ -36,7 +36,7 @@ export const useDismissReconnectAccountBanner = (
|
||||
connectedAccountId,
|
||||
},
|
||||
});
|
||||
setInformationBannerIsOpenComponent(false);
|
||||
setInformationBannerIsOpen(false);
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
+10
-6
@@ -14,18 +14,22 @@ export const IsAppMetadataReadyEffect = () => {
|
||||
const isLoggedIn = useIsLogged();
|
||||
const currentUser = useAtomStateValue(currentUserState);
|
||||
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
|
||||
const objectMetadataItemsEntry = useAtomFamilyStateValue(
|
||||
const metadataStore = useAtomFamilyStateValue(
|
||||
metadataStoreState,
|
||||
'objectMetadataItems',
|
||||
);
|
||||
const viewsEntry = useAtomFamilyStateValue(metadataStoreState, 'views');
|
||||
// eslint-disable-next-line twenty/matching-state-variable
|
||||
const metadataStoreViews = useAtomFamilyStateValue(
|
||||
metadataStoreState,
|
||||
'views',
|
||||
);
|
||||
const setIsAppMetadataReady = useSetAtomState(isAppMetadataReadyState);
|
||||
|
||||
useEffect(() => {
|
||||
const hasActiveWorkspace = isWorkspaceActiveOrSuspended(currentWorkspace);
|
||||
|
||||
const areObjectsLoaded = objectMetadataItemsEntry.status === 'up-to-date';
|
||||
const areViewsLoaded = viewsEntry.status === 'up-to-date';
|
||||
const areObjectsLoaded = metadataStore.status === 'up-to-date';
|
||||
const areViewsLoaded = metadataStoreViews.status === 'up-to-date';
|
||||
|
||||
if (!areObjectsLoaded) {
|
||||
setIsAppMetadataReady(false);
|
||||
@@ -41,8 +45,8 @@ export const IsAppMetadataReadyEffect = () => {
|
||||
isLoggedIn,
|
||||
currentUser,
|
||||
currentWorkspace,
|
||||
objectMetadataItemsEntry.status,
|
||||
viewsEntry.status,
|
||||
metadataStore.status,
|
||||
metadataStoreViews.status,
|
||||
setIsAppMetadataReady,
|
||||
]);
|
||||
|
||||
|
||||
+3
-3
@@ -41,7 +41,7 @@ export const UserMetadataProviderInitialEffect = () => {
|
||||
const setCurrentWorkspaceMembers = useSetAtomState(
|
||||
currentWorkspaceMembersState,
|
||||
);
|
||||
const setCurrentWorkspaceMembersWithDeleted = useSetAtomState(
|
||||
const setCurrentWorkspaceDeletedMembers = useSetAtomState(
|
||||
currentWorkspaceDeletedMembersState,
|
||||
);
|
||||
const setIsCurrentUserLoaded = useSetAtomState(isCurrentUserLoadedState);
|
||||
@@ -151,7 +151,7 @@ export const UserMetadataProviderInitialEffect = () => {
|
||||
}
|
||||
|
||||
if (isDefined(deletedWorkspaceMembers)) {
|
||||
setCurrentWorkspaceMembersWithDeleted(deletedWorkspaceMembers);
|
||||
setCurrentWorkspaceDeletedMembers(deletedWorkspaceMembers);
|
||||
}
|
||||
|
||||
if (isDefined(availableWorkspaces)) {
|
||||
@@ -172,7 +172,7 @@ export const UserMetadataProviderInitialEffect = () => {
|
||||
setCurrentWorkspace,
|
||||
setCurrentWorkspaceMember,
|
||||
initializeFormatPreferences,
|
||||
setCurrentWorkspaceMembersWithDeleted,
|
||||
setCurrentWorkspaceDeletedMembers,
|
||||
updateLocaleCatalog,
|
||||
setIsCurrentUserLoaded,
|
||||
]);
|
||||
|
||||
+6
-4
@@ -85,7 +85,7 @@ export const CurrentWorkspaceMemberNavigationMenuItems = ({
|
||||
const [openNavigationMenuItemFolderIds, setOpenNavigationMenuItemFolderIds] =
|
||||
useAtomState(openNavigationMenuItemFolderIdsState);
|
||||
|
||||
const setCurrentFolderId = useSetAtomState(
|
||||
const setCurrentNavigationMenuItemFolderId = useSetAtomState(
|
||||
currentNavigationMenuItemFolderIdState,
|
||||
);
|
||||
|
||||
@@ -93,7 +93,9 @@ export const CurrentWorkspaceMemberNavigationMenuItems = ({
|
||||
|
||||
const handleToggle = () => {
|
||||
if (isMobile) {
|
||||
setCurrentFolderId((prev) => (prev === folder.id ? null : folder.id));
|
||||
setCurrentNavigationMenuItemFolderId((prev) =>
|
||||
prev === folder.id ? null : folder.id,
|
||||
);
|
||||
} else {
|
||||
setOpenNavigationMenuItemFolderIds((currentOpenFolders) => {
|
||||
if (isOpen) {
|
||||
@@ -123,7 +125,7 @@ export const CurrentWorkspaceMemberNavigationMenuItems = ({
|
||||
|
||||
const dropdownId = `navigation-menu-item-folder-edit-${folder.id}`;
|
||||
|
||||
const isDropdownOpenComponent = useAtomComponentStateValue(
|
||||
const isDropdownOpen = useAtomComponentStateValue(
|
||||
isDropdownOpenComponentState,
|
||||
dropdownId,
|
||||
);
|
||||
@@ -237,7 +239,7 @@ export const CurrentWorkspaceMemberNavigationMenuItems = ({
|
||||
onClick={handleToggle}
|
||||
rightOptions={rightOptions}
|
||||
className="navigation-drawer-item"
|
||||
isRightOptionsDropdownOpen={isDropdownOpenComponent}
|
||||
isRightOptionsDropdownOpen={isDropdownOpen}
|
||||
triggerEvent="CLICK"
|
||||
preventCollapseOnMobile={isMobile}
|
||||
/>
|
||||
|
||||
+2
-2
@@ -36,14 +36,14 @@ export const NavigationMenuItemBackButton = ({
|
||||
folderName,
|
||||
}: NavigationMenuItemBackButtonProps) => {
|
||||
const theme = useTheme();
|
||||
const setCurrentFolderId = useSetAtomState(
|
||||
const setCurrentNavigationMenuItemFolderId = useSetAtomState(
|
||||
currentNavigationMenuItemFolderIdState,
|
||||
);
|
||||
|
||||
const handleClick = (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setCurrentFolderId(null);
|
||||
setCurrentNavigationMenuItemFolderId(null);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
+4
-2
@@ -110,7 +110,7 @@ export const WorkspaceNavigationMenuItemsFolder = ({
|
||||
const [openNavigationMenuItemFolderIds, setOpenNavigationMenuItemFolderIds] =
|
||||
useAtomState(openNavigationMenuItemFolderIdsState);
|
||||
|
||||
const setCurrentFolderId = useSetAtomState(
|
||||
const setCurrentNavigationMenuItemFolderId = useSetAtomState(
|
||||
currentNavigationMenuItemFolderIdState,
|
||||
);
|
||||
|
||||
@@ -118,7 +118,9 @@ export const WorkspaceNavigationMenuItemsFolder = ({
|
||||
|
||||
const handleToggle = () => {
|
||||
if (isMobile) {
|
||||
setCurrentFolderId((prev) => (prev === folderId ? null : folderId));
|
||||
setCurrentNavigationMenuItemFolderId((prev) =>
|
||||
prev === folderId ? null : folderId,
|
||||
);
|
||||
} else {
|
||||
setOpenNavigationMenuItemFolderIds((current) =>
|
||||
isOpen
|
||||
|
||||
+3
-3
@@ -12,7 +12,7 @@ export const useRemoveNavigationMenuItemByTargetRecordId = () => {
|
||||
const apolloCoreClient = useApolloCoreClient();
|
||||
const cache = apolloCoreClient.cache;
|
||||
|
||||
const setNavigationMenuItemsState = useSetAtomState(
|
||||
const setPrefetchNavigationMenuItems = useSetAtomState(
|
||||
prefetchNavigationMenuItemsState,
|
||||
);
|
||||
|
||||
@@ -29,7 +29,7 @@ export const useRemoveNavigationMenuItemByTargetRecordId = () => {
|
||||
!targetRecordIdsSet.has(item.targetRecordId),
|
||||
);
|
||||
|
||||
setNavigationMenuItemsState(updatedNavigationMenuItems);
|
||||
setPrefetchNavigationMenuItems(updatedNavigationMenuItems);
|
||||
|
||||
cache.updateQuery({ query: FIND_MANY_NAVIGATION_MENU_ITEMS }, (data) => {
|
||||
if (!isDefined(data?.navigationMenuItems)) {
|
||||
@@ -42,7 +42,7 @@ export const useRemoveNavigationMenuItemByTargetRecordId = () => {
|
||||
};
|
||||
});
|
||||
},
|
||||
[cache, setNavigationMenuItemsState, store],
|
||||
[cache, setPrefetchNavigationMenuItems, store],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
+4
-4
@@ -94,7 +94,7 @@ export const useFetchMoreRecordsWithPagination = <
|
||||
queryIdentifier,
|
||||
);
|
||||
|
||||
const setIsFetchingMoreObjects = useSetAtomFamilyState(
|
||||
const setIsFetchingMoreRecords = useSetAtomFamilyState(
|
||||
isFetchingMoreRecordsFamilyState,
|
||||
queryIdentifier,
|
||||
);
|
||||
@@ -119,7 +119,7 @@ export const useFetchMoreRecordsWithPagination = <
|
||||
hasNextPageLocal ||
|
||||
(!isAggregationEnabled(objectMetadataItem) && !error)
|
||||
) {
|
||||
setIsFetchingMoreObjects(true);
|
||||
setIsFetchingMoreRecords(true);
|
||||
|
||||
try {
|
||||
const { data: fetchMoreDataResult } = await fetchMore({
|
||||
@@ -193,13 +193,13 @@ export const useFetchMoreRecordsWithPagination = <
|
||||
handleFindManyRecordsError(error as ApolloError);
|
||||
return { error: error as ApolloError };
|
||||
} finally {
|
||||
setIsFetchingMoreObjects(false);
|
||||
setIsFetchingMoreRecords(false);
|
||||
}
|
||||
}
|
||||
}, [
|
||||
objectMetadataItem,
|
||||
error,
|
||||
setIsFetchingMoreObjects,
|
||||
setIsFetchingMoreRecords,
|
||||
fetchMore,
|
||||
filter,
|
||||
orderBy,
|
||||
|
||||
+5
-4
@@ -6,20 +6,21 @@ import { useLingui } from '@lingui/react/macro';
|
||||
export const ObjectFilterDropdownAnyFieldSearchInput = () => {
|
||||
const { t } = useLingui();
|
||||
|
||||
const [anyFieldFilterSearchValue, setAnyFieldFilterSearchValue] =
|
||||
useAtomComponentState(anyFieldFilterValueComponentState);
|
||||
const [anyFieldFilterValue, setAnyFieldFilterValue] = useAtomComponentState(
|
||||
anyFieldFilterValueComponentState,
|
||||
);
|
||||
|
||||
const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const inputValue = event.target.value;
|
||||
|
||||
setAnyFieldFilterSearchValue(inputValue);
|
||||
setAnyFieldFilterValue(inputValue);
|
||||
};
|
||||
|
||||
return (
|
||||
<DropdownMenuSearchInput
|
||||
autoFocus
|
||||
type="text"
|
||||
value={anyFieldFilterSearchValue}
|
||||
value={anyFieldFilterValue}
|
||||
placeholder={t`Search any field`}
|
||||
onChange={handleSearchChange}
|
||||
/>
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
|
||||
}: ObjectFilterDropdownFilterSelectMenuItemProps) => {
|
||||
const { resetSelectedItem } = useSelectableList(FILTER_FIELD_LIST_ID);
|
||||
|
||||
const isSelectedItem = useAtomComponentFamilyStateValue(
|
||||
const isSelectedItemId = useAtomComponentFamilyStateValue(
|
||||
isSelectedItemIdComponentFamilyState,
|
||||
fieldMetadataItemToSelect.id,
|
||||
);
|
||||
@@ -39,7 +39,7 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
focused={isSelectedItem}
|
||||
focused={isSelectedItemId}
|
||||
onClick={handleClick}
|
||||
LeftIcon={Icon}
|
||||
text={fieldMetadataItemToSelect.label}
|
||||
|
||||
+3
-2
@@ -2,11 +2,12 @@ import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
|
||||
export const useObjectFilterDropdownFilterValue = () => {
|
||||
const currentRecordFilter = useAtomComponentStateValue(
|
||||
const objectFilterDropdownCurrentRecordFilter = useAtomComponentStateValue(
|
||||
objectFilterDropdownCurrentRecordFilterComponentState,
|
||||
);
|
||||
|
||||
const objectFilterDropdownFilterValue = currentRecordFilter?.value;
|
||||
const objectFilterDropdownFilterValue =
|
||||
objectFilterDropdownCurrentRecordFilter?.value;
|
||||
|
||||
return { objectFilterDropdownFilterValue };
|
||||
};
|
||||
|
||||
+4
-4
@@ -54,7 +54,7 @@ export const ObjectOptionsDropdownCustomView = ({
|
||||
}
|
||||
: null;
|
||||
|
||||
const recordGroupFieldMetadata = useAtomComponentStateValue(
|
||||
const recordIndexGroupFieldMetadataItem = useAtomComponentStateValue(
|
||||
recordIndexGroupFieldMetadataItemComponentState,
|
||||
);
|
||||
|
||||
@@ -224,7 +224,7 @@ export const ObjectOptionsDropdownCustomView = ({
|
||||
<SelectableListItem
|
||||
itemId="Group"
|
||||
onEnter={() =>
|
||||
isDefined(recordGroupFieldMetadata)
|
||||
isDefined(recordIndexGroupFieldMetadataItem)
|
||||
? onContentChange('recordGroups')
|
||||
: onContentChange('recordGroupFields')
|
||||
}
|
||||
@@ -232,7 +232,7 @@ export const ObjectOptionsDropdownCustomView = ({
|
||||
<MenuItem
|
||||
focused={selectedItemId === 'Group'}
|
||||
onClick={() =>
|
||||
isDefined(recordGroupFieldMetadata)
|
||||
isDefined(recordIndexGroupFieldMetadataItem)
|
||||
? onContentChange('recordGroups')
|
||||
: onContentChange('recordGroupFields')
|
||||
}
|
||||
@@ -241,7 +241,7 @@ export const ObjectOptionsDropdownCustomView = ({
|
||||
contextualText={
|
||||
isDefaultView
|
||||
? t`Not available on Default View`
|
||||
: recordGroupFieldMetadata?.label
|
||||
: recordIndexGroupFieldMetadataItem?.label
|
||||
}
|
||||
contextualTextPosition="right"
|
||||
hasSubMenu
|
||||
|
||||
+4
-4
@@ -36,7 +36,7 @@ export const ObjectOptionsDropdownHiddenRecordGroupsContent = () => {
|
||||
viewType,
|
||||
} = useObjectOptionsDropdown();
|
||||
|
||||
const recordGroupFieldMetadata = useAtomComponentStateValue(
|
||||
const recordIndexGroupFieldMetadataItem = useAtomComponentStateValue(
|
||||
recordIndexGroupFieldMetadataItemComponentState,
|
||||
);
|
||||
|
||||
@@ -61,7 +61,7 @@ export const ObjectOptionsDropdownHiddenRecordGroupsContent = () => {
|
||||
|
||||
const viewGroupSettingsUrl = getSettingsPath(SettingsPath.ObjectFieldEdit, {
|
||||
objectNamePlural,
|
||||
fieldName: recordGroupFieldMetadata?.name ?? '',
|
||||
fieldName: recordIndexGroupFieldMetadataItem?.name ?? '',
|
||||
});
|
||||
|
||||
const location = useLocation();
|
||||
@@ -88,10 +88,10 @@ export const ObjectOptionsDropdownHiddenRecordGroupsContent = () => {
|
||||
/>
|
||||
}
|
||||
>
|
||||
{t`Hidden`} {recordGroupFieldMetadata?.label}
|
||||
{t`Hidden`} {recordIndexGroupFieldMetadataItem?.label}
|
||||
</DropdownMenuHeader>
|
||||
<RecordGroupsVisibilityDropdownSection
|
||||
title={`${t`Hidden`} ${recordGroupFieldMetadata?.label}`}
|
||||
title={`${t`Hidden`} ${recordIndexGroupFieldMetadataItem?.label}`}
|
||||
recordGroupIds={hiddenRecordGroupIds}
|
||||
onVisibilityChange={handleRecordGroupVisibilityChange}
|
||||
isDraggable={false}
|
||||
|
||||
+4
-4
@@ -66,7 +66,7 @@ export const ObjectOptionsDropdownLayoutContent = () => {
|
||||
const recordIndexCalendarLayout = useAtomStateValue(
|
||||
recordIndexCalendarLayoutState,
|
||||
);
|
||||
const recordGroupFieldMetadata = useAtomComponentStateValue(
|
||||
const recordIndexGroupFieldMetadataItem = useAtomComponentStateValue(
|
||||
recordIndexGroupFieldMetadataItemComponentState,
|
||||
);
|
||||
|
||||
@@ -282,7 +282,7 @@ export const ObjectOptionsDropdownLayoutContent = () => {
|
||||
<SelectableListItem
|
||||
itemId="Group"
|
||||
onEnter={() => {
|
||||
isDefined(recordGroupFieldMetadata)
|
||||
isDefined(recordIndexGroupFieldMetadataItem)
|
||||
? onContentChange('recordGroups')
|
||||
: onContentChange('recordGroupFields');
|
||||
}}
|
||||
@@ -290,13 +290,13 @@ export const ObjectOptionsDropdownLayoutContent = () => {
|
||||
<MenuItem
|
||||
focused={selectedItemId === 'Group'}
|
||||
onClick={() =>
|
||||
isDefined(recordGroupFieldMetadata)
|
||||
isDefined(recordIndexGroupFieldMetadataItem)
|
||||
? onContentChange('recordGroups')
|
||||
: onContentChange('recordGroupFields')
|
||||
}
|
||||
LeftIcon={IconLayoutList}
|
||||
text={t`Group`}
|
||||
contextualText={recordGroupFieldMetadata?.label}
|
||||
contextualText={recordIndexGroupFieldMetadataItem?.label}
|
||||
contextualTextPosition="right"
|
||||
hasSubMenu
|
||||
/>
|
||||
|
||||
+6
-4
@@ -52,7 +52,7 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
hiddenRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
const recordGroupFieldMetadata = useAtomComponentStateValue(
|
||||
const recordIndexGroupFieldMetadataItem = useAtomComponentStateValue(
|
||||
recordIndexGroupFieldMetadataItemComponentState,
|
||||
);
|
||||
|
||||
@@ -109,7 +109,7 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
StartComponent={
|
||||
<DropdownMenuHeaderLeftComponent
|
||||
onClick={() =>
|
||||
isDefined(recordGroupFieldMetadata)
|
||||
isDefined(recordIndexGroupFieldMetadataItem)
|
||||
? onContentChange('recordGroups')
|
||||
: resetContent()
|
||||
}
|
||||
@@ -130,14 +130,16 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
{viewType === ViewType.Table && (
|
||||
<MenuItemSelect
|
||||
text={t`None`}
|
||||
selected={!isDefined(recordGroupFieldMetadata)}
|
||||
selected={!isDefined(recordIndexGroupFieldMetadataItem)}
|
||||
onClick={handleResetRecordGroupField}
|
||||
/>
|
||||
)}
|
||||
{filteredRecordGroupFieldMetadataItems.map((fieldMetadataItem) => (
|
||||
<MenuItemSelect
|
||||
key={fieldMetadataItem.id}
|
||||
selected={fieldMetadataItem.id === recordGroupFieldMetadata?.id}
|
||||
selected={
|
||||
fieldMetadataItem.id === recordIndexGroupFieldMetadataItem?.id
|
||||
}
|
||||
onClick={() => handleRecordGroupFieldChange(fieldMetadataItem)}
|
||||
LeftIcon={getIcon(fieldMetadataItem.icon)}
|
||||
text={fieldMetadataItem.label}
|
||||
|
||||
+11
-7
@@ -31,12 +31,11 @@ export const ObjectOptionsDropdownRecordGroupSortContent = () => {
|
||||
hiddenRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
const [recordGroupSort, setRecordGroupSort] = useAtomComponentState(
|
||||
recordIndexRecordGroupSortComponentState,
|
||||
);
|
||||
const [recordIndexRecordGroupSort, setRecordIndexRecordGroupSort] =
|
||||
useAtomComponentState(recordIndexRecordGroupSortComponentState);
|
||||
|
||||
const handleRecordGroupSortChange = (sort: RecordGroupSort) => {
|
||||
setRecordGroupSort(sort);
|
||||
setRecordIndexRecordGroupSort(sort);
|
||||
};
|
||||
|
||||
const selectedItemId = useAtomComponentStateValue(
|
||||
@@ -87,7 +86,7 @@ export const ObjectOptionsDropdownRecordGroupSortContent = () => {
|
||||
}
|
||||
LeftIcon={IconHandMove}
|
||||
text={RecordGroupSort.Manual}
|
||||
selected={recordGroupSort === RecordGroupSort.Manual}
|
||||
selected={recordIndexRecordGroupSort === RecordGroupSort.Manual}
|
||||
focused={selectedItemId === RecordGroupSort.Manual}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
@@ -103,7 +102,9 @@ export const ObjectOptionsDropdownRecordGroupSortContent = () => {
|
||||
}
|
||||
LeftIcon={IconSortAZ}
|
||||
text={RecordGroupSort.Alphabetical}
|
||||
selected={recordGroupSort === RecordGroupSort.Alphabetical}
|
||||
selected={
|
||||
recordIndexRecordGroupSort === RecordGroupSort.Alphabetical
|
||||
}
|
||||
focused={selectedItemId === RecordGroupSort.Alphabetical}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
@@ -119,7 +120,10 @@ export const ObjectOptionsDropdownRecordGroupSortContent = () => {
|
||||
}
|
||||
LeftIcon={IconSortZA}
|
||||
text={RecordGroupSort.ReverseAlphabetical}
|
||||
selected={recordGroupSort === RecordGroupSort.ReverseAlphabetical}
|
||||
selected={
|
||||
recordIndexRecordGroupSort ===
|
||||
RecordGroupSort.ReverseAlphabetical
|
||||
}
|
||||
focused={selectedItemId === RecordGroupSort.ReverseAlphabetical}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
|
||||
+9
-7
@@ -48,7 +48,7 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
|
||||
const { currentView } = useGetCurrentViewOnly();
|
||||
|
||||
const recordGroupFieldMetadata = useAtomComponentStateValue(
|
||||
const recordIndexGroupFieldMetadataItem = useAtomComponentStateValue(
|
||||
recordIndexGroupFieldMetadataItemComponentState,
|
||||
);
|
||||
|
||||
@@ -61,14 +61,16 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
hiddenRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
const hideEmptyRecordGroup = useAtomComponentStateValue(
|
||||
const recordIndexShouldHideEmptyRecordGroups = useAtomComponentStateValue(
|
||||
recordIndexShouldHideEmptyRecordGroupsComponentState,
|
||||
);
|
||||
|
||||
const shouldHideEmptyGroups =
|
||||
hideEmptyRecordGroup ?? currentView?.shouldHideEmptyGroups ?? false;
|
||||
recordIndexShouldHideEmptyRecordGroups ??
|
||||
currentView?.shouldHideEmptyGroups ??
|
||||
false;
|
||||
|
||||
const recordGroupSort = useAtomComponentStateValue(
|
||||
const recordIndexRecordGroupSort = useAtomComponentStateValue(
|
||||
recordIndexRecordGroupSortComponentState,
|
||||
);
|
||||
|
||||
@@ -136,7 +138,7 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
onClick={() => onContentChange('recordGroupFields')}
|
||||
LeftIcon={IconLayoutList}
|
||||
text={t`Group by`}
|
||||
contextualText={recordGroupFieldMetadata?.label}
|
||||
contextualText={recordIndexGroupFieldMetadataItem?.label}
|
||||
contextualTextPosition="right"
|
||||
hasSubMenu
|
||||
/>
|
||||
@@ -150,7 +152,7 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
onClick={() => onContentChange('recordGroupSort')}
|
||||
LeftIcon={IconSortDescending}
|
||||
text={t`Sort`}
|
||||
contextualText={recordGroupSort}
|
||||
contextualText={recordIndexRecordGroupSort}
|
||||
contextualTextPosition="right"
|
||||
hasSubMenu
|
||||
/>
|
||||
@@ -201,7 +203,7 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
<MenuItemNavigate
|
||||
onClick={() => onContentChange('hiddenRecordGroups')}
|
||||
LeftIcon={IconEyeOff}
|
||||
text={`${t`Hidden`} ${recordGroupFieldMetadata?.label ?? ''}`}
|
||||
text={`${t`Hidden`} ${recordIndexGroupFieldMetadataItem?.label ?? ''}`}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
</SelectableList>
|
||||
|
||||
+8
-6
@@ -7,12 +7,14 @@ import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
export const useSearchRecordGroupField = () => {
|
||||
const { objectMetadataItem } = useRecordIndexContextOrThrow();
|
||||
|
||||
const [recordGroupFieldSearchInput, setRecordGroupFieldSearchInput] =
|
||||
useAtomComponentState(objectOptionsDropdownSearchInputComponentState);
|
||||
const [
|
||||
objectOptionsDropdownSearchInput,
|
||||
setObjectOptionsDropdownSearchInput,
|
||||
] = useAtomComponentState(objectOptionsDropdownSearchInputComponentState);
|
||||
|
||||
const filteredRecordGroupFieldMetadataItems = useMemo(() => {
|
||||
const searchInputLowerCase =
|
||||
recordGroupFieldSearchInput.toLocaleLowerCase();
|
||||
objectOptionsDropdownSearchInput.toLocaleLowerCase();
|
||||
|
||||
return objectMetadataItem.readableFields.filter(
|
||||
(field) =>
|
||||
@@ -20,11 +22,11 @@ export const useSearchRecordGroupField = () => {
|
||||
field.isActive &&
|
||||
field.label.toLocaleLowerCase().includes(searchInputLowerCase),
|
||||
);
|
||||
}, [objectMetadataItem.readableFields, recordGroupFieldSearchInput]);
|
||||
}, [objectMetadataItem.readableFields, objectOptionsDropdownSearchInput]);
|
||||
|
||||
return {
|
||||
recordGroupFieldSearchInput,
|
||||
setRecordGroupFieldSearchInput,
|
||||
recordGroupFieldSearchInput: objectOptionsDropdownSearchInput,
|
||||
setRecordGroupFieldSearchInput: setObjectOptionsDropdownSearchInput,
|
||||
filteredRecordGroupFieldMetadataItems,
|
||||
};
|
||||
};
|
||||
|
||||
+6
-6
@@ -16,11 +16,11 @@ export const useUpdateObjectViewOptions = () => {
|
||||
recordIndexOpenRecordInState,
|
||||
);
|
||||
|
||||
const setRecordIndexViewName = useSetAtomComponentState(
|
||||
const setViewPickerInputName = useSetAtomComponentState(
|
||||
viewPickerInputNameComponentState,
|
||||
);
|
||||
|
||||
const setRecordIndexViewIcon = useSetAtomComponentState(
|
||||
const setViewPickerSelectedIcon = useSetAtomComponentState(
|
||||
viewPickerSelectedIconComponentState,
|
||||
);
|
||||
|
||||
@@ -41,23 +41,23 @@ export const useUpdateObjectViewOptions = () => {
|
||||
const setAndPersistViewName = useCallback(
|
||||
(viewName: string, view: GraphQLView | undefined) => {
|
||||
if (!view) return;
|
||||
setRecordIndexViewName(viewName);
|
||||
setViewPickerInputName(viewName);
|
||||
updateCurrentView({
|
||||
name: viewName,
|
||||
});
|
||||
},
|
||||
[setRecordIndexViewName, updateCurrentView],
|
||||
[setViewPickerInputName, updateCurrentView],
|
||||
);
|
||||
|
||||
const setAndPersistViewIcon = useCallback(
|
||||
(viewIcon: string, view: GraphQLView | undefined) => {
|
||||
if (!view) return;
|
||||
setRecordIndexViewIcon(viewIcon);
|
||||
setViewPickerSelectedIcon(viewIcon);
|
||||
updateCurrentView({
|
||||
icon: viewIcon,
|
||||
});
|
||||
},
|
||||
[setRecordIndexViewIcon, updateCurrentView],
|
||||
[setViewPickerSelectedIcon, updateCurrentView],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
+2
-2
@@ -131,13 +131,13 @@ export const ObjectSortDropdownButton = () => {
|
||||
const [selectedRecordSortDirection, setSelectedRecordSortDirection] =
|
||||
useAtomComponentState(selectedRecordSortDirectionComponentState);
|
||||
|
||||
const setIsRecordSortDirectionMenuUnfolded = useSetAtomComponentState(
|
||||
const setIsRecordSortDirectionDropdownMenuUnfolded = useSetAtomComponentState(
|
||||
isRecordSortDirectionDropdownMenuUnfoldedComponentState,
|
||||
);
|
||||
|
||||
const handleSortDirectionClick = (sortDirection: ViewSortDirection) => {
|
||||
setSelectedRecordSortDirection(sortDirection);
|
||||
setIsRecordSortDirectionMenuUnfolded(false);
|
||||
setIsRecordSortDirectionDropdownMenuUnfolded(false);
|
||||
};
|
||||
|
||||
const isDropdownOpen = useAtomComponentStateValue(
|
||||
|
||||
+2
-4
@@ -55,7 +55,7 @@ export const RecordBoardContainer = ({
|
||||
...args,
|
||||
});
|
||||
|
||||
const isRecordIndexRemoveSortingModalOpened = useAtomComponentStateValue(
|
||||
const isModalOpened = useAtomComponentStateValue(
|
||||
isModalOpenedComponentState,
|
||||
RECORD_INDEX_REMOVE_SORTING_MODAL_ID,
|
||||
);
|
||||
@@ -80,9 +80,7 @@ export const RecordBoardContainer = ({
|
||||
value={{ instanceId: recordBoardId }}
|
||||
>
|
||||
<RecordBoard />
|
||||
{isRecordIndexRemoveSortingModalOpened && (
|
||||
<RecordIndexRemoveSortingModal />
|
||||
)}
|
||||
{isModalOpened && <RecordIndexRemoveSortingModal />}
|
||||
<RecordBoardHotkeyEffect />
|
||||
<RecordBoardBodyEscapeHotkeyEffect />
|
||||
</RecordBoardComponentInstanceContext.Provider>
|
||||
|
||||
+14
-12
@@ -21,15 +21,14 @@ const StyledFetchMoreTriggerDiv = styled.div<{ width: number }>`
|
||||
`;
|
||||
|
||||
export const RecordBoardFetchMoreInViewTriggerComponent = () => {
|
||||
const [shouldFetchMore, setShouldFetchMore] = useAtomComponentState(
|
||||
recordBoardShouldFetchMoreComponentState,
|
||||
);
|
||||
const [recordBoardShouldFetchMore, setRecordBoardShouldFetchMore] =
|
||||
useAtomComponentState(recordBoardShouldFetchMoreComponentState);
|
||||
|
||||
const isInitialLoading = useAtomComponentStateValue(
|
||||
const recordIndexRecordGroupsAreInInitialLoading = useAtomComponentStateValue(
|
||||
recordIndexRecordGroupsAreInInitialLoadingComponentState,
|
||||
);
|
||||
|
||||
const isFetchingMore = useAtomComponentStateValue(
|
||||
const recordBoardIsFetchingMore = useAtomComponentStateValue(
|
||||
recordBoardIsFetchingMoreComponentState,
|
||||
);
|
||||
|
||||
@@ -52,19 +51,22 @@ export const RecordBoardFetchMoreInViewTriggerComponent = () => {
|
||||
1;
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInitialLoading && !isFetchingMore) {
|
||||
if (
|
||||
!recordIndexRecordGroupsAreInInitialLoading &&
|
||||
!recordBoardIsFetchingMore
|
||||
) {
|
||||
const newShouldFetchMore = inView;
|
||||
|
||||
if (shouldFetchMore !== newShouldFetchMore) {
|
||||
setShouldFetchMore(newShouldFetchMore);
|
||||
if (recordBoardShouldFetchMore !== newShouldFetchMore) {
|
||||
setRecordBoardShouldFetchMore(newShouldFetchMore);
|
||||
}
|
||||
}
|
||||
}, [
|
||||
shouldFetchMore,
|
||||
setShouldFetchMore,
|
||||
recordBoardShouldFetchMore,
|
||||
setRecordBoardShouldFetchMore,
|
||||
inView,
|
||||
isInitialLoading,
|
||||
isFetchingMore,
|
||||
recordIndexRecordGroupsAreInInitialLoading,
|
||||
recordBoardIsFetchingMore,
|
||||
]);
|
||||
|
||||
return (
|
||||
|
||||
+7
-7
@@ -51,7 +51,7 @@ export const RecordBoardQueryEffect = () => {
|
||||
|
||||
const { scrollWrapperHTMLElement } = useScrollWrapperHTMLElement();
|
||||
|
||||
const [shouldFetchMore] = useAtomComponentState(
|
||||
const [recordBoardShouldFetchMore] = useAtomComponentState(
|
||||
recordBoardShouldFetchMoreComponentState,
|
||||
);
|
||||
|
||||
@@ -64,11 +64,11 @@ export const RecordBoardQueryEffect = () => {
|
||||
const { triggerRecordBoardInitialQuery } =
|
||||
useTriggerRecordBoardInitialQuery();
|
||||
|
||||
const recordGroupdIds = useAtomComponentStateValue(
|
||||
const recordGroupIds = useAtomComponentStateValue(
|
||||
recordGroupIdsComponentState,
|
||||
);
|
||||
const recordGroupIdsHaveChanged = !isDeeplyEqual(
|
||||
[...recordGroupdIds].sort(),
|
||||
[...recordGroupIds].sort(),
|
||||
[...lastRecordGroupIds].sort(),
|
||||
);
|
||||
|
||||
@@ -78,10 +78,10 @@ export const RecordBoardQueryEffect = () => {
|
||||
(queryIdentifierHasChanged || recordGroupIdsHaveChanged)
|
||||
) {
|
||||
triggerRecordBoardInitialQuery();
|
||||
setLastRecordGroupIds(recordGroupdIds);
|
||||
setLastRecordGroupIds(recordGroupIds);
|
||||
} else if (
|
||||
!recordIndexRecordGroupsAreInInitialLoading &&
|
||||
shouldFetchMore &&
|
||||
recordBoardShouldFetchMore &&
|
||||
!queryIdentifierHasChanged &&
|
||||
!recordBoardIsFetchingMore
|
||||
) {
|
||||
@@ -95,11 +95,11 @@ export const RecordBoardQueryEffect = () => {
|
||||
setRecordBoardCurrentGroupByQueryOffset,
|
||||
scrollWrapperHTMLElement,
|
||||
recordIndexRecordGroupsAreInInitialLoading,
|
||||
shouldFetchMore,
|
||||
recordBoardShouldFetchMore,
|
||||
recordBoardIsFetchingMore,
|
||||
triggerRecordBoardFetchMore,
|
||||
setLastRecordGroupIds,
|
||||
recordGroupdIds,
|
||||
recordGroupIds,
|
||||
recordGroupIdsHaveChanged,
|
||||
]);
|
||||
|
||||
|
||||
+5
-5
@@ -8,22 +8,22 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
|
||||
export const RecordBoardScrollToFocusedCardEffect = () => {
|
||||
const { recordBoardId } = useContext(RecordBoardContext);
|
||||
|
||||
const focusedCardIndexes = useAtomComponentStateValue(
|
||||
const focusedRecordBoardCardIndexes = useAtomComponentStateValue(
|
||||
focusedRecordBoardCardIndexesComponentState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const isFocusActive = useAtomComponentStateValue(
|
||||
const isRecordBoardCardFocusActive = useAtomComponentStateValue(
|
||||
isRecordBoardCardFocusActiveComponentState,
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isFocusActive || !focusedCardIndexes) {
|
||||
if (!isRecordBoardCardFocusActive || !focusedRecordBoardCardIndexes) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { rowIndex, columnIndex } = focusedCardIndexes;
|
||||
const { rowIndex, columnIndex } = focusedRecordBoardCardIndexes;
|
||||
|
||||
const focusElement = document.getElementById(
|
||||
`record-board-card-${columnIndex}-${rowIndex}`,
|
||||
@@ -36,7 +36,7 @@ export const RecordBoardScrollToFocusedCardEffect = () => {
|
||||
if (focusElement instanceof HTMLElement) {
|
||||
focusElement.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||
}
|
||||
}, [focusedCardIndexes, isFocusActive]);
|
||||
}, [focusedRecordBoardCardIndexes, isRecordBoardCardFocusActive]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
+4
-4
@@ -10,23 +10,23 @@ export const RecordBoardSelectRecordsEffect = () => {
|
||||
recordBoardSelectedRecordIdsComponentSelector,
|
||||
);
|
||||
|
||||
const setContextStoreTargetedRecords = useSetAtomComponentState(
|
||||
const setContextStoreTargetedRecordsRule = useSetAtomComponentState(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setContextStoreTargetedRecords({
|
||||
setContextStoreTargetedRecordsRule({
|
||||
mode: 'selection',
|
||||
selectedRecordIds: selectedRecordIds,
|
||||
});
|
||||
|
||||
return () => {
|
||||
setContextStoreTargetedRecords({
|
||||
setContextStoreTargetedRecordsRule({
|
||||
mode: 'selection',
|
||||
selectedRecordIds: [],
|
||||
});
|
||||
};
|
||||
}, [selectedRecordIds, setContextStoreTargetedRecords]);
|
||||
}, [selectedRecordIds, setContextStoreTargetedRecordsRule]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
+3
-3
@@ -3,13 +3,13 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export const RecordBoardStickyHeaderEffect = () => {
|
||||
const scrollTop = useAtomComponentStateValue(
|
||||
const scrollWrapperScrollTop = useAtomComponentStateValue(
|
||||
scrollWrapperScrollTopComponentState,
|
||||
);
|
||||
|
||||
// TODO: move this outside because it might cause way too many re-renders for other hooks
|
||||
useEffect(() => {
|
||||
if (scrollTop > 0) {
|
||||
if (scrollWrapperScrollTop > 0) {
|
||||
document
|
||||
.getElementById('record-board-header')
|
||||
?.classList.add('header-sticky');
|
||||
@@ -18,7 +18,7 @@ export const RecordBoardStickyHeaderEffect = () => {
|
||||
.getElementById('record-board-header')
|
||||
?.classList.remove('header-sticky');
|
||||
}
|
||||
}, [scrollTop]);
|
||||
}, [scrollWrapperScrollTop]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
+3
-3
@@ -21,7 +21,7 @@ export const useRemoveSelectedRecordsFromRecordBoard = (
|
||||
recordBoardIndexId,
|
||||
);
|
||||
|
||||
const groupByFieldMetadataItem = useAtomComponentStateValue(
|
||||
const recordIndexGroupFieldMetadataItem = useAtomComponentStateValue(
|
||||
recordIndexGroupFieldMetadataItemComponentState,
|
||||
recordBoardIndexId,
|
||||
);
|
||||
@@ -46,7 +46,7 @@ export const useRemoveSelectedRecordsFromRecordBoard = (
|
||||
) as string[];
|
||||
|
||||
if (
|
||||
!isDefined(groupByFieldMetadataItem) ||
|
||||
!isDefined(recordIndexGroupFieldMetadataItem) ||
|
||||
!isNonEmptyArray(recordGroupDefinitions) ||
|
||||
!isNonEmptyArray(deletedRecordIds)
|
||||
) {
|
||||
@@ -86,7 +86,7 @@ export const useRemoveSelectedRecordsFromRecordBoard = (
|
||||
resetRecordBoardSelection();
|
||||
}, [
|
||||
store,
|
||||
groupByFieldMetadataItem,
|
||||
recordIndexGroupFieldMetadataItem,
|
||||
recordIndexRecordIdsByGroupCallbackState,
|
||||
recordGroupDefinitions,
|
||||
recordBoardSelectedRecordIds,
|
||||
|
||||
+5
-2
@@ -16,13 +16,16 @@ export const RecordBoardCardCellEditModePortal = () => {
|
||||
const { objectMetadataItem } = useContext(RecordBoardContext);
|
||||
const { recordId } = useContext(RecordBoardCardContext);
|
||||
|
||||
const editModePosition = useAtomComponentStateValue(
|
||||
const recordBoardCardEditModePosition = useAtomComponentStateValue(
|
||||
recordBoardCardEditModePositionComponentState,
|
||||
);
|
||||
|
||||
const { editedFieldMetadataItem } = useRecordBoardCardMetadataFromPosition();
|
||||
|
||||
if (!isDefined(editModePosition) || !isDefined(editedFieldMetadataItem)) {
|
||||
if (
|
||||
!isDefined(recordBoardCardEditModePosition) ||
|
||||
!isDefined(editedFieldMetadataItem)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+17
-16
@@ -73,18 +73,19 @@ export const RecordBoardCard = () => {
|
||||
|
||||
const isCompactModeActive = currentView?.isCompact ?? false;
|
||||
|
||||
const [isCardExpanded, setIsCardExpanded] = useAtomComponentState(
|
||||
recordBoardCardIsExpandedComponentState,
|
||||
`record-board-card-${recordId}`,
|
||||
);
|
||||
const [recordBoardCardIsExpanded, setRecordBoardCardIsExpanded] =
|
||||
useAtomComponentState(
|
||||
recordBoardCardIsExpandedComponentState,
|
||||
`record-board-card-${recordId}`,
|
||||
);
|
||||
|
||||
const [isCurrentCardSelected, setIsCurrentCardSelected] =
|
||||
const [isRecordBoardCardSelected, setIsRecordBoardCardSelected] =
|
||||
useAtomComponentFamilyState(
|
||||
isRecordBoardCardSelectedComponentFamilyState,
|
||||
recordId,
|
||||
);
|
||||
|
||||
const isCurrentCardFocused = useAtomComponentFamilyStateValue(
|
||||
const isRecordBoardCardFocused = useAtomComponentFamilyStateValue(
|
||||
isRecordBoardCardFocusedComponentFamilyState,
|
||||
{
|
||||
rowIndex,
|
||||
@@ -92,7 +93,7 @@ export const RecordBoardCard = () => {
|
||||
},
|
||||
);
|
||||
|
||||
const isCurrentCardActive = useAtomComponentFamilyStateValue(
|
||||
const isRecordBoardCardActive = useAtomComponentFamilyStateValue(
|
||||
isRecordBoardCardActiveComponentFamilyState,
|
||||
{
|
||||
rowIndex,
|
||||
@@ -105,7 +106,7 @@ export const RecordBoardCard = () => {
|
||||
const actionMenuDropdownId =
|
||||
getActionMenuDropdownIdFromActionMenuId(actionMenuId);
|
||||
|
||||
const setActionMenuDropdownPosition = useSetAtomComponentState(
|
||||
const setRecordIndexActionMenuDropdownPosition = useSetAtomComponentState(
|
||||
recordIndexActionMenuDropdownPositionComponentState,
|
||||
actionMenuDropdownId,
|
||||
);
|
||||
@@ -118,8 +119,8 @@ export const RecordBoardCard = () => {
|
||||
|
||||
const handleContextMenuOpen = (event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
setIsCurrentCardSelected(true);
|
||||
setActionMenuDropdownPosition({
|
||||
setIsRecordBoardCardSelected(true);
|
||||
setRecordIndexActionMenuDropdownPosition({
|
||||
x: event.clientX,
|
||||
y: event.clientY,
|
||||
});
|
||||
@@ -139,8 +140,8 @@ export const RecordBoardCard = () => {
|
||||
};
|
||||
|
||||
const onMouseLeaveBoard = useDebouncedCallback(() => {
|
||||
if (isCompactModeActive && isCardExpanded) {
|
||||
setIsCardExpanded(false);
|
||||
if (isCompactModeActive && recordBoardCardIsExpanded) {
|
||||
setRecordBoardCardIsExpanded(false);
|
||||
}
|
||||
}, 800);
|
||||
|
||||
@@ -165,9 +166,9 @@ export const RecordBoardCard = () => {
|
||||
>
|
||||
{isRecordIdPrimaryDragMultiple && <RecordBoardCardMultiDragStack />}
|
||||
<RecordCard
|
||||
data-selected={isCurrentCardSelected}
|
||||
data-focused={isCurrentCardFocused}
|
||||
data-active={isCurrentCardActive}
|
||||
data-selected={isRecordBoardCardSelected}
|
||||
data-focused={isRecordBoardCardFocused}
|
||||
data-active={isRecordBoardCardActive}
|
||||
onMouseLeave={onMouseLeaveBoard}
|
||||
onClick={handleCardClick}
|
||||
isPrimaryMultiDrag={isRecordIdPrimaryDragMultiple}
|
||||
@@ -176,7 +177,7 @@ export const RecordBoardCard = () => {
|
||||
>
|
||||
<RecordBoardCardHeader />
|
||||
<AnimatedEaseInOut
|
||||
isOpen={isCardExpanded || !isCompactModeActive}
|
||||
isOpen={recordBoardCardIsExpanded || !isCompactModeActive}
|
||||
initial={false}
|
||||
>
|
||||
<RecordBoardCardBody />
|
||||
|
||||
+2
-2
@@ -36,7 +36,7 @@ export const RecordBoardCardDraggableContainer = ({
|
||||
|
||||
const { columnIndex } = useContext(RecordBoardColumnContext);
|
||||
|
||||
const isRecordBoardCardFocusActive = useAtomComponentFamilyStateValue(
|
||||
const isRecordBoardCardFocused = useAtomComponentFamilyStateValue(
|
||||
isRecordBoardCardFocusedComponentFamilyState,
|
||||
{
|
||||
rowIndex,
|
||||
@@ -61,7 +61,7 @@ export const RecordBoardCardDraggableContainer = ({
|
||||
data-select-disable
|
||||
>
|
||||
<DragAndDropLibraryLegacyReRenderBreaker memoizationId={recordId}>
|
||||
{isRecordBoardCardFocusActive && <RecordBoardCardHotkeysEffect />}
|
||||
{isRecordBoardCardFocused && <RecordBoardCardHotkeysEffect />}
|
||||
<RecordBoardCard />
|
||||
<RecordBoardCardMultiDragPreview />
|
||||
</DragAndDropLibraryLegacyReRenderBreaker>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user