Fix Activities and Tasks modules (#2561)
* Fix activities * Fix Timeline * Refactor useCreateOne and useUpdateOne records * Fix seeds
This commit is contained in:
@ -63,7 +63,7 @@ export const ActivityComments = ({
|
|||||||
}: ActivityCommentsProps) => {
|
}: ActivityCommentsProps) => {
|
||||||
const currentUser = useRecoilValue(currentUserState);
|
const currentUser = useRecoilValue(currentUserState);
|
||||||
const { createOneObject } = useCreateOneObjectRecord({
|
const { createOneObject } = useCreateOneObjectRecord({
|
||||||
objectNamePlural: 'commentsV2',
|
objectNameSingular: 'commentV2',
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!currentUser) {
|
if (!currentUser) {
|
||||||
|
|||||||
@ -86,8 +86,8 @@ export const ActivityEditor = ({
|
|||||||
activity.completedAt ?? '',
|
activity.completedAt ?? '',
|
||||||
);
|
);
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const { updateOneObject } = useUpdateOneObjectRecord({
|
const { updateOneObject } = useUpdateOneObjectRecord<Activity>({
|
||||||
objectNamePlural: 'activitiesV2',
|
objectNameSingular: 'activityV2',
|
||||||
});
|
});
|
||||||
|
|
||||||
const updateTitle = useCallback(
|
const updateTitle = useCallback(
|
||||||
|
|||||||
@ -16,8 +16,8 @@ export const useHandleCheckableActivityTargetChange = ({
|
|||||||
> | null;
|
> | null;
|
||||||
};
|
};
|
||||||
}) => {
|
}) => {
|
||||||
const { createOneObject } = useCreateOneObjectRecord({
|
const { createOneObject } = useCreateOneObjectRecord<ActivityTarget>({
|
||||||
objectNamePlural: 'activityTargetV2',
|
objectNameSingular: 'activityTargetV2',
|
||||||
});
|
});
|
||||||
const { deleteOneObject } = useDeleteOneObjectRecord({
|
const { deleteOneObject } = useDeleteOneObjectRecord({
|
||||||
objectNamePlural: 'activityTargetV2',
|
objectNamePlural: 'activityTargetV2',
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||||
import { v4 } from 'uuid';
|
|
||||||
|
|
||||||
import { Activity, ActivityType } from '@/activities/types/Activity';
|
import { Activity, ActivityType } from '@/activities/types/Activity';
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { ActivityTarget } from '@/activities/types/ActivityTarget';
|
||||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { useCreateOneObjectRecord } from '@/object-record/hooks/useCreateOneObjectRecord';
|
import { useCreateOneObjectRecord } from '@/object-record/hooks/useCreateOneObjectRecord';
|
||||||
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
|
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
|
||||||
@ -13,14 +12,18 @@ import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope
|
|||||||
import { activityTargetableEntityArrayState } from '../states/activityTargetableEntityArrayState';
|
import { activityTargetableEntityArrayState } from '../states/activityTargetableEntityArrayState';
|
||||||
import { viewableActivityIdState } from '../states/viewableActivityIdState';
|
import { viewableActivityIdState } from '../states/viewableActivityIdState';
|
||||||
import { ActivityTargetableEntity } from '../types/ActivityTargetableEntity';
|
import { ActivityTargetableEntity } from '../types/ActivityTargetableEntity';
|
||||||
import { getRelationData } from '../utils/getRelationData';
|
import { getTargetableEntitiesWithParents } from '../utils/getTargetableEntitiesWithParents';
|
||||||
|
|
||||||
export const useOpenCreateActivityDrawer = () => {
|
export const useOpenCreateActivityDrawer = () => {
|
||||||
const { openRightDrawer } = useRightDrawer();
|
const { openRightDrawer } = useRightDrawer();
|
||||||
const { createOneObject } = useCreateOneObjectRecord({
|
const { createOneObject: createOneActivityTarget } =
|
||||||
objectNamePlural: 'activitiesV2',
|
useCreateOneObjectRecord<ActivityTarget>({
|
||||||
});
|
objectNameSingular: 'activityTargetV2',
|
||||||
const currentUser = useRecoilValue(currentUserState);
|
});
|
||||||
|
const { createOneObject: createOneActivity } =
|
||||||
|
useCreateOneObjectRecord<Activity>({
|
||||||
|
objectNameSingular: 'activityV2',
|
||||||
|
});
|
||||||
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||||
const setHotkeyScope = useSetHotkeyScope();
|
const setHotkeyScope = useSetHotkeyScope();
|
||||||
|
|
||||||
@ -29,7 +32,7 @@ export const useOpenCreateActivityDrawer = () => {
|
|||||||
);
|
);
|
||||||
const [, setViewableActivityId] = useRecoilState(viewableActivityIdState);
|
const [, setViewableActivityId] = useRecoilState(viewableActivityIdState);
|
||||||
|
|
||||||
return ({
|
return async ({
|
||||||
type,
|
type,
|
||||||
targetableEntities,
|
targetableEntities,
|
||||||
assigneeId,
|
assigneeId,
|
||||||
@ -38,33 +41,35 @@ export const useOpenCreateActivityDrawer = () => {
|
|||||||
targetableEntities?: ActivityTargetableEntity[];
|
targetableEntities?: ActivityTargetableEntity[];
|
||||||
assigneeId?: string;
|
assigneeId?: string;
|
||||||
}) => {
|
}) => {
|
||||||
const now = new Date().toISOString();
|
const targetableEntitiesWithRelations = targetableEntities
|
||||||
|
? getTargetableEntitiesWithParents(targetableEntities)
|
||||||
|
: [];
|
||||||
|
|
||||||
createOneObject?.({
|
const createdActivity = await createOneActivity?.({
|
||||||
id: v4(),
|
authorId: currentWorkspaceMember?.id,
|
||||||
createdAt: now,
|
assigneeId: assigneeId ?? currentWorkspaceMember?.id,
|
||||||
updatedAt: now,
|
|
||||||
author: { connect: { id: currentUser?.id ?? '' } },
|
|
||||||
workspaceMemberAuthor: {
|
|
||||||
connect: { id: currentWorkspaceMember?.id ?? '' },
|
|
||||||
},
|
|
||||||
assignee: { connect: { id: assigneeId ?? currentUser?.id ?? '' } },
|
|
||||||
workspaceMemberAssignee: {
|
|
||||||
connect: { id: currentWorkspaceMember?.id ?? '' },
|
|
||||||
},
|
|
||||||
type: type,
|
type: type,
|
||||||
activityTargets: {
|
|
||||||
createMany: {
|
|
||||||
data: targetableEntities ? getRelationData(targetableEntities) : [],
|
|
||||||
skipDuplicates: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
onCompleted: (data: Activity) => {
|
|
||||||
setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false });
|
|
||||||
setViewableActivityId(data.id);
|
|
||||||
setActivityTargetableEntityArray(targetableEntities ?? []);
|
|
||||||
openRightDrawer(RightDrawerPages.CreateActivity);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!createdActivity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
targetableEntitiesWithRelations.map(async (targetableEntity) => {
|
||||||
|
await createOneActivityTarget?.({
|
||||||
|
companyId:
|
||||||
|
targetableEntity.type === 'Company' ? targetableEntity.id : null,
|
||||||
|
personId:
|
||||||
|
targetableEntity.type === 'Person' ? targetableEntity.id : null,
|
||||||
|
activityId: createdActivity.id,
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false });
|
||||||
|
setViewableActivityId(createdActivity.id);
|
||||||
|
setActivityTargetableEntityArray(targetableEntities ?? []);
|
||||||
|
openRightDrawer(RightDrawerPages.CreateActivity);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,45 +1,20 @@
|
|||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
|
||||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
|
import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
|
||||||
import { turnFilterIntoWhereClause } from '@/ui/object/object-filter-dropdown/utils/turnFilterIntoWhereClause';
|
|
||||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
|
||||||
import { SortOrder } from '~/generated/graphql';
|
|
||||||
import { ActivityType } from '~/generated-metadata/graphql';
|
|
||||||
import { parseDate } from '~/utils/date-utils';
|
import { parseDate } from '~/utils/date-utils';
|
||||||
|
|
||||||
export const useCurrentUserTaskCount = () => {
|
export const useCurrentUserTaskCount = () => {
|
||||||
const [currentUser] = useRecoilState(currentUserState);
|
|
||||||
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||||
|
|
||||||
const { objects } = useFindManyObjectRecords({
|
const { objects } = useFindManyObjectRecords({
|
||||||
objectNamePlural: 'activitiesV2',
|
objectNamePlural: 'activitiesV2',
|
||||||
filter: {
|
filter: {
|
||||||
type: { equals: ActivityType.Task },
|
type: { eq: 'Task' },
|
||||||
completedAt: { eq: null },
|
completedAt: { eq: null },
|
||||||
...(currentUser
|
assigneeId: { eq: currentWorkspaceMember?.id },
|
||||||
? turnFilterIntoWhereClause({
|
|
||||||
fieldMetadataId: 'assigneeId',
|
|
||||||
value: currentUser.id,
|
|
||||||
operand: ViewFilterOperand.Is,
|
|
||||||
displayValue:
|
|
||||||
currentWorkspaceMember?.firstName +
|
|
||||||
' ' +
|
|
||||||
currentWorkspaceMember?.lastName,
|
|
||||||
displayAvatarUrl: currentWorkspaceMember?.avatarUrl ?? undefined,
|
|
||||||
definition: {
|
|
||||||
type: 'ENTITY',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
: {}),
|
|
||||||
},
|
},
|
||||||
orderBy: [
|
|
||||||
{
|
|
||||||
createdAt: SortOrder.Desc,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const currentUserDueTaskCount = objects.filter((task) => {
|
const currentUserDueTaskCount = objects.filter((task) => {
|
||||||
|
|||||||
@ -4,11 +4,9 @@ import styled from '@emotion/styled';
|
|||||||
import { ActivityCreateButton } from '@/activities/components/ActivityCreateButton';
|
import { ActivityCreateButton } from '@/activities/components/ActivityCreateButton';
|
||||||
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
|
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
|
||||||
import { Activity } from '@/activities/types/Activity';
|
import { Activity } from '@/activities/types/Activity';
|
||||||
import { ActivityForDrawer } from '@/activities/types/ActivityForDrawer';
|
|
||||||
import { ActivityTargetableEntity } from '@/activities/types/ActivityTargetableEntity';
|
import { ActivityTargetableEntity } from '@/activities/types/ActivityTargetableEntity';
|
||||||
import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
|
import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
|
||||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||||
import { SortOrder } from '~/generated/graphql';
|
|
||||||
|
|
||||||
import { TimelineItemsContainer } from './TimelineItemsContainer';
|
import { TimelineItemsContainer } from './TimelineItemsContainer';
|
||||||
|
|
||||||
@ -50,22 +48,29 @@ const StyledEmptyTimelineSubTitle = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const Timeline = ({ entity }: { entity: ActivityTargetableEntity }) => {
|
export const Timeline = ({ entity }: { entity: ActivityTargetableEntity }) => {
|
||||||
const { objects, loading } = useFindManyObjectRecords({
|
const { objects: activityTargets, loading } = useFindManyObjectRecords({
|
||||||
|
objectNamePlural: 'activityTargetsV2',
|
||||||
|
filter: {
|
||||||
|
or: {
|
||||||
|
companyId: { eq: entity.id },
|
||||||
|
personId: { eq: entity.id },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { objects: activities } = useFindManyObjectRecords({
|
||||||
|
skip: !activityTargets?.length,
|
||||||
objectNamePlural: 'activitiesV2',
|
objectNamePlural: 'activitiesV2',
|
||||||
filter: {
|
filter: {
|
||||||
companyId: { eq: entity.id },
|
activityTargets: { in: activityTargets?.map((at) => at.id) },
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
createdAt: 'AscNullsFirst',
|
||||||
},
|
},
|
||||||
orderBy: [
|
|
||||||
{
|
|
||||||
createdAt: SortOrder.Desc,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const openCreateActivity = useOpenCreateActivityDrawer();
|
const openCreateActivity = useOpenCreateActivityDrawer();
|
||||||
|
|
||||||
const activities: ActivityForDrawer[] = (objects ?? []) as Activity[];
|
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
@ -95,7 +100,7 @@ export const Timeline = ({ entity }: { entity: ActivityTargetableEntity }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledMainContainer>
|
<StyledMainContainer>
|
||||||
<TimelineItemsContainer activities={activities} />
|
<TimelineItemsContainer activities={activities as Activity[]} />
|
||||||
</StyledMainContainer>
|
</StyledMainContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,32 +0,0 @@
|
|||||||
import { v4 } from 'uuid';
|
|
||||||
|
|
||||||
import { ActivityTargetCreateManyActivityInput } from '~/generated/graphql';
|
|
||||||
|
|
||||||
import { ActivityTargetableEntity } from '../types/ActivityTargetableEntity';
|
|
||||||
|
|
||||||
export const getRelationData = (
|
|
||||||
entities: ActivityTargetableEntity[],
|
|
||||||
): ActivityTargetCreateManyActivityInput[] => {
|
|
||||||
const now = new Date().toISOString();
|
|
||||||
|
|
||||||
const relationData: ActivityTargetCreateManyActivityInput[] = [];
|
|
||||||
for (const entity of entities ?? []) {
|
|
||||||
relationData.push({
|
|
||||||
companyId: entity.type === 'Company' ? entity.id : null,
|
|
||||||
personId: entity.type === 'Person' ? entity.id : null,
|
|
||||||
id: v4(),
|
|
||||||
createdAt: now,
|
|
||||||
});
|
|
||||||
if (entity.relatedEntities) {
|
|
||||||
for (const relatedEntity of entity.relatedEntities ?? []) {
|
|
||||||
relationData.push({
|
|
||||||
companyId: relatedEntity.type === 'Company' ? relatedEntity.id : null,
|
|
||||||
personId: relatedEntity.type === 'Person' ? relatedEntity.id : null,
|
|
||||||
id: v4(),
|
|
||||||
createdAt: now,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return relationData;
|
|
||||||
};
|
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
import { ActivityTargetableEntity } from '../types/ActivityTargetableEntity';
|
||||||
|
|
||||||
|
export const getTargetableEntitiesWithParents = (
|
||||||
|
entities: ActivityTargetableEntity[],
|
||||||
|
): ActivityTargetableEntity[] => {
|
||||||
|
const entitiesWithRelations: ActivityTargetableEntity[] = [];
|
||||||
|
for (const entity of entities ?? []) {
|
||||||
|
entitiesWithRelations.push(entity);
|
||||||
|
if (entity.relatedEntities) {
|
||||||
|
for (const relatedEntity of entity.relatedEntities ?? []) {
|
||||||
|
entitiesWithRelations.push(relatedEntity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entitiesWithRelations;
|
||||||
|
};
|
||||||
@ -8,7 +8,10 @@ import { isNonEmptyArray } from '@sniptt/guards';
|
|||||||
import { useRecoilCallback } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
import { GET_COMPANIES } from '@/companies/graphql/queries/getCompanies';
|
import { GET_COMPANIES } from '@/companies/graphql/queries/getCompanies';
|
||||||
import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
import {
|
||||||
|
EMPTY_QUERY,
|
||||||
|
useFindOneObjectMetadataItem,
|
||||||
|
} from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { GET_PEOPLE } from '@/people/graphql/queries/getPeople';
|
import { GET_PEOPLE } from '@/people/graphql/queries/getPeople';
|
||||||
import { GET_API_KEYS } from '@/settings/developers/graphql/queries/getApiKeys';
|
import { GET_API_KEYS } from '@/settings/developers/graphql/queries/getApiKeys';
|
||||||
@ -22,7 +25,7 @@ import { optimisticEffectState } from '../states/optimisticEffectState';
|
|||||||
import { OptimisticEffect } from '../types/internal/OptimisticEffect';
|
import { OptimisticEffect } from '../types/internal/OptimisticEffect';
|
||||||
import { OptimisticEffectDefinition } from '../types/OptimisticEffectDefinition';
|
import { OptimisticEffectDefinition } from '../types/OptimisticEffectDefinition';
|
||||||
|
|
||||||
export const useOptimisticEffect = (objectNameSingular: string) => {
|
export const useOptimisticEffect = (objectNameSingular?: string) => {
|
||||||
const apolloClient = useApolloClient();
|
const apolloClient = useApolloClient();
|
||||||
const { findManyQuery } = useFindOneObjectMetadataItem({
|
const { findManyQuery } = useFindOneObjectMetadataItem({
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
@ -37,6 +40,12 @@ export const useOptimisticEffect = (objectNameSingular: string) => {
|
|||||||
variables: OperationVariables;
|
variables: OperationVariables;
|
||||||
definition: OptimisticEffectDefinition;
|
definition: OptimisticEffectDefinition;
|
||||||
}) => {
|
}) => {
|
||||||
|
if (findManyQuery === EMPTY_QUERY) {
|
||||||
|
throw new Error(
|
||||||
|
`Trying to register an optimistic effect for unknown object ${objectNameSingular}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const optimisticEffects = snapshot
|
const optimisticEffects = snapshot
|
||||||
.getLoadable(optimisticEffectState)
|
.getLoadable(optimisticEffectState)
|
||||||
.getValue();
|
.getValue();
|
||||||
|
|||||||
@ -38,7 +38,6 @@ export const RecordTableContainer = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { updateOneObject } = useUpdateOneObjectRecord({
|
const { updateOneObject } = useUpdateOneObjectRecord({
|
||||||
objectNamePlural,
|
|
||||||
objectNameSingular: foundObjectMetadataItem?.nameSingular,
|
objectNameSingular: foundObjectMetadataItem?.nameSingular,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -30,9 +30,10 @@ export type RecordTablePageProps = Pick<
|
|||||||
export const RecordTablePage = () => {
|
export const RecordTablePage = () => {
|
||||||
const objectNamePlural = useParams().objectNamePlural ?? '';
|
const objectNamePlural = useParams().objectNamePlural ?? '';
|
||||||
|
|
||||||
const { objectNotFoundInMetadata, loading } = useFindOneObjectMetadataItem({
|
const { objectNotFoundInMetadata, loading, foundObjectMetadataItem } =
|
||||||
objectNamePlural,
|
useFindOneObjectMetadataItem({
|
||||||
});
|
objectNamePlural,
|
||||||
|
});
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ export const RecordTablePage = () => {
|
|||||||
}, [objectNotFoundInMetadata, loading, navigate]);
|
}, [objectNotFoundInMetadata, loading, navigate]);
|
||||||
|
|
||||||
const { createOneObject } = useCreateOneObjectRecord({
|
const { createOneObject } = useCreateOneObjectRecord({
|
||||||
objectNamePlural,
|
objectNameSingular: foundObjectMetadataItem?.nameSingular,
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleAddButtonClick = async () => {
|
const handleAddButtonClick = async () => {
|
||||||
|
|||||||
@ -4,60 +4,44 @@ import { v4 } from 'uuid';
|
|||||||
import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect';
|
import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect';
|
||||||
import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
||||||
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
||||||
import { CurrencyCode, FieldMetadataType } from '~/generated-metadata/graphql';
|
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
const defaultFieldValues: Record<FieldMetadataType, unknown> = {
|
export const useCreateOneObjectRecord = <T>({
|
||||||
[FieldMetadataType.Currency]: {
|
objectNameSingular,
|
||||||
amountMicros: null,
|
}: Pick<ObjectMetadataItemIdentifier, 'objectNameSingular'>) => {
|
||||||
currencyCode: CurrencyCode.Usd,
|
const { triggerOptimisticEffects } = useOptimisticEffect(objectNameSingular);
|
||||||
},
|
|
||||||
[FieldMetadataType.Boolean]: false,
|
|
||||||
[FieldMetadataType.Date]: null,
|
|
||||||
[FieldMetadataType.Email]: '',
|
|
||||||
[FieldMetadataType.Enum]: null,
|
|
||||||
[FieldMetadataType.Number]: null,
|
|
||||||
[FieldMetadataType.Probability]: null,
|
|
||||||
[FieldMetadataType.Relation]: null,
|
|
||||||
[FieldMetadataType.Phone]: '',
|
|
||||||
[FieldMetadataType.Text]: '',
|
|
||||||
[FieldMetadataType.Link]: { url: '', label: '' },
|
|
||||||
[FieldMetadataType.Uuid]: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useCreateOneObjectRecord = ({
|
|
||||||
objectNamePlural,
|
|
||||||
}: Pick<ObjectMetadataItemIdentifier, 'objectNamePlural'>) => {
|
|
||||||
const { triggerOptimisticEffects } = useOptimisticEffect('CompanyV2');
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
foundObjectMetadataItem,
|
foundObjectMetadataItem,
|
||||||
objectNotFoundInMetadata,
|
objectNotFoundInMetadata,
|
||||||
createOneMutation,
|
createOneMutation,
|
||||||
} = useFindOneObjectMetadataItem({
|
} = useFindOneObjectMetadataItem({
|
||||||
objectNamePlural,
|
objectNameSingular,
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: type this with a minimal type at least with Record<string, any>
|
// TODO: type this with a minimal type at least with Record<string, any>
|
||||||
const [mutate] = useMutation(createOneMutation);
|
const [mutate] = useMutation(createOneMutation);
|
||||||
|
|
||||||
const createOneObject = foundObjectMetadataItem
|
const createOneObject =
|
||||||
? async (input: Record<string, any>) => {
|
objectNameSingular && foundObjectMetadataItem
|
||||||
const createdObject = await mutate({
|
? async (input: Record<string, any>) => {
|
||||||
variables: {
|
const createdObject = await mutate({
|
||||||
input: { ...input, id: v4() },
|
variables: {
|
||||||
},
|
input: { ...input, id: v4() },
|
||||||
});
|
},
|
||||||
|
});
|
||||||
|
|
||||||
triggerOptimisticEffects(
|
triggerOptimisticEffects(
|
||||||
`${capitalize(foundObjectMetadataItem.nameSingular)}Edge`,
|
`${capitalize(foundObjectMetadataItem.nameSingular)}Edge`,
|
||||||
createdObject.data[
|
createdObject.data[
|
||||||
`create${capitalize(foundObjectMetadataItem.nameSingular)}`
|
`create${capitalize(foundObjectMetadataItem.nameSingular)}`
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
return createdObject.data;
|
return createdObject.data[
|
||||||
}
|
`create${capitalize(objectNameSingular)}`
|
||||||
: undefined;
|
] as T;
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createOneObject,
|
createOneObject,
|
||||||
|
|||||||
@ -2,41 +2,45 @@ import { useMutation } from '@apollo/client';
|
|||||||
|
|
||||||
import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem';
|
||||||
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
||||||
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
export const useUpdateOneObjectRecord = ({
|
export const useUpdateOneObjectRecord = <T>({
|
||||||
objectNamePlural,
|
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
}: ObjectMetadataItemIdentifier) => {
|
}: Pick<ObjectMetadataItemIdentifier, 'objectNameSingular'>) => {
|
||||||
const {
|
const {
|
||||||
foundObjectMetadataItem,
|
foundObjectMetadataItem,
|
||||||
objectNotFoundInMetadata,
|
objectNotFoundInMetadata,
|
||||||
updateOneMutation,
|
updateOneMutation,
|
||||||
} = useFindOneObjectMetadataItem({
|
} = useFindOneObjectMetadataItem({
|
||||||
objectNamePlural,
|
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: type this with a minimal type at least with Record<string, any>
|
// TODO: type this with a minimal type at least with Record<string, any>
|
||||||
const [mutate] = useMutation(updateOneMutation);
|
const [mutate] = useMutation(updateOneMutation);
|
||||||
|
|
||||||
const updateOneObject = foundObjectMetadataItem
|
const updateOneObject =
|
||||||
? ({
|
objectNameSingular && foundObjectMetadataItem
|
||||||
idToUpdate,
|
? async ({
|
||||||
input,
|
idToUpdate,
|
||||||
}: {
|
input,
|
||||||
idToUpdate: string;
|
}: {
|
||||||
input: Record<string, any>;
|
idToUpdate: string;
|
||||||
}) => {
|
input: Record<string, any>;
|
||||||
return mutate({
|
}) => {
|
||||||
variables: {
|
const updatedObject = await mutate({
|
||||||
idToUpdate: idToUpdate,
|
variables: {
|
||||||
input: {
|
idToUpdate: idToUpdate,
|
||||||
...input,
|
input: {
|
||||||
|
...input,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
});
|
|
||||||
}
|
return updatedObject.data[
|
||||||
: undefined;
|
`update${capitalize(objectNameSingular)}`
|
||||||
|
] as T;
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
updateOneObject,
|
updateOneObject,
|
||||||
|
|||||||
@ -10,7 +10,7 @@ export const useColorScheme = () => {
|
|||||||
|
|
||||||
const { updateOneObject: updateOneWorkspaceMember } =
|
const { updateOneObject: updateOneWorkspaceMember } =
|
||||||
useUpdateOneObjectRecord({
|
useUpdateOneObjectRecord({
|
||||||
objectNamePlural: 'workspaceMembersV2',
|
objectNameSingular: 'workspaceMemberV2',
|
||||||
});
|
});
|
||||||
const colorScheme = currentWorkspaceMember?.colorScheme ?? 'System';
|
const colorScheme = currentWorkspaceMember?.colorScheme ?? 'System';
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar';
|
|||||||
import { MainButton } from '@/ui/input/button/components/MainButton';
|
import { MainButton } from '@/ui/input/button/components/MainButton';
|
||||||
import { TextInput } from '@/ui/input/components/TextInput';
|
import { TextInput } from '@/ui/input/components/TextInput';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
|
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
|
||||||
|
|
||||||
const StyledContentContainer = styled.div`
|
const StyledContentContainer = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -59,7 +60,7 @@ export const CreateProfile = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const { updateOneObject, objectNotFoundInMetadata } =
|
const { updateOneObject, objectNotFoundInMetadata } =
|
||||||
useUpdateOneObjectRecord({
|
useUpdateOneObjectRecord<WorkspaceMember>({
|
||||||
objectNameSingular: 'workspaceMemberV2',
|
objectNameSingular: 'workspaceMemberV2',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -91,7 +92,7 @@ export const CreateProfile = () => {
|
|||||||
throw new Error('Object not found in metadata');
|
throw new Error('Object not found in metadata');
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await updateOneObject({
|
await updateOneObject({
|
||||||
idToUpdate: currentWorkspaceMember?.id,
|
idToUpdate: currentWorkspaceMember?.id,
|
||||||
input: {
|
input: {
|
||||||
firstName: data.firstName,
|
firstName: data.firstName,
|
||||||
@ -99,10 +100,6 @@ export const CreateProfile = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result.errors || !result.data?.updateWorkspaceMemberV2) {
|
|
||||||
throw result.errors ?? new Error('Unknown error');
|
|
||||||
}
|
|
||||||
|
|
||||||
setCurrentWorkspaceMember(
|
setCurrentWorkspaceMember(
|
||||||
(current) =>
|
(current) =>
|
||||||
({
|
({
|
||||||
|
|||||||
@ -33,7 +33,7 @@ export const SettingsNewObject = () => {
|
|||||||
} = useObjectMetadataItemForSettings();
|
} = useObjectMetadataItemForSettings();
|
||||||
|
|
||||||
const { createOneObject: createOneView } = useCreateOneObjectRecord({
|
const { createOneObject: createOneView } = useCreateOneObjectRecord({
|
||||||
objectNamePlural: 'viewsV2',
|
objectNameSingular: 'viewV2',
|
||||||
});
|
});
|
||||||
|
|
||||||
const [
|
const [
|
||||||
|
|||||||
@ -45,7 +45,7 @@ export const SettingsObjectNewFieldStep2 = () => {
|
|||||||
const [objectViews, setObjectViews] = useState<View[]>([]);
|
const [objectViews, setObjectViews] = useState<View[]>([]);
|
||||||
|
|
||||||
const { createOneObject: createOneViewField } = useCreateOneObjectRecord({
|
const { createOneObject: createOneViewField } = useCreateOneObjectRecord({
|
||||||
objectNamePlural: 'viewFieldsV2',
|
objectNameSingular: 'viewFieldV2',
|
||||||
});
|
});
|
||||||
|
|
||||||
useFindManyObjectRecords({
|
useFindManyObjectRecords({
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import { TextInput } from '@/ui/input/components/TextInput';
|
|||||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
|
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
|
||||||
import { Section } from '@/ui/layout/section/components/Section';
|
import { Section } from '@/ui/layout/section/components/Section';
|
||||||
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
|
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
|
||||||
import { useGenerateOneApiKeyTokenMutation } from '~/generated/graphql';
|
import { ApiKey, useGenerateOneApiKeyTokenMutation } from '~/generated/graphql';
|
||||||
|
|
||||||
const StyledInfo = styled.span`
|
const StyledInfo = styled.span`
|
||||||
color: ${({ theme }) => theme.font.color.light};
|
color: ${({ theme }) => theme.font.color.light};
|
||||||
@ -47,11 +47,13 @@ export const SettingsDevelopersApiKeyDetail = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const [generateOneApiKeyToken] = useGenerateOneApiKeyTokenMutation();
|
const [generateOneApiKeyToken] = useGenerateOneApiKeyTokenMutation();
|
||||||
const { createOneObject: createOneApiKey } = useCreateOneObjectRecord({
|
const { createOneObject: createOneApiKey } = useCreateOneObjectRecord<ApiKey>(
|
||||||
objectNamePlural: 'apiKeysV2',
|
{
|
||||||
});
|
objectNameSingular: 'apiKeyV2',
|
||||||
const { updateOneObject: updateApiKey } = useUpdateOneObjectRecord({
|
},
|
||||||
objectNamePlural: 'apiKeysV2',
|
);
|
||||||
|
const { updateOneObject: updateApiKey } = useUpdateOneObjectRecord<ApiKey>({
|
||||||
|
objectNameSingular: 'apiKeyV2',
|
||||||
});
|
});
|
||||||
|
|
||||||
const { object: apiKeyData } = useFindOneObjectRecord({
|
const { object: apiKeyData } = useFindOneObjectRecord({
|
||||||
@ -77,17 +79,22 @@ export const SettingsDevelopersApiKeyDetail = () => {
|
|||||||
name: name,
|
name: name,
|
||||||
expiresAt: newExpiresAt,
|
expiresAt: newExpiresAt,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!newApiKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const tokenData = await generateOneApiKeyToken({
|
const tokenData = await generateOneApiKeyToken({
|
||||||
variables: {
|
variables: {
|
||||||
data: {
|
data: {
|
||||||
id: newApiKey.createApiKeyV2.id,
|
id: newApiKey.id,
|
||||||
expiresAt: newApiKey.createApiKeyV2.expiresAt,
|
expiresAt: newApiKey.expiresAt,
|
||||||
name: newApiKey.createApiKeyV2.name, // TODO update typing to remove useless name param here
|
name: newApiKey.name, // TODO update typing to remove useless name param here
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
id: newApiKey.createApiKeyV2.id,
|
id: newApiKey.id,
|
||||||
token: tokenData.data?.generateApiKeyV2Token.token,
|
token: tokenData.data?.generateApiKeyV2Token.token,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -100,7 +107,8 @@ export const SettingsDevelopersApiKeyDetail = () => {
|
|||||||
);
|
);
|
||||||
const apiKey = await createIntegration(apiKeyData.name, newExpiresAt);
|
const apiKey = await createIntegration(apiKeyData.name, newExpiresAt);
|
||||||
await deleteIntegration(false);
|
await deleteIntegration(false);
|
||||||
if (apiKey.token) {
|
|
||||||
|
if (apiKey && apiKey.token) {
|
||||||
setGeneratedApi(apiKey.id, apiKey.token);
|
setGeneratedApi(apiKey.id, apiKey.token);
|
||||||
navigate(`/settings/developers/api-keys/${apiKey.id}`);
|
navigate(`/settings/developers/api-keys/${apiKey.id}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import { TextInput } from '@/ui/input/components/TextInput';
|
|||||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
|
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
|
||||||
import { Section } from '@/ui/layout/section/components/Section';
|
import { Section } from '@/ui/layout/section/components/Section';
|
||||||
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
|
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
|
||||||
import { useGenerateOneApiKeyTokenMutation } from '~/generated/graphql';
|
import { ApiKey, useGenerateOneApiKeyTokenMutation } from '~/generated/graphql';
|
||||||
|
|
||||||
export const SettingsDevelopersApiKeysNew = () => {
|
export const SettingsDevelopersApiKeysNew = () => {
|
||||||
const [generateOneApiKeyToken] = useGenerateOneApiKeyTokenMutation();
|
const [generateOneApiKeyToken] = useGenerateOneApiKeyTokenMutation();
|
||||||
@ -29,9 +29,11 @@ export const SettingsDevelopersApiKeysNew = () => {
|
|||||||
name: '',
|
name: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const { createOneObject: createOneApiKey } = useCreateOneObjectRecord({
|
const { createOneObject: createOneApiKey } = useCreateOneObjectRecord<ApiKey>(
|
||||||
objectNamePlural: 'apiKeysV2',
|
{
|
||||||
});
|
objectNameSingular: 'apiKeyV2',
|
||||||
|
},
|
||||||
|
);
|
||||||
const onSave = async () => {
|
const onSave = async () => {
|
||||||
const expiresAt = formValues.expirationDate
|
const expiresAt = formValues.expirationDate
|
||||||
? DateTime.now().plus({ days: formValues.expirationDate }).toString()
|
? DateTime.now().plus({ days: formValues.expirationDate }).toString()
|
||||||
@ -40,21 +42,23 @@ export const SettingsDevelopersApiKeysNew = () => {
|
|||||||
name: formValues.name,
|
name: formValues.name,
|
||||||
expiresAt,
|
expiresAt,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!newApiKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const tokenData = await generateOneApiKeyToken({
|
const tokenData = await generateOneApiKeyToken({
|
||||||
variables: {
|
variables: {
|
||||||
data: {
|
data: {
|
||||||
id: newApiKey.createApiKeyV2.id,
|
id: newApiKey.id,
|
||||||
expiresAt: newApiKey.createApiKeyV2.expiresAt,
|
expiresAt: newApiKey.expiresAt,
|
||||||
name: newApiKey.createApiKeyV2.name, // TODO update typing to remove useless name param here
|
name: newApiKey.name, // TODO update typing to remove useless name param here
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (tokenData.data?.generateApiKeyV2Token) {
|
if (tokenData.data?.generateApiKeyV2Token) {
|
||||||
setGeneratedApi(
|
setGeneratedApi(newApiKey.id, tokenData.data.generateApiKeyV2Token.token);
|
||||||
newApiKey.createApiKeyV2.id,
|
navigate(`/settings/developers/api-keys/${newApiKey.id}`);
|
||||||
tokenData.data.generateApiKeyV2Token.token,
|
|
||||||
);
|
|
||||||
navigate(`/settings/developers/api-keys/${newApiKey.createApiKeyV2.id}`);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const canSave = !!formValues.name && createOneApiKey;
|
const canSave = !!formValues.name && createOneApiKey;
|
||||||
|
|||||||
@ -112,7 +112,7 @@ export const seedActivityTargetFieldMetadata = async (
|
|||||||
targetColumnMap: {},
|
targetColumnMap: {},
|
||||||
description: 'ActivityTarget activity',
|
description: 'ActivityTarget activity',
|
||||||
icon: 'IconNotes',
|
icon: 'IconNotes',
|
||||||
isNullable: false,
|
isNullable: true,
|
||||||
isSystem: false,
|
isSystem: false,
|
||||||
defaultValue: undefined,
|
defaultValue: undefined,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -283,7 +283,7 @@ export const seedActivityFieldMetadata = async (
|
|||||||
description:
|
description:
|
||||||
'Activity author. This is the person who created the activity',
|
'Activity author. This is the person who created the activity',
|
||||||
icon: 'IconUserCircle',
|
icon: 'IconUserCircle',
|
||||||
isNullable: false,
|
isNullable: true,
|
||||||
isSystem: false,
|
isSystem: false,
|
||||||
defaultValue: undefined,
|
defaultValue: undefined,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -18,12 +18,10 @@ const activityTargetMetadata = {
|
|||||||
type: FieldMetadataType.RELATION,
|
type: FieldMetadataType.RELATION,
|
||||||
name: 'activity',
|
name: 'activity',
|
||||||
label: 'Activity',
|
label: 'Activity',
|
||||||
targetColumnMap: {
|
targetColumnMap: {},
|
||||||
value: 'activityId',
|
|
||||||
},
|
|
||||||
description: 'ActivityTarget activity',
|
description: 'ActivityTarget activity',
|
||||||
icon: 'IconCheckbox',
|
icon: 'IconCheckbox',
|
||||||
isNullable: false,
|
isNullable: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
isCustom: false,
|
isCustom: false,
|
||||||
@ -51,6 +49,45 @@ const activityTargetMetadata = {
|
|||||||
icon: 'IconBuildingSkyscraper',
|
icon: 'IconBuildingSkyscraper',
|
||||||
isNullable: true,
|
isNullable: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
isCustom: false,
|
||||||
|
isActive: true,
|
||||||
|
type: FieldMetadataType.UUID,
|
||||||
|
name: 'activityId',
|
||||||
|
label: 'Activity id (foreign key)',
|
||||||
|
targetColumnMap: {},
|
||||||
|
description: 'ActivityTarget activity id foreign key',
|
||||||
|
icon: undefined,
|
||||||
|
isNullable: false,
|
||||||
|
isSystem: true,
|
||||||
|
defaultValue: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
isCustom: false,
|
||||||
|
isActive: true,
|
||||||
|
type: FieldMetadataType.UUID,
|
||||||
|
name: 'personId',
|
||||||
|
label: 'Person id (foreign key)',
|
||||||
|
targetColumnMap: {},
|
||||||
|
description: 'ActivityTarget person id foreign key',
|
||||||
|
icon: undefined,
|
||||||
|
isNullable: true,
|
||||||
|
isSystem: true,
|
||||||
|
defaultValue: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
isCustom: false,
|
||||||
|
isActive: true,
|
||||||
|
type: FieldMetadataType.UUID,
|
||||||
|
name: 'companyId',
|
||||||
|
label: 'Company id (foreign key)',
|
||||||
|
targetColumnMap: {},
|
||||||
|
description: 'ActivityTarget company id foreign key',
|
||||||
|
icon: undefined,
|
||||||
|
isNullable: true,
|
||||||
|
isSystem: true,
|
||||||
|
defaultValue: undefined,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { SeedWorkspaceId } from 'src/database/seeds/metadata';
|
||||||
import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity';
|
import { FieldMetadataType } from 'src/metadata/field-metadata/field-metadata.entity';
|
||||||
|
|
||||||
const activityMetadata = {
|
const activityMetadata = {
|
||||||
@ -129,28 +130,52 @@ const activityMetadata = {
|
|||||||
type: FieldMetadataType.RELATION,
|
type: FieldMetadataType.RELATION,
|
||||||
name: 'author',
|
name: 'author',
|
||||||
label: 'Author',
|
label: 'Author',
|
||||||
targetColumnMap: {
|
targetColumnMap: {},
|
||||||
value: 'authorId',
|
|
||||||
},
|
|
||||||
description:
|
description:
|
||||||
'Activity author. This is the person who created the activity',
|
'Activity author. This is the person who created the activity',
|
||||||
icon: 'IconUserCircle',
|
icon: 'IconUserCircle',
|
||||||
isNullable: false,
|
isNullable: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
isCustom: false,
|
||||||
|
workspaceId: SeedWorkspaceId,
|
||||||
|
isActive: true,
|
||||||
|
type: FieldMetadataType.UUID,
|
||||||
|
name: 'authorId',
|
||||||
|
label: 'Author id (foreign key)',
|
||||||
|
targetColumnMap: {},
|
||||||
|
description: 'Activity author id foreign key',
|
||||||
|
icon: undefined,
|
||||||
|
isNullable: false,
|
||||||
|
isSystem: true,
|
||||||
|
defaultValue: undefined,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
isCustom: false,
|
isCustom: false,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
type: FieldMetadataType.RELATION,
|
type: FieldMetadataType.RELATION,
|
||||||
name: 'assignee',
|
name: 'assignee',
|
||||||
label: 'Assignee',
|
label: 'Assignee',
|
||||||
targetColumnMap: {
|
targetColumnMap: {},
|
||||||
value: 'assigneeId',
|
|
||||||
},
|
|
||||||
description:
|
description:
|
||||||
'Acitivity assignee. This is the workspace member assigned to the activity ',
|
'Acitivity assignee. This is the workspace member assigned to the activity ',
|
||||||
icon: 'IconUserCircle',
|
icon: 'IconUserCircle',
|
||||||
isNullable: true,
|
isNullable: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
isCustom: false,
|
||||||
|
workspaceId: SeedWorkspaceId,
|
||||||
|
isActive: true,
|
||||||
|
type: FieldMetadataType.UUID,
|
||||||
|
name: 'assigneeId',
|
||||||
|
label: 'Assignee id (foreign key)',
|
||||||
|
targetColumnMap: {},
|
||||||
|
description: 'Acitivity assignee id foreign key',
|
||||||
|
icon: undefined,
|
||||||
|
isNullable: true,
|
||||||
|
isSystem: true,
|
||||||
|
defaultValue: undefined,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user