feat: create default opportunities view on workspace creation + add seed data (#1461)

Closes #1314
This commit is contained in:
Thaïs 2023-09-06 12:05:33 +02:00 committed by GitHub
parent 08b56ec7e2
commit 5c7660f588
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 106 additions and 30 deletions

View File

@ -2495,7 +2495,7 @@ export type ViewField = {
key: Scalars['String'];
name: Scalars['String'];
objectId: Scalars['String'];
size: Scalars['Int'];
size?: Maybe<Scalars['Int']>;
view: View;
viewId: Scalars['String'];
};
@ -2506,7 +2506,7 @@ export type ViewFieldCreateInput = {
key: Scalars['String'];
name: Scalars['String'];
objectId: Scalars['String'];
size: Scalars['Int'];
size?: InputMaybe<Scalars['Int']>;
view: ViewCreateNestedOneWithoutFieldsInput;
};
@ -2516,7 +2516,7 @@ export type ViewFieldCreateManyInput = {
key: Scalars['String'];
name: Scalars['String'];
objectId: Scalars['String'];
size: Scalars['Int'];
size?: InputMaybe<Scalars['Int']>;
viewId: Scalars['String'];
};
@ -2592,7 +2592,7 @@ export type ViewFieldWhereInput = {
key?: InputMaybe<StringFilter>;
name?: InputMaybe<StringFilter>;
objectId?: InputMaybe<StringFilter>;
size?: InputMaybe<IntFilter>;
size?: InputMaybe<IntNullableFilter>;
view?: InputMaybe<ViewRelationFilter>;
viewId?: InputMaybe<StringFilter>;
};
@ -3520,7 +3520,7 @@ export type UpdateViewFieldMutationVariables = Exact<{
}>;
export type UpdateViewFieldMutation = { __typename?: 'Mutation', updateOneViewField: { __typename?: 'ViewField', index: number, isVisible: boolean, key: string, name: string, size: number } };
export type UpdateViewFieldMutation = { __typename?: 'Mutation', updateOneViewField: { __typename?: 'ViewField', index: number, isVisible: boolean, key: string, name: string, size?: number | null } };
export type UpdateViewFilterMutationVariables = Exact<{
data: ViewFilterUpdateInput;
@ -3544,7 +3544,7 @@ export type GetViewFieldsQueryVariables = Exact<{
}>;
export type GetViewFieldsQuery = { __typename?: 'Query', viewFields: Array<{ __typename?: 'ViewField', index: number, isVisible: boolean, key: string, name: string, size: number }> };
export type GetViewFieldsQuery = { __typename?: 'Query', viewFields: Array<{ __typename?: 'ViewField', index: number, isVisible: boolean, key: string, name: string, size?: number | null }> };
export type GetViewFiltersQueryVariables = Exact<{
where?: InputMaybe<ViewFilterWhereInput>;

View File

@ -1,10 +1,7 @@
import { useCallback } from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import type {
ViewFieldMetadata,
ViewFieldTextMetadata,
} from '@/ui/editable-field/types/ViewField';
import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField';
import { availableTableColumnsScopedState } from '@/ui/table/states/availableTableColumnsScopedState';
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { savedTableColumnsScopedState } from '@/ui/table/states/savedTableColumnsScopedState';
@ -20,14 +17,9 @@ import {
useGetViewFieldsQuery,
useUpdateViewFieldMutation,
} from '~/generated/graphql';
import { assertNotNull } from '~/utils/assert';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
const DEFAULT_VIEW_FIELD_METADATA: ViewFieldTextMetadata = {
type: 'text',
placeHolder: '',
fieldName: '',
};
const toViewFieldInput = (
objectId: 'company' | 'person',
fieldDefinition: ColumnDefinition<ViewFieldMetadata>,
@ -119,7 +111,6 @@ export const useTableViewFields = ({
variables: {
orderBy: { index: SortOrder.Asc },
where: {
objectId: { equals: objectId },
viewId: { equals: currentTableViewId },
},
},
@ -130,18 +121,24 @@ export const useTableViewFields = ({
return refetch();
}
const nextColumns = data.viewFields.map<
ColumnDefinition<ViewFieldMetadata>
>((viewField) => ({
...(columnDefinitions.find(({ key }) => viewField.key === key) || {
metadata: DEFAULT_VIEW_FIELD_METADATA,
}),
key: viewField.key,
name: viewField.name,
index: viewField.index,
size: viewField.size,
isVisible: viewField.isVisible,
}));
const nextColumns = data.viewFields
.map<ColumnDefinition<ViewFieldMetadata> | null>((viewField) => {
const columnDefinition = columnDefinitions.find(
({ key }) => viewField.key === key,
);
return columnDefinition
? {
...columnDefinition,
key: viewField.key,
name: viewField.name,
index: viewField.index,
size: viewField.size ?? columnDefinition.size,
isVisible: viewField.isVisible,
}
: null;
})
.filter<ColumnDefinition<ViewFieldMetadata>>(assertNotNull);
if (!isDeeplyEqual(tableColumns, nextColumns)) {
setSavedTableColumns(nextColumns);

View File

@ -10,6 +10,7 @@ import { tableColumnsScopedState } from '@/ui/table/states/tableColumnsScopedSta
import { currentTableViewIdState } from '@/ui/table/states/tableViewsState';
import type { ColumnDefinition } from '@/ui/table/types/ColumnDefinition';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { ViewType } from '~/generated/graphql';
import { useTableViewFields } from './useTableViewFields';
import { useViewFilters } from './useViewFilters';
@ -44,6 +45,7 @@ export const useTableViews = <Entity, SortField>({
const { handleViewsChange, isFetchingViews } = useViews({
objectId,
onViewCreate: handleViewCreate,
type: ViewType.Table,
});
const { createViewFields, persistColumns } = useTableViewFields({
objectId,

View File

@ -24,9 +24,11 @@ import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
export const useViews = ({
objectId,
onViewCreate,
type,
}: {
objectId: 'company' | 'person';
onViewCreate: (viewId: string) => Promise<void>;
type: ViewType;
}) => {
const [currentTableViewId, setCurrentTableViewId] = useRecoilScopedState(
currentTableViewIdState,
@ -86,6 +88,7 @@ export const useViews = ({
variables: {
where: {
objectId: { equals: objectId },
type: { equals: type },
},
},
onCompleted: (data) => {

View File

@ -97,5 +97,28 @@
"size": 150
}
]
},
{
"name": "All Opportunities",
"objectId": "company",
"type": "Pipeline",
"fields": [
{
"key": "closeDate",
"name": "Close Date"
},
{
"key": "amount",
"name": "Amount"
},
{
"key": "probability",
"name": "Probability"
},
{
"key": "pointOfContact",
"name": "Point of Contact"
}
]
}
]

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "viewFields" ALTER COLUMN "size" DROP NOT NULL;

View File

@ -662,7 +662,7 @@ model ViewField {
key String
name String
objectId String
size Int
size Int?
view View @relation(fields: [viewId], references: [id], onDelete: Cascade)
viewId String

View File

@ -4,6 +4,7 @@ export const seedViews = async (prisma: PrismaClient) => {
const workspaceId = 'twenty-7ed9d212-1c25-4d02-bf25-6aeccf7ea419';
const companyViewId = 'twenty-5e924b69-a619-41bf-bd31-a9e8551fc9d1';
const personViewId = 'twenty-db9e6c85-c091-4fd6-88b1-c1830f5e90d1';
const opportunitiesViewId = 'twenty-6abb47a2-7a91-4679-a538-59946f0c06a9';
await prisma.view.upsert({
where: { id: companyViewId },
@ -149,4 +150,52 @@ export const seedViews = async (prisma: PrismaClient) => {
}),
),
);
await prisma.view.upsert({
where: { id: opportunitiesViewId },
update: {},
create: {
id: opportunitiesViewId,
name: 'All Opportunities',
objectId: 'company',
type: 'Pipeline',
workspaceId,
},
});
await Promise.all(
[
{
key: 'closeDate',
name: 'Close Date',
},
{
key: 'amount',
name: 'Amount',
},
{
key: 'probability',
name: 'Probability',
},
{
key: 'pointOfContact',
name: 'Point of Contact',
},
].map((viewField, index) =>
prisma.viewField.upsert({
where: {
viewId_key: { key: viewField.key, viewId: opportunitiesViewId },
},
update: {},
create: {
...viewField,
index,
isVisible: true,
objectId: 'company',
viewId: opportunitiesViewId,
workspaceId,
},
}),
),
);
};