Feat/show page metadata (#2234)
* Fix view fetch bug * Finished types * Removed console.log * Fixed todo * Working Object Show Page * Minor fixes * Fix custom object requests pending (#2240) * Fix custom object requests pending * fix typo * Fix various bugs * Typo * Fix * Fix * Fix --------- Co-authored-by: Weiko <corentin@twenty.com>
This commit is contained in:
@ -4,6 +4,7 @@ module.exports = {
|
||||
project: 'tsconfig.json',
|
||||
tsconfigRootDir: __dirname,
|
||||
sourceType: 'module',
|
||||
ecmaVersion: "2023"
|
||||
},
|
||||
plugins: [
|
||||
'@typescript-eslint/eslint-plugin',
|
||||
|
||||
@ -22,6 +22,20 @@ module.exports = {
|
||||
'@': path.resolve(__dirname, 'src/modules'),
|
||||
'@testing': path.resolve(__dirname, 'src/testing'),
|
||||
},
|
||||
mode: 'extends',
|
||||
// TODO: remove this workaround by resolving source map errors with @sniptt/guards
|
||||
configure: {
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
enforce: "pre",
|
||||
use: ["source-map-loader"],
|
||||
},
|
||||
],
|
||||
},
|
||||
ignoreWarnings: [/Failed to parse source map/],
|
||||
},
|
||||
},
|
||||
jest: {
|
||||
configure: {
|
||||
|
||||
@ -180,7 +180,7 @@
|
||||
"storybook-addon-cookie": "^3.0.1",
|
||||
"storybook-addon-pseudo-states": "^2.1.0",
|
||||
"ts-jest": "^29.1.0",
|
||||
"typescript": "^4.9.3",
|
||||
"typescript": "^5.2.2",
|
||||
"webpack": "^5.75.0"
|
||||
},
|
||||
"msw": {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Navigate, Route, Routes, useLocation } from 'react-router-dom';
|
||||
|
||||
import { ObjectShowPage } from '@/metadata/components/ObjectShowPage';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { DefaultLayout } from '@/ui/layout/page/DefaultLayout';
|
||||
@ -63,6 +64,7 @@ export const App = () => {
|
||||
|
||||
<Route path={AppPath.OpportunitiesPage} element={<Opportunities />} />
|
||||
<Route path={AppPath.ObjectTablePage} element={<ObjectTablePage />} />
|
||||
<Route path={AppPath.ObjectShowPage} element={<ObjectShowPage />} />
|
||||
|
||||
<Route
|
||||
path={AppPath.SettingsCatchAll}
|
||||
|
||||
@ -10,7 +10,10 @@ import { useFindManyObjects } from '../hooks/useFindManyObjects';
|
||||
import { useSetObjectDataTableData } from '../hooks/useSetDataTableData';
|
||||
import { MetadataObjectIdentifier } from '../types/MetadataObjectIdentifier';
|
||||
|
||||
export type ObjectDataTableEffectProps = MetadataObjectIdentifier;
|
||||
export type ObjectDataTableEffectProps = Pick<
|
||||
MetadataObjectIdentifier,
|
||||
'objectNamePlural'
|
||||
>;
|
||||
|
||||
export const ObjectDataTableEffect = ({
|
||||
objectNamePlural,
|
||||
@ -33,10 +36,11 @@ export const ObjectDataTableEffect = ({
|
||||
const tableRecoilScopeId = useRecoilScopeId(TableRecoilScopeContext);
|
||||
const handleViewSelect = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
async (viewId: string) => {
|
||||
const currentView = await snapshot.getPromise(
|
||||
(viewId: string) => {
|
||||
const currentView = snapshot.getLoadable(
|
||||
currentViewIdScopedState({ scopeId: tableRecoilScopeId }),
|
||||
);
|
||||
).getValue()
|
||||
|
||||
if (currentView === viewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
159
front/src/modules/metadata/components/ObjectShowPage.tsx
Normal file
159
front/src/modules/metadata/components/ObjectShowPage.tsx
Normal file
@ -0,0 +1,159 @@
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { DateTime } from 'luxon';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { ActivityTargetableEntityType } from '@/activities/types/ActivityTargetableEntity';
|
||||
import { FieldContext } from '@/ui/data/field/contexts/FieldContext';
|
||||
import { entityFieldsFamilyState } from '@/ui/data/field/states/entityFieldsFamilyState';
|
||||
import { InlineCell } from '@/ui/data/inline-cell/components/InlineCell';
|
||||
import { PropertyBox } from '@/ui/data/inline-cell/property-box/components/PropertyBox';
|
||||
import { InlineCellHotkeyScope } from '@/ui/data/inline-cell/types/InlineCellHotkeyScope';
|
||||
import { IconBuildingSkyscraper } from '@/ui/display/icon';
|
||||
import { PageBody } from '@/ui/layout/page/PageBody';
|
||||
import { PageContainer } from '@/ui/layout/page/PageContainer';
|
||||
import { PageFavoriteButton } from '@/ui/layout/page/PageFavoriteButton';
|
||||
import { PageHeader } from '@/ui/layout/page/PageHeader';
|
||||
import { ShowPageContainer } from '@/ui/layout/page/ShowPageContainer';
|
||||
import { ShowPageAddButton } from '@/ui/layout/show-page/components/ShowPageAddButton';
|
||||
import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer';
|
||||
import { ShowPageRightContainer } from '@/ui/layout/show-page/components/ShowPageRightContainer';
|
||||
import { ShowPageSummaryCard } from '@/ui/layout/show-page/components/ShowPageSummaryCard';
|
||||
import { ShowPageRecoilScopeContext } from '@/ui/layout/states/ShowPageRecoilScopeContext';
|
||||
import { PageTitle } from '@/ui/utilities/page-title/PageTitle';
|
||||
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
|
||||
|
||||
import { useFindOneMetadataObject } from '../hooks/useFindOneMetadataObject';
|
||||
import { useFindOneObject } from '../hooks/useFindOneObject';
|
||||
import { useUpdateOneObject } from '../hooks/useUpdateOneObject';
|
||||
import { formatMetadataFieldAsColumnDefinition } from '../utils/formatMetadataFieldAsColumnDefinition';
|
||||
|
||||
export const ObjectShowPage = () => {
|
||||
const { objectNameSingular, objectId } = useParams<{
|
||||
objectNameSingular: string;
|
||||
objectId: string;
|
||||
}>();
|
||||
|
||||
const { foundMetadataObject } = useFindOneMetadataObject({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const [, setEntityFields] = useRecoilState(
|
||||
entityFieldsFamilyState(objectId ?? ''),
|
||||
);
|
||||
|
||||
const { object } = useFindOneObject({
|
||||
objectId: objectId,
|
||||
objectNameSingular,
|
||||
onCompleted: (data) => {
|
||||
setEntityFields(data);
|
||||
},
|
||||
});
|
||||
|
||||
const useUpdateOneObjectMutation: () => [(params: any) => any, any] = () => {
|
||||
const { updateOneObject } = useUpdateOneObject({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const updateEntity = ({
|
||||
variables,
|
||||
}: {
|
||||
variables: {
|
||||
where: { id: string };
|
||||
data: {
|
||||
[fieldName: string]: any;
|
||||
};
|
||||
};
|
||||
}) => {
|
||||
updateOneObject?.({
|
||||
idToUpdate: variables.where.id,
|
||||
input: variables.data,
|
||||
});
|
||||
};
|
||||
|
||||
return [updateEntity, { loading: false }];
|
||||
};
|
||||
|
||||
const handleFavoriteButtonClick = async () => {
|
||||
//
|
||||
};
|
||||
|
||||
if (!object) return <></>;
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<PageTitle title={object.name || 'No Name'} />
|
||||
<PageHeader
|
||||
title={object.name ?? ''}
|
||||
hasBackButton
|
||||
Icon={IconBuildingSkyscraper}
|
||||
>
|
||||
<PageFavoriteButton
|
||||
isFavorite={false}
|
||||
onClick={handleFavoriteButtonClick}
|
||||
/>
|
||||
<ShowPageAddButton
|
||||
key="add"
|
||||
entity={{
|
||||
id: object.id,
|
||||
type: ActivityTargetableEntityType.Company,
|
||||
}}
|
||||
/>
|
||||
</PageHeader>
|
||||
<PageBody>
|
||||
<RecoilScope CustomRecoilScopeContext={ShowPageRecoilScopeContext}>
|
||||
<ShowPageContainer>
|
||||
<ShowPageLeftContainer>
|
||||
<ShowPageSummaryCard
|
||||
id={object.id}
|
||||
logoOrAvatar={''}
|
||||
title={object.name ?? 'No name'}
|
||||
date={object.createdAt ?? ''}
|
||||
renderTitleEditComponent={() => <></>}
|
||||
avatarType="squared"
|
||||
/>
|
||||
<PropertyBox extraPadding={true}>
|
||||
{foundMetadataObject?.fields
|
||||
.toSorted((a, b) =>
|
||||
DateTime.fromISO(a.createdAt)
|
||||
.diff(DateTime.fromISO(b.createdAt))
|
||||
.toMillis(),
|
||||
)
|
||||
.map((metadataField, index) => {
|
||||
return (
|
||||
<FieldContext.Provider
|
||||
key={object.id + metadataField.id}
|
||||
value={{
|
||||
entityId: object.id,
|
||||
recoilScopeId: object.id + metadataField.id,
|
||||
fieldDefinition:
|
||||
formatMetadataFieldAsColumnDefinition({
|
||||
field: metadataField,
|
||||
index: index,
|
||||
metadataObject: foundMetadataObject,
|
||||
}),
|
||||
useUpdateEntityMutation: useUpdateOneObjectMutation,
|
||||
hotkeyScope: InlineCellHotkeyScope.InlineCell,
|
||||
}}
|
||||
>
|
||||
<InlineCell />
|
||||
</FieldContext.Provider>
|
||||
);
|
||||
})}
|
||||
</PropertyBox>
|
||||
</ShowPageLeftContainer>
|
||||
<ShowPageRightContainer
|
||||
entity={{
|
||||
id: object.id,
|
||||
type: ActivityTargetableEntityType.Company,
|
||||
}}
|
||||
timeline
|
||||
tasks
|
||||
notes
|
||||
emails
|
||||
/>
|
||||
</ShowPageContainer>
|
||||
</RecoilScope>
|
||||
</PageBody>
|
||||
</PageContainer>
|
||||
);
|
||||
};
|
||||
@ -6,7 +6,10 @@ import { MetadataObjectIdentifier } from '../types/MetadataObjectIdentifier';
|
||||
|
||||
import { ObjectDataTableEffect } from './ObjectDataTableEffect';
|
||||
|
||||
export type ObjectTableProps = MetadataObjectIdentifier;
|
||||
export type ObjectTableProps = Pick<
|
||||
MetadataObjectIdentifier,
|
||||
'objectNamePlural'
|
||||
>;
|
||||
|
||||
export const ObjectTable = ({ objectNamePlural }: ObjectTableProps) => {
|
||||
const { updateOneObject } = useUpdateOneObject({
|
||||
|
||||
@ -24,7 +24,10 @@ const StyledTableContainer = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export type ObjectTablePageProps = MetadataObjectIdentifier;
|
||||
export type ObjectTablePageProps = Pick<
|
||||
MetadataObjectIdentifier,
|
||||
'objectNamePlural'
|
||||
>;
|
||||
|
||||
export const ObjectTablePage = () => {
|
||||
const objectNamePlural = useParams().objectNamePlural ?? '';
|
||||
|
||||
@ -2,7 +2,7 @@ import { gql } from '@apollo/client';
|
||||
|
||||
export const FIND_MANY_METADATA_OBJECTS = gql`
|
||||
query MetadataObjects {
|
||||
objects {
|
||||
objects(paging: { first: 100 }) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
@ -17,7 +17,7 @@ export const FIND_MANY_METADATA_OBJECTS = gql`
|
||||
isActive
|
||||
createdAt
|
||||
updatedAt
|
||||
fields {
|
||||
fields(paging: { first: 100 }) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
|
||||
@ -169,8 +169,8 @@ export const useCreateNewTempsCustomObject = () => {
|
||||
});
|
||||
|
||||
const createdFields = [
|
||||
emailFieldData,
|
||||
nameFieldData,
|
||||
emailFieldData,
|
||||
cityFieldData,
|
||||
phoneFieldData,
|
||||
twitterFieldData,
|
||||
|
||||
@ -7,7 +7,7 @@ import { useFindOneMetadataObject } from './useFindOneMetadataObject';
|
||||
|
||||
export const useCreateOneObject = ({
|
||||
objectNamePlural,
|
||||
}: MetadataObjectIdentifier) => {
|
||||
}: Pick<MetadataObjectIdentifier, 'objectNamePlural'>) => {
|
||||
const {
|
||||
foundMetadataObject,
|
||||
objectNotFoundInMetadata,
|
||||
|
||||
@ -7,7 +7,7 @@ import { useFindOneMetadataObject } from './useFindOneMetadataObject';
|
||||
|
||||
export const useDeleteOneObject = ({
|
||||
objectNamePlural,
|
||||
}: MetadataObjectIdentifier) => {
|
||||
}: Pick<MetadataObjectIdentifier, 'objectNamePlural'>) => {
|
||||
const {
|
||||
foundMetadataObject,
|
||||
objectNotFoundInMetadata,
|
||||
|
||||
@ -13,7 +13,7 @@ export const useFindManyObjects = <
|
||||
ObjectType extends { id: string } & Record<string, any>,
|
||||
>({
|
||||
objectNamePlural,
|
||||
}: MetadataObjectIdentifier) => {
|
||||
}: Pick<MetadataObjectIdentifier, 'objectNamePlural'>) => {
|
||||
const { foundMetadataObject, objectNotFoundInMetadata, findManyQuery } =
|
||||
useFindOneMetadataObject({
|
||||
objectNamePlural,
|
||||
@ -28,10 +28,12 @@ export const useFindManyObjects = <
|
||||
|
||||
const objects = useMemo(
|
||||
() =>
|
||||
formatPagedObjectsToObjects({
|
||||
pagedObjects: data,
|
||||
objectNamePlural,
|
||||
}),
|
||||
objectNamePlural
|
||||
? formatPagedObjectsToObjects({
|
||||
pagedObjects: data,
|
||||
objectNamePlural,
|
||||
})
|
||||
: [],
|
||||
[data, objectNamePlural],
|
||||
);
|
||||
|
||||
|
||||
@ -7,16 +7,20 @@ import { MetadataObjectIdentifier } from '../types/MetadataObjectIdentifier';
|
||||
import { formatMetadataFieldAsColumnDefinition } from '../utils/formatMetadataFieldAsColumnDefinition';
|
||||
import { generateCreateOneObjectMutation } from '../utils/generateCreateOneObjectMutation';
|
||||
import { generateFindManyCustomObjectsQuery } from '../utils/generateFindManyCustomObjectsQuery';
|
||||
import { generateFindOneCustomObjectQuery } from '../utils/generateFindOneCustomObjectQuery';
|
||||
|
||||
import { useFindManyMetadataObjects } from './useFindManyMetadataObjects';
|
||||
|
||||
export const useFindOneMetadataObject = ({
|
||||
objectNamePlural,
|
||||
objectNameSingular,
|
||||
}: MetadataObjectIdentifier) => {
|
||||
const { metadataObjects, loading } = useFindManyMetadataObjects();
|
||||
|
||||
const foundMetadataObject = metadataObjects.find(
|
||||
(object) => object.namePlural === objectNamePlural,
|
||||
(object) =>
|
||||
object.namePlural === objectNamePlural ||
|
||||
object.nameSingular === objectNameSingular,
|
||||
);
|
||||
|
||||
const objectNotFoundInMetadata =
|
||||
@ -28,6 +32,7 @@ export const useFindOneMetadataObject = ({
|
||||
formatMetadataFieldAsColumnDefinition({
|
||||
index,
|
||||
field,
|
||||
metadataObject: foundMetadataObject,
|
||||
}),
|
||||
) ?? [];
|
||||
|
||||
@ -41,6 +46,16 @@ export const useFindOneMetadataObject = ({
|
||||
}
|
||||
`;
|
||||
|
||||
const findOneQuery = foundMetadataObject
|
||||
? generateFindOneCustomObjectQuery({
|
||||
metadataObject: foundMetadataObject,
|
||||
})
|
||||
: gql`
|
||||
query EmptyQuery {
|
||||
empty
|
||||
}
|
||||
`;
|
||||
|
||||
const createOneMutation = foundMetadataObject
|
||||
? generateCreateOneObjectMutation({
|
||||
metadataObject: foundMetadataObject,
|
||||
@ -67,6 +82,7 @@ export const useFindOneMetadataObject = ({
|
||||
objectNotFoundInMetadata,
|
||||
columnDefinitions,
|
||||
findManyQuery,
|
||||
findOneQuery,
|
||||
createOneMutation,
|
||||
deleteOneMutation,
|
||||
loading,
|
||||
|
||||
46
front/src/modules/metadata/hooks/useFindOneObject.ts
Normal file
46
front/src/modules/metadata/hooks/useFindOneObject.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { useQuery } from '@apollo/client';
|
||||
|
||||
import { MetadataObjectIdentifier } from '../types/MetadataObjectIdentifier';
|
||||
|
||||
import { useFindOneMetadataObject } from './useFindOneMetadataObject';
|
||||
|
||||
export const useFindOneObject = <
|
||||
ObjectType extends { id: string } & Record<string, any>,
|
||||
>({
|
||||
objectNameSingular,
|
||||
objectId,
|
||||
onCompleted,
|
||||
}: Pick<MetadataObjectIdentifier, 'objectNameSingular'> & {
|
||||
objectId: string | undefined;
|
||||
onCompleted?: (data: ObjectType) => void;
|
||||
}) => {
|
||||
const { foundMetadataObject, objectNotFoundInMetadata, findOneQuery } =
|
||||
useFindOneMetadataObject({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const { data, loading, error } = useQuery<
|
||||
{ [nameSingular: string]: ObjectType },
|
||||
{ objectId: string }
|
||||
>(findOneQuery, {
|
||||
skip: !foundMetadataObject || !objectId,
|
||||
variables: {
|
||||
objectId: objectId ?? '',
|
||||
},
|
||||
onCompleted: (data) => {
|
||||
if (onCompleted && objectNameSingular) {
|
||||
onCompleted(data[objectNameSingular]);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const object =
|
||||
objectNameSingular && data ? data[objectNameSingular] : undefined;
|
||||
|
||||
return {
|
||||
object,
|
||||
loading,
|
||||
error,
|
||||
objectNotFoundInMetadata,
|
||||
};
|
||||
};
|
||||
@ -1,4 +1,5 @@
|
||||
import { gql, useMutation } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
|
||||
import { MetadataObjectIdentifier } from '../types/MetadataObjectIdentifier';
|
||||
import { generateUpdateOneObjectMutation } from '../utils/generateUpdateOneObjectMutation';
|
||||
@ -7,10 +8,12 @@ import { useFindOneMetadataObject } from './useFindOneMetadataObject';
|
||||
|
||||
export const useUpdateOneObject = ({
|
||||
objectNamePlural,
|
||||
objectNameSingular,
|
||||
}: MetadataObjectIdentifier) => {
|
||||
const { foundMetadataObject, objectNotFoundInMetadata } =
|
||||
const { foundMetadataObject, objectNotFoundInMetadata, findManyQuery } =
|
||||
useFindOneMetadataObject({
|
||||
objectNamePlural,
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const generatedMutation = foundMetadataObject
|
||||
@ -24,7 +27,9 @@ export const useUpdateOneObject = ({
|
||||
`;
|
||||
|
||||
// TODO: type this with a minimal type at least with Record<string, any>
|
||||
const [mutate] = useMutation(generatedMutation);
|
||||
const [mutate] = useMutation(generatedMutation, {
|
||||
refetchQueries: [getOperationName(findManyQuery) ?? ''],
|
||||
});
|
||||
|
||||
const updateOneObject = foundMetadataObject
|
||||
? ({
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
export type MetadataObjectIdentifier = {
|
||||
objectNamePlural: string;
|
||||
objectNamePlural?: string;
|
||||
objectNameSingular?: string;
|
||||
};
|
||||
|
||||
@ -20,9 +20,11 @@ const parseFieldType = (fieldType: string): FieldType => {
|
||||
export const formatMetadataFieldAsColumnDefinition = ({
|
||||
index,
|
||||
field,
|
||||
metadataObject,
|
||||
}: {
|
||||
index: number;
|
||||
field: MetadataObject['fields'][0];
|
||||
metadataObject: Omit<MetadataObject, 'fields'>;
|
||||
}): ColumnDefinition<FieldMetadata> => ({
|
||||
index,
|
||||
key: field.name,
|
||||
@ -35,4 +37,5 @@ export const formatMetadataFieldAsColumnDefinition = ({
|
||||
},
|
||||
Icon: IconBrandLinkedin,
|
||||
isVisible: true,
|
||||
basePathToShowPage: `/object/${metadataObject.nameSingular}/`,
|
||||
});
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
import { MetadataObject } from '../types/MetadataObject';
|
||||
|
||||
import { mapFieldMetadataToGraphQLQuery } from './mapFieldMetadataToGraphQLQuery';
|
||||
|
||||
export const generateFindOneCustomObjectQuery = ({
|
||||
metadataObject,
|
||||
}: {
|
||||
metadataObject: MetadataObject;
|
||||
}) => {
|
||||
return gql`
|
||||
query FindOne${metadataObject.nameSingular}($objectId: UUID!) {
|
||||
${metadataObject.nameSingular}(filter: {
|
||||
id: {
|
||||
eq: $objectId
|
||||
}
|
||||
}){
|
||||
id
|
||||
${metadataObject.fields.map(mapFieldMetadataToGraphQLQuery).join('\n')}
|
||||
}
|
||||
}
|
||||
`;
|
||||
};
|
||||
@ -31,7 +31,8 @@ export const SettingsObjectFieldDataType = ({
|
||||
value,
|
||||
}: SettingsObjectFieldDataTypeProps) => {
|
||||
const theme = useTheme();
|
||||
const { label, Icon } = dataTypes[value];
|
||||
|
||||
const { label, Icon } = dataTypes?.[value];
|
||||
|
||||
return (
|
||||
<StyledDataType value={value}>
|
||||
|
||||
@ -37,6 +37,18 @@ export const SettingsObjectFieldItemTableRow = ({
|
||||
const theme = useTheme();
|
||||
const { Icon } = useLazyLoadIcon(fieldItem.icon ?? '');
|
||||
|
||||
// TODO: parse with zod and merge types with FieldType (create a subset of FieldType for example)
|
||||
const fieldDataTypeIsSupported = [
|
||||
'text',
|
||||
'number',
|
||||
'boolean',
|
||||
'url',
|
||||
].includes(fieldItem.type);
|
||||
|
||||
if (!fieldDataTypeIsSupported) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledObjectFieldTableRow>
|
||||
<StyledNameTableCell>
|
||||
|
||||
@ -19,6 +19,8 @@ export enum AppPath {
|
||||
OpportunitiesPage = '/opportunities',
|
||||
ObjectTablePage = '/objects/:objectNamePlural',
|
||||
|
||||
ObjectShowPage = '/object/:objectNameSingular/:objectId',
|
||||
|
||||
SettingsCatchAll = `/settings/*`,
|
||||
DevelopersCatchAll = `/developers/*`,
|
||||
|
||||
|
||||
@ -6,9 +6,9 @@ import { isTableCellInEditModeFamilyState } from '../states/isTableCellInEditMod
|
||||
export const useCloseCurrentTableCellInEditMode = () =>
|
||||
useRecoilCallback(({ set, snapshot }) => {
|
||||
return async () => {
|
||||
const currentTableCellInEditModePosition = await snapshot.getPromise(
|
||||
currentTableCellInEditModePositionState,
|
||||
);
|
||||
const currentTableCellInEditModePosition = snapshot
|
||||
.getLoadable(currentTableCellInEditModePositionState)
|
||||
.valueOrThrow();
|
||||
|
||||
set(
|
||||
isTableCellInEditModeFamilyState(currentTableCellInEditModePosition),
|
||||
|
||||
@ -110,6 +110,7 @@ export const BoardOptionsDropdownContent = ({
|
||||
const viewEditMode = snapshot
|
||||
.getLoadable(viewEditModeScopedState({ scopeId: boardRecoilScopeId }))
|
||||
.getValue();
|
||||
|
||||
if (!viewEditMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -23,9 +23,10 @@ export const useSetHotkeyScope = () =>
|
||||
useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (hotkeyScopeToSet: string, customScopes?: CustomHotkeyScopes) => {
|
||||
const currentHotkeyScope = await snapshot.getPromise(
|
||||
currentHotkeyScopeState,
|
||||
);
|
||||
const currentHotkeyScope = snapshot
|
||||
.getLoadable(currentHotkeyScopeState)
|
||||
.valueOrThrow();
|
||||
|
||||
if (currentHotkeyScope.scope === hotkeyScopeToSet) {
|
||||
if (!isDefined(customScopes)) {
|
||||
if (
|
||||
|
||||
@ -13,6 +13,7 @@ import {
|
||||
} from '~/generated/graphql';
|
||||
|
||||
import { GET_VIEW_FIELDS } from '../../graphql/queries/getViewFields';
|
||||
import { GET_VIEWS } from '@/views/graphql/queries/getViews';
|
||||
|
||||
export const toViewFieldInput = (
|
||||
objectId: string,
|
||||
@ -92,6 +93,7 @@ export const useViewFields = (viewScopeId: string) => {
|
||||
viewId_key: { key: viewField.key, viewId: currentViewId },
|
||||
},
|
||||
},
|
||||
refetchQueries: [getOperationName(GET_VIEWS) ?? ''],
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"lib": ["dom", "dom.iterable", "esnext", "ES2023", "ES2023.Array"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
|
||||
@ -18729,10 +18729,10 @@ typedarray@^0.0.6:
|
||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
|
||||
|
||||
typescript@^4.9.3:
|
||||
version "4.9.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
|
||||
integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
|
||||
typescript@^5.2.2:
|
||||
version "5.2.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78"
|
||||
integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==
|
||||
|
||||
ua-parser-js@^1.0.35:
|
||||
version "1.0.35"
|
||||
|
||||
Reference in New Issue
Block a user