Merge commit '80a562d90d1d354c580351a2c94d32aa024b139e' into context-menu-vertical

This commit is contained in:
brendanlaschke
2023-08-10 20:27:05 +02:00
53 changed files with 1561 additions and 277 deletions

View File

@ -846,6 +846,20 @@ export type EnumPipelineProgressableTypeFilter = {
notIn?: InputMaybe<Array<PipelineProgressableType>>;
};
export type EnumViewSortDirectionFilter = {
equals?: InputMaybe<ViewSortDirection>;
in?: InputMaybe<Array<ViewSortDirection>>;
not?: InputMaybe<NestedEnumViewSortDirectionFilter>;
notIn?: InputMaybe<Array<ViewSortDirection>>;
};
export type EnumViewTypeFilter = {
equals?: InputMaybe<ViewType>;
in?: InputMaybe<Array<ViewType>>;
not?: InputMaybe<NestedEnumViewTypeFilter>;
notIn?: InputMaybe<Array<ViewType>>;
};
export enum FileFolder {
Attachment = 'Attachment',
PersonPicture = 'PersonPicture',
@ -902,6 +916,7 @@ export type Mutation = {
challenge: LoginToken;
createEvent: Analytics;
createManyViewField: AffectedRows;
createManyViewSort: AffectedRows;
createOneActivity: Activity;
createOneComment: Comment;
createOneCompany: Company;
@ -913,6 +928,7 @@ export type Mutation = {
deleteManyCompany: AffectedRows;
deleteManyPerson: AffectedRows;
deleteManyPipelineProgress: AffectedRows;
deleteManyViewSort: AffectedRows;
deleteUserAccount: User;
deleteWorkspaceMember: WorkspaceMember;
impersonate: Verify;
@ -924,6 +940,7 @@ export type Mutation = {
updateOnePipelineProgress?: Maybe<PipelineProgress>;
updateOnePipelineStage?: Maybe<PipelineStage>;
updateOneViewField: ViewField;
updateOneViewSort: ViewSort;
updateUser: User;
updateWorkspace: Workspace;
uploadAttachment: Scalars['String'];
@ -959,6 +976,12 @@ export type MutationCreateManyViewFieldArgs = {
};
export type MutationCreateManyViewSortArgs = {
data: Array<ViewSortCreateManyInput>;
skipDuplicates?: InputMaybe<Scalars['Boolean']>;
};
export type MutationCreateOneActivityArgs = {
data: ActivityCreateInput;
};
@ -1009,6 +1032,11 @@ export type MutationDeleteManyPipelineProgressArgs = {
};
export type MutationDeleteManyViewSortArgs = {
where?: InputMaybe<ViewSortWhereInput>;
};
export type MutationDeleteWorkspaceMemberArgs = {
where: WorkspaceMemberWhereUniqueInput;
};
@ -1067,6 +1095,12 @@ export type MutationUpdateOneViewFieldArgs = {
};
export type MutationUpdateOneViewSortArgs = {
data: ViewSortUpdateInput;
where: ViewSortWhereUniqueInput;
};
export type MutationUpdateUserArgs = {
data: UserUpdateInput;
where: UserWhereUniqueInput;
@ -1178,6 +1212,20 @@ export type NestedEnumPipelineProgressableTypeFilter = {
notIn?: InputMaybe<Array<PipelineProgressableType>>;
};
export type NestedEnumViewSortDirectionFilter = {
equals?: InputMaybe<ViewSortDirection>;
in?: InputMaybe<Array<ViewSortDirection>>;
not?: InputMaybe<NestedEnumViewSortDirectionFilter>;
notIn?: InputMaybe<Array<ViewSortDirection>>;
};
export type NestedEnumViewTypeFilter = {
equals?: InputMaybe<ViewType>;
in?: InputMaybe<Array<ViewType>>;
not?: InputMaybe<NestedEnumViewTypeFilter>;
notIn?: InputMaybe<Array<ViewType>>;
};
export type NestedIntFilter = {
equals?: InputMaybe<Scalars['Int']>;
gt?: InputMaybe<Scalars['Int']>;
@ -1766,6 +1814,7 @@ export type Query = {
findManyPipelineStage: Array<PipelineStage>;
findManyUser: Array<User>;
findManyViewField: Array<ViewField>;
findManyViewSort: Array<ViewSort>;
findManyWorkspaceMember: Array<WorkspaceMember>;
findUniqueCompany: Company;
findUniquePerson: Person;
@ -1863,6 +1912,16 @@ export type QueryFindManyViewFieldArgs = {
};
export type QueryFindManyViewSortArgs = {
cursor?: InputMaybe<ViewSortWhereUniqueInput>;
distinct?: InputMaybe<Array<ViewSortScalarFieldEnum>>;
orderBy?: InputMaybe<Array<ViewSortOrderByWithRelationInput>>;
skip?: InputMaybe<Scalars['Int']>;
take?: InputMaybe<Scalars['Int']>;
where?: InputMaybe<ViewSortWhereInput>;
};
export type QueryFindManyWorkspaceMemberArgs = {
cursor?: InputMaybe<WorkspaceMemberWhereUniqueInput>;
distinct?: InputMaybe<Array<WorkspaceMemberScalarFieldEnum>>;
@ -2161,6 +2220,20 @@ export type Verify = {
user: User;
};
export type View = {
__typename?: 'View';
fields?: Maybe<Array<ViewField>>;
id: Scalars['ID'];
name: Scalars['String'];
objectId: Scalars['String'];
sorts?: Maybe<Array<ViewSort>>;
type: ViewType;
};
export type ViewCreateNestedOneWithoutFieldsInput = {
connect?: InputMaybe<ViewWhereUniqueInput>;
};
export type ViewField = {
__typename?: 'ViewField';
fieldName: Scalars['String'];
@ -2169,6 +2242,8 @@ export type ViewField = {
isVisible: Scalars['Boolean'];
objectName: Scalars['String'];
sizeInPx: Scalars['Int'];
view?: Maybe<View>;
viewId?: Maybe<Scalars['String']>;
};
export type ViewFieldCreateInput = {
@ -2178,6 +2253,7 @@ export type ViewFieldCreateInput = {
isVisible: Scalars['Boolean'];
objectName: Scalars['String'];
sizeInPx: Scalars['Int'];
view?: InputMaybe<ViewCreateNestedOneWithoutFieldsInput>;
};
export type ViewFieldCreateManyInput = {
@ -2187,6 +2263,17 @@ export type ViewFieldCreateManyInput = {
isVisible: Scalars['Boolean'];
objectName: Scalars['String'];
sizeInPx: Scalars['Int'];
viewId?: InputMaybe<Scalars['String']>;
};
export type ViewFieldListRelationFilter = {
every?: InputMaybe<ViewFieldWhereInput>;
none?: InputMaybe<ViewFieldWhereInput>;
some?: InputMaybe<ViewFieldWhereInput>;
};
export type ViewFieldOrderByRelationAggregateInput = {
_count?: InputMaybe<SortOrder>;
};
export type ViewFieldOrderByWithRelationInput = {
@ -2196,6 +2283,8 @@ export type ViewFieldOrderByWithRelationInput = {
isVisible?: InputMaybe<SortOrder>;
objectName?: InputMaybe<SortOrder>;
sizeInPx?: InputMaybe<SortOrder>;
view?: InputMaybe<ViewOrderByWithRelationInput>;
viewId?: InputMaybe<SortOrder>;
};
export enum ViewFieldScalarFieldEnum {
@ -2205,6 +2294,7 @@ export enum ViewFieldScalarFieldEnum {
IsVisible = 'isVisible',
ObjectName = 'objectName',
SizeInPx = 'sizeInPx',
ViewId = 'viewId',
WorkspaceId = 'workspaceId'
}
@ -2215,6 +2305,7 @@ export type ViewFieldUpdateInput = {
isVisible?: InputMaybe<Scalars['Boolean']>;
objectName?: InputMaybe<Scalars['String']>;
sizeInPx?: InputMaybe<Scalars['Int']>;
view?: InputMaybe<ViewUpdateOneWithoutFieldsNestedInput>;
};
export type ViewFieldUpdateManyWithoutWorkspaceNestedInput = {
@ -2233,10 +2324,156 @@ export type ViewFieldWhereInput = {
isVisible?: InputMaybe<BoolFilter>;
objectName?: InputMaybe<StringFilter>;
sizeInPx?: InputMaybe<IntFilter>;
view?: InputMaybe<ViewRelationFilter>;
viewId?: InputMaybe<StringNullableFilter>;
};
export type ViewFieldWhereUniqueInput = {
id?: InputMaybe<Scalars['String']>;
workspaceId_viewId_objectName_fieldName?: InputMaybe<ViewFieldWorkspaceIdViewIdObjectNameFieldNameCompoundUniqueInput>;
};
export type ViewFieldWorkspaceIdViewIdObjectNameFieldNameCompoundUniqueInput = {
fieldName: Scalars['String'];
objectName: Scalars['String'];
viewId: Scalars['String'];
};
export type ViewOrderByWithRelationInput = {
fields?: InputMaybe<ViewFieldOrderByRelationAggregateInput>;
id?: InputMaybe<SortOrder>;
name?: InputMaybe<SortOrder>;
objectId?: InputMaybe<SortOrder>;
sorts?: InputMaybe<ViewSortOrderByRelationAggregateInput>;
type?: InputMaybe<SortOrder>;
};
export type ViewRelationFilter = {
is?: InputMaybe<ViewWhereInput>;
isNot?: InputMaybe<ViewWhereInput>;
};
export type ViewSort = {
__typename?: 'ViewSort';
direction: ViewSortDirection;
key: Scalars['String'];
name: Scalars['String'];
view: View;
viewId: Scalars['String'];
};
export type ViewSortCreateManyInput = {
direction: ViewSortDirection;
key: Scalars['String'];
name: Scalars['String'];
viewId: Scalars['String'];
};
export enum ViewSortDirection {
Asc = 'asc',
Desc = 'desc'
}
export type ViewSortListRelationFilter = {
every?: InputMaybe<ViewSortWhereInput>;
none?: InputMaybe<ViewSortWhereInput>;
some?: InputMaybe<ViewSortWhereInput>;
};
export type ViewSortOrderByRelationAggregateInput = {
_count?: InputMaybe<SortOrder>;
};
export type ViewSortOrderByWithRelationInput = {
direction?: InputMaybe<SortOrder>;
key?: InputMaybe<SortOrder>;
name?: InputMaybe<SortOrder>;
view?: InputMaybe<ViewOrderByWithRelationInput>;
viewId?: InputMaybe<SortOrder>;
};
export enum ViewSortScalarFieldEnum {
Direction = 'direction',
Key = 'key',
Name = 'name',
ViewId = 'viewId',
WorkspaceId = 'workspaceId'
}
export type ViewSortUpdateInput = {
direction?: InputMaybe<ViewSortDirection>;
key?: InputMaybe<Scalars['String']>;
name?: InputMaybe<Scalars['String']>;
view?: InputMaybe<ViewUpdateOneRequiredWithoutSortsNestedInput>;
};
export type ViewSortUpdateManyWithoutWorkspaceNestedInput = {
connect?: InputMaybe<Array<ViewSortWhereUniqueInput>>;
disconnect?: InputMaybe<Array<ViewSortWhereUniqueInput>>;
set?: InputMaybe<Array<ViewSortWhereUniqueInput>>;
};
export type ViewSortViewIdKeyCompoundUniqueInput = {
key: Scalars['String'];
viewId: Scalars['String'];
};
export type ViewSortWhereInput = {
AND?: InputMaybe<Array<ViewSortWhereInput>>;
NOT?: InputMaybe<Array<ViewSortWhereInput>>;
OR?: InputMaybe<Array<ViewSortWhereInput>>;
direction?: InputMaybe<EnumViewSortDirectionFilter>;
key?: InputMaybe<StringFilter>;
name?: InputMaybe<StringFilter>;
view?: InputMaybe<ViewRelationFilter>;
viewId?: InputMaybe<StringFilter>;
};
export type ViewSortWhereUniqueInput = {
viewId_key?: InputMaybe<ViewSortViewIdKeyCompoundUniqueInput>;
};
export enum ViewType {
Pipeline = 'Pipeline',
Table = 'Table'
}
export type ViewUpdateManyWithoutWorkspaceNestedInput = {
connect?: InputMaybe<Array<ViewWhereUniqueInput>>;
disconnect?: InputMaybe<Array<ViewWhereUniqueInput>>;
set?: InputMaybe<Array<ViewWhereUniqueInput>>;
};
export type ViewUpdateOneRequiredWithoutSortsNestedInput = {
connect?: InputMaybe<ViewWhereUniqueInput>;
};
export type ViewUpdateOneWithoutFieldsNestedInput = {
connect?: InputMaybe<ViewWhereUniqueInput>;
disconnect?: InputMaybe<Scalars['Boolean']>;
};
export type ViewWhereInput = {
AND?: InputMaybe<Array<ViewWhereInput>>;
NOT?: InputMaybe<Array<ViewWhereInput>>;
OR?: InputMaybe<Array<ViewWhereInput>>;
fields?: InputMaybe<ViewFieldListRelationFilter>;
id?: InputMaybe<StringFilter>;
name?: InputMaybe<StringFilter>;
objectId?: InputMaybe<StringFilter>;
sorts?: InputMaybe<ViewSortListRelationFilter>;
type?: InputMaybe<EnumViewTypeFilter>;
};
export type ViewWhereUniqueInput = {
id?: InputMaybe<Scalars['String']>;
workspaceId_type_objectId_name?: InputMaybe<ViewWorkspaceIdTypeObjectIdNameCompoundUniqueInput>;
};
export type ViewWorkspaceIdTypeObjectIdNameCompoundUniqueInput = {
name: Scalars['String'];
objectId: Scalars['String'];
type: ViewType;
};
export type Workspace = {
@ -2258,6 +2495,8 @@ export type Workspace = {
pipelines?: Maybe<Array<Pipeline>>;
updatedAt: Scalars['DateTime'];
viewFields?: Maybe<Array<ViewField>>;
viewSorts?: Maybe<Array<ViewSort>>;
views?: Maybe<Array<View>>;
workspaceMember?: Maybe<Array<WorkspaceMember>>;
};
@ -2337,6 +2576,8 @@ export type WorkspaceUpdateInput = {
pipelines?: InputMaybe<PipelineUpdateManyWithoutWorkspaceNestedInput>;
updatedAt?: InputMaybe<Scalars['DateTime']>;
viewFields?: InputMaybe<ViewFieldUpdateManyWithoutWorkspaceNestedInput>;
viewSorts?: InputMaybe<ViewSortUpdateManyWithoutWorkspaceNestedInput>;
views?: InputMaybe<ViewUpdateManyWithoutWorkspaceNestedInput>;
workspaceMember?: InputMaybe<WorkspaceMemberUpdateManyWithoutWorkspaceNestedInput>;
};
@ -2503,12 +2744,14 @@ export type UpdateOneCompanyMutationVariables = Exact<{
export type UpdateOneCompanyMutation = { __typename?: 'Mutation', updateOneCompany?: { __typename?: 'Company', address: string, createdAt: string, domainName: string, employees?: number | null, linkedinUrl?: string | null, id: string, name: string, accountOwner?: { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null } | null } | null };
export type InsertCompanyFragmentFragment = { __typename?: 'Company', domainName: string, address: string, id: string, name: string, createdAt: string };
export type InsertOneCompanyMutationVariables = Exact<{
data: CompanyCreateInput;
}>;
export type InsertOneCompanyMutation = { __typename?: 'Mutation', createOneCompany: { __typename?: 'Company', address: string, createdAt: string, domainName: string, linkedinUrl?: string | null, employees?: number | null, id: string, name: string } };
export type InsertOneCompanyMutation = { __typename?: 'Mutation', createOneCompany: { __typename?: 'Company', domainName: string, address: string, id: string, name: string, createdAt: string } };
export type DeleteManyCompaniesMutationVariables = Exact<{
ids?: InputMaybe<Array<Scalars['String']> | Scalars['String']>;
@ -2590,12 +2833,14 @@ export type UpdateOnePersonMutationVariables = Exact<{
export type UpdateOnePersonMutation = { __typename?: 'Mutation', updateOnePerson?: { __typename?: 'Person', id: string, city?: string | null, email?: string | null, jobTitle?: string | null, linkedinUrl?: string | null, xUrl?: string | null, firstName?: string | null, lastName?: string | null, displayName: string, phone?: string | null, createdAt: string, company?: { __typename?: 'Company', domainName: string, name: string, id: string } | null } | null };
export type InsertPersonFragmentFragment = { __typename?: 'Person', id: string, firstName?: string | null, lastName?: string | null, displayName: string, createdAt: string };
export type InsertOnePersonMutationVariables = Exact<{
data: PersonCreateInput;
}>;
export type InsertOnePersonMutation = { __typename?: 'Mutation', createOnePerson: { __typename?: 'Person', id: string, city?: string | null, email?: string | null, firstName?: string | null, lastName?: string | null, jobTitle?: string | null, linkedinUrl?: string | null, xUrl?: string | null, displayName: string, phone?: string | null, createdAt: string, company?: { __typename?: 'Company', domainName: string, name: string, id: string } | null } };
export type InsertOnePersonMutation = { __typename?: 'Mutation', createOnePerson: { __typename?: 'Person', id: string, firstName?: string | null, lastName?: string | null, displayName: string, createdAt: string } };
export type DeleteManyPersonMutationVariables = Exact<{
ids?: InputMaybe<Array<Scalars['String']> | Scalars['String']>;
@ -2774,6 +3019,20 @@ export type CreateViewFieldsMutationVariables = Exact<{
export type CreateViewFieldsMutation = { __typename?: 'Mutation', createManyViewField: { __typename?: 'AffectedRows', count: number } };
export type CreateViewSortsMutationVariables = Exact<{
data: Array<ViewSortCreateManyInput> | ViewSortCreateManyInput;
}>;
export type CreateViewSortsMutation = { __typename?: 'Mutation', createManyViewSort: { __typename?: 'AffectedRows', count: number } };
export type DeleteViewSortsMutationVariables = Exact<{
where: ViewSortWhereInput;
}>;
export type DeleteViewSortsMutation = { __typename?: 'Mutation', deleteManyViewSort: { __typename?: 'AffectedRows', count: number } };
export type GetViewFieldsQueryVariables = Exact<{
where?: InputMaybe<ViewFieldWhereInput>;
orderBy?: InputMaybe<Array<ViewFieldOrderByWithRelationInput> | ViewFieldOrderByWithRelationInput>;
@ -2782,6 +3041,13 @@ export type GetViewFieldsQueryVariables = Exact<{
export type GetViewFieldsQuery = { __typename?: 'Query', viewFields: Array<{ __typename?: 'ViewField', id: string, fieldName: string, isVisible: boolean, sizeInPx: number, index: number }> };
export type GetViewSortsQueryVariables = Exact<{
where?: InputMaybe<ViewSortWhereInput>;
}>;
export type GetViewSortsQuery = { __typename?: 'Query', viewSorts: Array<{ __typename?: 'ViewSort', direction: ViewSortDirection, key: string, name: string }> };
export type UpdateViewFieldMutationVariables = Exact<{
data: ViewFieldUpdateInput;
where: ViewFieldWhereUniqueInput;
@ -2790,6 +3056,14 @@ export type UpdateViewFieldMutationVariables = Exact<{
export type UpdateViewFieldMutation = { __typename?: 'Mutation', updateOneViewField: { __typename?: 'ViewField', id: string, fieldName: string, isVisible: boolean, sizeInPx: number, index: number } };
export type UpdateViewSortMutationVariables = Exact<{
data: ViewSortUpdateInput;
where: ViewSortWhereUniqueInput;
}>;
export type UpdateViewSortMutation = { __typename?: 'Mutation', viewSort: { __typename?: 'ViewSort', direction: ViewSortDirection, key: string, name: string } };
export type GetWorkspaceMembersQueryVariables = Exact<{ [key: string]: never; }>;
@ -2849,6 +3123,24 @@ export const ActivityUpdatePartsFragmentDoc = gql`
}
}
`;
export const InsertCompanyFragmentFragmentDoc = gql`
fragment InsertCompanyFragment on Company {
domainName
address
id
name
createdAt
}
`;
export const InsertPersonFragmentFragmentDoc = gql`
fragment InsertPersonFragment on Person {
id
firstName
lastName
displayName
createdAt
}
`;
export const CreateCommentDocument = gql`
mutation CreateComment($commentId: String!, $commentText: String!, $authorId: String!, $activityId: String!, $createdAt: DateTime!) {
createOneComment(
@ -3886,16 +4178,10 @@ export type UpdateOneCompanyMutationOptions = Apollo.BaseMutationOptions<UpdateO
export const InsertOneCompanyDocument = gql`
mutation InsertOneCompany($data: CompanyCreateInput!) {
createOneCompany(data: $data) {
address
createdAt
domainName
linkedinUrl
employees
id
name
...InsertCompanyFragment
}
}
`;
${InsertCompanyFragmentFragmentDoc}`;
export type InsertOneCompanyMutationFn = Apollo.MutationFunction<InsertOneCompanyMutation, InsertOneCompanyMutationVariables>;
/**
@ -4372,25 +4658,10 @@ export type UpdateOnePersonMutationOptions = Apollo.BaseMutationOptions<UpdateOn
export const InsertOnePersonDocument = gql`
mutation InsertOnePerson($data: PersonCreateInput!) {
createOnePerson(data: $data) {
id
city
company {
domainName
name
id
}
email
firstName
lastName
jobTitle
linkedinUrl
xUrl
displayName
phone
createdAt
...InsertPersonFragment
}
}
`;
${InsertPersonFragmentFragmentDoc}`;
export type InsertOnePersonMutationFn = Apollo.MutationFunction<InsertOnePersonMutation, InsertOnePersonMutationVariables>;
/**
@ -5346,6 +5617,72 @@ export function useCreateViewFieldsMutation(baseOptions?: Apollo.MutationHookOpt
export type CreateViewFieldsMutationHookResult = ReturnType<typeof useCreateViewFieldsMutation>;
export type CreateViewFieldsMutationResult = Apollo.MutationResult<CreateViewFieldsMutation>;
export type CreateViewFieldsMutationOptions = Apollo.BaseMutationOptions<CreateViewFieldsMutation, CreateViewFieldsMutationVariables>;
export const CreateViewSortsDocument = gql`
mutation CreateViewSorts($data: [ViewSortCreateManyInput!]!) {
createManyViewSort(data: $data) {
count
}
}
`;
export type CreateViewSortsMutationFn = Apollo.MutationFunction<CreateViewSortsMutation, CreateViewSortsMutationVariables>;
/**
* __useCreateViewSortsMutation__
*
* To run a mutation, you first call `useCreateViewSortsMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useCreateViewSortsMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [createViewSortsMutation, { data, loading, error }] = useCreateViewSortsMutation({
* variables: {
* data: // value for 'data'
* },
* });
*/
export function useCreateViewSortsMutation(baseOptions?: Apollo.MutationHookOptions<CreateViewSortsMutation, CreateViewSortsMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<CreateViewSortsMutation, CreateViewSortsMutationVariables>(CreateViewSortsDocument, options);
}
export type CreateViewSortsMutationHookResult = ReturnType<typeof useCreateViewSortsMutation>;
export type CreateViewSortsMutationResult = Apollo.MutationResult<CreateViewSortsMutation>;
export type CreateViewSortsMutationOptions = Apollo.BaseMutationOptions<CreateViewSortsMutation, CreateViewSortsMutationVariables>;
export const DeleteViewSortsDocument = gql`
mutation DeleteViewSorts($where: ViewSortWhereInput!) {
deleteManyViewSort(where: $where) {
count
}
}
`;
export type DeleteViewSortsMutationFn = Apollo.MutationFunction<DeleteViewSortsMutation, DeleteViewSortsMutationVariables>;
/**
* __useDeleteViewSortsMutation__
*
* To run a mutation, you first call `useDeleteViewSortsMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useDeleteViewSortsMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [deleteViewSortsMutation, { data, loading, error }] = useDeleteViewSortsMutation({
* variables: {
* where: // value for 'where'
* },
* });
*/
export function useDeleteViewSortsMutation(baseOptions?: Apollo.MutationHookOptions<DeleteViewSortsMutation, DeleteViewSortsMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<DeleteViewSortsMutation, DeleteViewSortsMutationVariables>(DeleteViewSortsDocument, options);
}
export type DeleteViewSortsMutationHookResult = ReturnType<typeof useDeleteViewSortsMutation>;
export type DeleteViewSortsMutationResult = Apollo.MutationResult<DeleteViewSortsMutation>;
export type DeleteViewSortsMutationOptions = Apollo.BaseMutationOptions<DeleteViewSortsMutation, DeleteViewSortsMutationVariables>;
export const GetViewFieldsDocument = gql`
query GetViewFields($where: ViewFieldWhereInput, $orderBy: [ViewFieldOrderByWithRelationInput!]) {
viewFields: findManyViewField(where: $where, orderBy: $orderBy) {
@ -5386,6 +5723,43 @@ export function useGetViewFieldsLazyQuery(baseOptions?: Apollo.LazyQueryHookOpti
export type GetViewFieldsQueryHookResult = ReturnType<typeof useGetViewFieldsQuery>;
export type GetViewFieldsLazyQueryHookResult = ReturnType<typeof useGetViewFieldsLazyQuery>;
export type GetViewFieldsQueryResult = Apollo.QueryResult<GetViewFieldsQuery, GetViewFieldsQueryVariables>;
export const GetViewSortsDocument = gql`
query GetViewSorts($where: ViewSortWhereInput) {
viewSorts: findManyViewSort(where: $where) {
direction
key
name
}
}
`;
/**
* __useGetViewSortsQuery__
*
* To run a query within a React component, call `useGetViewSortsQuery` and pass it any options that fit your needs.
* When your component renders, `useGetViewSortsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useGetViewSortsQuery({
* variables: {
* where: // value for 'where'
* },
* });
*/
export function useGetViewSortsQuery(baseOptions?: Apollo.QueryHookOptions<GetViewSortsQuery, GetViewSortsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<GetViewSortsQuery, GetViewSortsQueryVariables>(GetViewSortsDocument, options);
}
export function useGetViewSortsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetViewSortsQuery, GetViewSortsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<GetViewSortsQuery, GetViewSortsQueryVariables>(GetViewSortsDocument, options);
}
export type GetViewSortsQueryHookResult = ReturnType<typeof useGetViewSortsQuery>;
export type GetViewSortsLazyQueryHookResult = ReturnType<typeof useGetViewSortsLazyQuery>;
export type GetViewSortsQueryResult = Apollo.QueryResult<GetViewSortsQuery, GetViewSortsQueryVariables>;
export const UpdateViewFieldDocument = gql`
mutation UpdateViewField($data: ViewFieldUpdateInput!, $where: ViewFieldWhereUniqueInput!) {
updateOneViewField(data: $data, where: $where) {
@ -5424,6 +5798,42 @@ export function useUpdateViewFieldMutation(baseOptions?: Apollo.MutationHookOpti
export type UpdateViewFieldMutationHookResult = ReturnType<typeof useUpdateViewFieldMutation>;
export type UpdateViewFieldMutationResult = Apollo.MutationResult<UpdateViewFieldMutation>;
export type UpdateViewFieldMutationOptions = Apollo.BaseMutationOptions<UpdateViewFieldMutation, UpdateViewFieldMutationVariables>;
export const UpdateViewSortDocument = gql`
mutation UpdateViewSort($data: ViewSortUpdateInput!, $where: ViewSortWhereUniqueInput!) {
viewSort: updateOneViewSort(data: $data, where: $where) {
direction
key
name
}
}
`;
export type UpdateViewSortMutationFn = Apollo.MutationFunction<UpdateViewSortMutation, UpdateViewSortMutationVariables>;
/**
* __useUpdateViewSortMutation__
*
* To run a mutation, you first call `useUpdateViewSortMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useUpdateViewSortMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [updateViewSortMutation, { data, loading, error }] = useUpdateViewSortMutation({
* variables: {
* data: // value for 'data'
* where: // value for 'where'
* },
* });
*/
export function useUpdateViewSortMutation(baseOptions?: Apollo.MutationHookOptions<UpdateViewSortMutation, UpdateViewSortMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<UpdateViewSortMutation, UpdateViewSortMutationVariables>(UpdateViewSortDocument, options);
}
export type UpdateViewSortMutationHookResult = ReturnType<typeof useUpdateViewSortMutation>;
export type UpdateViewSortMutationResult = Apollo.MutationResult<UpdateViewSortMutation>;
export type UpdateViewSortMutationOptions = Apollo.BaseMutationOptions<UpdateViewSortMutation, UpdateViewSortMutationVariables>;
export const GetWorkspaceMembersDocument = gql`
query GetWorkspaceMembers {
workspaceMembers: findManyWorkspaceMember {

View File

@ -37,7 +37,7 @@ export function useOpenCreateActivityDrawer() {
return function openCreateActivityDrawer(
type: ActivityType,
entity?: CommentableEntity,
entities?: CommentableEntity[],
) {
const now = new Date().toISOString();
@ -52,23 +52,19 @@ export function useOpenCreateActivityDrawer() {
type: type,
activityTargets: {
createMany: {
data: entity
? [
{
commentableId: entity.id,
commentableType: entity.type,
companyId:
entity.type === CommentableType.Company
? entity.id
: null,
personId:
entity.type === CommentableType.Person
? entity.id
: null,
id: v4(),
createdAt: now,
},
]
data: entities
? entities.map((entity) => ({
commentableId: entity.id,
commentableType: entity.type,
companyId:
entity.type === CommentableType.Company
? entity.id
: null,
personId:
entity.type === CommentableType.Person ? entity.id : null,
id: v4(),
createdAt: now,
}))
: [],
skipDuplicates: true,
},
@ -85,7 +81,7 @@ export function useOpenCreateActivityDrawer() {
onCompleted(data) {
setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false });
setViewableActivityId(data.createOneActivity.id);
setCommentableEntityArray(entity ? [entity] : []);
setCommentableEntityArray(entities ?? []);
openRightDrawer(RightDrawerPages.CreateActivity);
},
});

View File

@ -1,41 +1,19 @@
import { getOperationName } from '@apollo/client/utilities/graphql/getFromAST';
import { useRecoilState, useRecoilValue } from 'recoil';
import { v4 } from 'uuid';
import { useRecoilValue } from 'recoil';
import { currentUserState } from '@/auth/states/currentUserState';
import { GET_COMPANIES } from '@/companies/queries';
import { GET_PEOPLE } from '@/people/queries';
import { useRightDrawer } from '@/ui/right-drawer/hooks/useRightDrawer';
import { RightDrawerHotkeyScope } from '@/ui/right-drawer/types/RightDrawerHotkeyScope';
import { RightDrawerPages } from '@/ui/right-drawer/types/RightDrawerPages';
import { selectedRowIdsSelector } from '@/ui/table/states/selectedRowIdsSelector';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
import {
ActivityType,
CommentableType,
useCreateActivityMutation,
} from '~/generated/graphql';
import { ActivityType, CommentableType } from '~/generated/graphql';
import { GET_ACTIVITIES_BY_TARGETS, GET_ACTIVITY } from '../queries';
import { commentableEntityArrayState } from '../states/commentableEntityArrayState';
import { viewableActivityIdState } from '../states/viewableActivityIdState';
import { CommentableEntity } from '../types/CommentableEntity';
import { useOpenCreateActivityDrawer } from './useOpenCreateActivityDrawer';
export function useOpenCreateActivityDrawerForSelectedRowIds() {
const { openRightDrawer } = useRightDrawer();
const [createActivityMutation] = useCreateActivityMutation();
const currentUser = useRecoilValue(currentUserState);
const [, setViewableActivityId] = useRecoilState(viewableActivityIdState);
const setHotkeyScope = useSetHotkeyScope();
const [, setCommentableEntityArray] = useRecoilState(
commentableEntityArrayState,
);
const selectedEntityIds = useRecoilValue(selectedRowIdsSelector);
const openCreateActivityDrawer = useOpenCreateActivityDrawer();
return function openCreateCommentDrawerForSelectedRowIds(
type: ActivityType,
entityType: CommentableType,
) {
const commentableEntityArray: CommentableEntity[] = selectedEntityIds.map(
@ -44,45 +22,6 @@ export function useOpenCreateActivityDrawerForSelectedRowIds() {
id,
}),
);
const now = new Date().toISOString();
createActivityMutation({
variables: {
data: {
id: v4(),
createdAt: now,
updatedAt: now,
author: { connect: { id: currentUser?.id ?? '' } },
type: ActivityType.Note,
activityTargets: {
createMany: {
data: commentableEntityArray.map((entity) => ({
commentableId: entity.id,
commentableType: entity.type,
id: v4(),
createdAt: new Date().toISOString(),
companyId:
entity.type === CommentableType.Company ? entity.id : null,
personId:
entity.type === CommentableType.Person ? entity.id : null,
})),
skipDuplicates: true,
},
},
},
},
refetchQueries: [
getOperationName(GET_COMPANIES) ?? '',
getOperationName(GET_PEOPLE) ?? '',
getOperationName(GET_ACTIVITY) ?? '',
getOperationName(GET_ACTIVITIES_BY_TARGETS) ?? '',
],
onCompleted(data) {
setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false });
setViewableActivityId(data.createOneActivity.id);
setCommentableEntityArray(commentableEntityArray);
openRightDrawer(RightDrawerPages.CreateActivity);
},
});
openCreateActivityDrawer(type, commentableEntityArray);
};
}

View File

@ -121,8 +121,8 @@ export function Timeline({ entity }: { entity: CommentableEntity }) {
<StyledEmptyTimelineTitle>No activity yet</StyledEmptyTimelineTitle>
<StyledEmptyTimelineSubTitle>Create one:</StyledEmptyTimelineSubTitle>
<ActivityCreateButton
onNoteClick={() => openCreateActivity(ActivityType.Note, entity)}
onTaskClick={() => openCreateActivity(ActivityType.Task, entity)}
onNoteClick={() => openCreateActivity(ActivityType.Note, [entity])}
onTaskClick={() => openCreateActivity(ActivityType.Task, [entity])}
/>
</StyledTimelineEmptyContainer>
);
@ -132,8 +132,8 @@ export function Timeline({ entity }: { entity: CommentableEntity }) {
<StyledMainContainer>
<StyledTopActionBar>
<ActivityCreateButton
onNoteClick={() => openCreateActivity(ActivityType.Note, entity)}
onTaskClick={() => openCreateActivity(ActivityType.Task, entity)}
onNoteClick={() => openCreateActivity(ActivityType.Note, [entity])}
onTaskClick={() => openCreateActivity(ActivityType.Task, [entity])}
/>
</StyledTopActionBar>
<StyledTimelineContainer>

View File

@ -5,12 +5,11 @@ import { CompaniesSelectedSortType } from '../select';
describe('reduceSortsToOrderBy', () => {
it('should return an array of objects with the id as key and the order as value', () => {
const sorts = [
{ key: 'name', label: 'name', order: 'asc', _type: 'default_sort' },
{ key: 'name', label: 'name', order: 'asc' },
{
key: 'domainName',
label: 'domainName',
order: 'desc',
_type: 'default_sort',
},
] satisfies CompaniesSelectedSortType[];
const result = reduceSortsToOrderBy(sorts);

View File

@ -24,16 +24,20 @@ export const UPDATE_ONE_COMPANY = gql`
}
`;
export const INSERT_COMPANY_FRAGMENT = gql`
fragment InsertCompanyFragment on Company {
domainName
address
id
name
createdAt
}
`;
export const INSERT_ONE_COMPANY = gql`
mutation InsertOneCompany($data: CompanyCreateInput!) {
createOneCompany(data: $data) {
address
createdAt
domainName
linkedinUrl
employees
id
name
...InsertCompanyFragment
}
}
`;

View File

@ -1,30 +1,33 @@
import { useCallback, useMemo, useState } from 'react';
import { useMemo } from 'react';
import { useRecoilValue } from 'recoil';
import { companyViewFields } from '@/companies/constants/companyViewFields';
import { CompaniesSelectedSortType, defaultOrderBy } from '@/companies/queries';
import { reduceSortsToOrderBy } from '@/ui/filter-n-sort/helpers';
import { filtersScopedState } from '@/ui/filter-n-sort/states/filtersScopedState';
import { sortsOrderByScopedState } from '@/ui/filter-n-sort/states/sortScopedState';
import { turnFilterIntoWhereClause } from '@/ui/filter-n-sort/utils/turnFilterIntoWhereClause';
import { IconList } from '@/ui/icon';
import { EntityTable } from '@/ui/table/components/EntityTable';
import { GenericEntityTableData } from '@/ui/table/components/GenericEntityTableData';
import { TableContext } from '@/ui/table/states/TableContext';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useViewSorts } from '@/views/hooks/useViewSorts';
import { currentViewIdState } from '@/views/states/currentViewIdState';
import {
CompanyOrderByWithRelationInput,
useGetCompaniesQuery,
useUpdateOneCompanyMutation,
} from '~/generated/graphql';
import { companiesFilters } from '~/pages/companies/companies-filters';
import { availableSorts } from '~/pages/companies/companies-sorts';
export function CompanyTable() {
const [orderBy, setOrderBy] =
useState<CompanyOrderByWithRelationInput[]>(defaultOrderBy);
import { defaultOrderBy } from '../../queries';
const updateSorts = useCallback((sorts: Array<CompaniesSelectedSortType>) => {
setOrderBy(sorts.length ? reduceSortsToOrderBy(sorts) : defaultOrderBy);
}, []);
export function CompanyTable() {
const currentViewId = useRecoilValue(currentViewIdState);
const orderBy = useRecoilScopedValue(sortsOrderByScopedState, TableContext);
const { updateSorts } = useViewSorts({
availableSorts,
Context: TableContext,
});
const filters = useRecoilScopedValue(filtersScopedState, TableContext);
@ -38,7 +41,7 @@ export function CompanyTable() {
objectName="company"
getRequestResultKey="companies"
useGetRequest={useGetCompaniesQuery}
orderBy={orderBy}
orderBy={orderBy.length ? orderBy : defaultOrderBy}
whereFilters={whereFilters}
viewFieldDefinitions={companyViewFields}
filterDefinitionArray={companiesFilters}
@ -47,7 +50,7 @@ export function CompanyTable() {
viewName="All Companies"
viewIcon={<IconList size={16} />}
availableSorts={availableSorts}
onSortsUpdate={updateSorts}
onSortsUpdate={currentViewId ? updateSorts : undefined}
useUpdateEntityMutation={useUpdateOneCompanyMutation}
/>
</>

View File

@ -1,14 +1,24 @@
import { useOpenCreateActivityDrawerForSelectedRowIds } from '@/activities/hooks/useOpenCreateActivityDrawerForSelectedRowIds';
import { TableActionBarButtonToggleComments } from '@/ui/table/action-bar/components/TableActionBarButtonOpenComments';
import { CommentableType } from '~/generated/graphql';
import { TableActionBarButtonToggleTasks } from '@/ui/table/action-bar/components/TableActionBarButtonOpenTasks';
import { ActivityType, CommentableType } from '~/generated/graphql';
export function TableActionBarButtonCreateActivityCompany() {
const openCreateActivityRightDrawer =
useOpenCreateActivityDrawerForSelectedRowIds();
async function handleButtonClick() {
openCreateActivityRightDrawer(CommentableType.Company);
async function handleButtonClick(type: ActivityType) {
openCreateActivityRightDrawer(type, CommentableType.Company);
}
return <TableActionBarButtonToggleComments onClick={handleButtonClick} />;
return (
<>
<TableActionBarButtonToggleComments
onClick={() => handleButtonClick(ActivityType.Note)}
/>
<TableActionBarButtonToggleTasks
onClick={() => handleButtonClick(ActivityType.Task)}
/>
</>
);
}

View File

@ -1,12 +1,12 @@
import { getOperationName } from '@apollo/client/utilities';
import { useRecoilValue } from 'recoil';
import { useRecoilState, useRecoilValue } from 'recoil';
import { GET_COMPANIES } from '@/companies/queries';
import { GET_PIPELINES } from '@/pipeline/queries';
import { IconTrash } from '@/ui/icon/index';
import { EntityTableActionBarButton } from '@/ui/table/action-bar/components/EntityTableActionBarButton';
import { useResetTableRowSelection } from '@/ui/table/hooks/useResetTableRowSelection';
import { selectedRowIdsSelector } from '@/ui/table/states/selectedRowIdsSelector';
import { tableRowIdsState } from '@/ui/table/states/tableRowIdsState';
import { useDeleteManyCompaniesMutation } from '~/generated/graphql';
export function TableActionBarButtonDeleteCompanies() {
@ -15,12 +15,11 @@ export function TableActionBarButtonDeleteCompanies() {
const resetRowSelection = useResetTableRowSelection();
const [deleteCompanies] = useDeleteManyCompaniesMutation({
refetchQueries: [
getOperationName(GET_COMPANIES) ?? '',
getOperationName(GET_PIPELINES) ?? '',
],
refetchQueries: [getOperationName(GET_PIPELINES) ?? ''],
});
const [tableRowIds, setTableRowIds] = useRecoilState(tableRowIdsState);
async function handleDeleteClick() {
const rowIdsToDelete = selectedRowIds;
@ -30,6 +29,17 @@ export function TableActionBarButtonDeleteCompanies() {
variables: {
ids: rowIdsToDelete,
},
optimisticResponse: {
__typename: 'Mutation',
deleteManyCompany: {
count: rowIdsToDelete.length,
},
},
update: () => {
setTableRowIds(
tableRowIds.filter((id) => !rowIdsToDelete.includes(id)),
);
},
});
}

View File

@ -26,25 +26,20 @@ export const UPDATE_ONE_PERSON = gql`
}
`;
export const INSERT_PERSON_FRAGMENT = gql`
fragment InsertPersonFragment on Person {
id
firstName
lastName
displayName
createdAt
}
`;
export const INSERT_ONE_PERSON = gql`
mutation InsertOnePerson($data: PersonCreateInput!) {
createOnePerson(data: $data) {
id
city
company {
domainName
name
id
}
email
firstName
lastName
jobTitle
linkedinUrl
xUrl
displayName
phone
createdAt
...InsertPersonFragment
}
}
`;

View File

@ -1,31 +1,33 @@
import { useCallback, useMemo, useState } from 'react';
import { useMemo } from 'react';
import { useRecoilValue } from 'recoil';
import { defaultOrderBy } from '@/companies/queries';
import { peopleViewFields } from '@/people/constants/peopleViewFields';
import { PeopleSelectedSortType } from '@/people/queries';
import { reduceSortsToOrderBy } from '@/ui/filter-n-sort/helpers';
import { filtersScopedState } from '@/ui/filter-n-sort/states/filtersScopedState';
import { sortsOrderByScopedState } from '@/ui/filter-n-sort/states/sortScopedState';
import { turnFilterIntoWhereClause } from '@/ui/filter-n-sort/utils/turnFilterIntoWhereClause';
import { IconList } from '@/ui/icon';
import { EntityTable } from '@/ui/table/components/EntityTable';
import { GenericEntityTableData } from '@/ui/table/components/GenericEntityTableData';
import { TableContext } from '@/ui/table/states/TableContext';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useViewSorts } from '@/views/hooks/useViewSorts';
import { currentViewIdState } from '@/views/states/currentViewIdState';
import {
PersonOrderByWithRelationInput,
useGetPeopleQuery,
useUpdateOnePersonMutation,
} from '~/generated/graphql';
import { peopleFilters } from '~/pages/people/people-filters';
import { availableSorts } from '~/pages/people/people-sorts';
export function PeopleTable() {
const [orderBy, setOrderBy] =
useState<PersonOrderByWithRelationInput[]>(defaultOrderBy);
import { defaultOrderBy } from '../../queries';
const updateSorts = useCallback((sorts: Array<PeopleSelectedSortType>) => {
setOrderBy(sorts.length ? reduceSortsToOrderBy(sorts) : defaultOrderBy);
}, []);
export function PeopleTable() {
const currentViewId = useRecoilValue(currentViewIdState);
const orderBy = useRecoilScopedValue(sortsOrderByScopedState, TableContext);
const { updateSorts } = useViewSorts({
availableSorts,
Context: TableContext,
});
const filters = useRecoilScopedValue(filtersScopedState, TableContext);
@ -39,7 +41,7 @@ export function PeopleTable() {
objectName="person"
getRequestResultKey="people"
useGetRequest={useGetPeopleQuery}
orderBy={orderBy}
orderBy={orderBy.length ? orderBy : defaultOrderBy}
whereFilters={whereFilters}
viewFieldDefinitions={peopleViewFields}
filterDefinitionArray={peopleFilters}
@ -48,7 +50,7 @@ export function PeopleTable() {
viewName="All People"
viewIcon={<IconList size={16} />}
availableSorts={availableSorts}
onSortsUpdate={updateSorts}
onSortsUpdate={currentViewId ? updateSorts : undefined}
useUpdateEntityMutation={useUpdateOnePersonMutation}
/>
</>

View File

@ -1,14 +1,24 @@
import { useOpenCreateActivityDrawerForSelectedRowIds } from '@/activities/hooks/useOpenCreateActivityDrawerForSelectedRowIds';
import { TableActionBarButtonToggleComments } from '@/ui/table/action-bar/components/TableActionBarButtonOpenComments';
import { CommentableType } from '~/generated/graphql';
import { TableActionBarButtonToggleTasks } from '@/ui/table/action-bar/components/TableActionBarButtonOpenTasks';
import { ActivityType, CommentableType } from '~/generated/graphql';
export function TableActionBarButtonCreateActivityPeople() {
const openCreateActivityRightDrawer =
useOpenCreateActivityDrawerForSelectedRowIds();
async function handleButtonClick() {
openCreateActivityRightDrawer(CommentableType.Person);
async function handleButtonClick(type: ActivityType) {
openCreateActivityRightDrawer(type, CommentableType.Person);
}
return <TableActionBarButtonToggleComments onClick={handleButtonClick} />;
return (
<>
<TableActionBarButtonToggleComments
onClick={() => handleButtonClick(ActivityType.Note)}
/>
<TableActionBarButtonToggleTasks
onClick={() => handleButtonClick(ActivityType.Task)}
/>
</>
);
}

View File

@ -1,15 +1,17 @@
import { getOperationName } from '@apollo/client/utilities';
import { useRecoilValue } from 'recoil';
import { useRecoilState, useRecoilValue } from 'recoil';
import { GET_PEOPLE } from '@/people/queries';
import { IconTrash } from '@/ui/icon/index';
import { EntityTableActionBarButton } from '@/ui/table/action-bar/components/EntityTableActionBarButton';
import { useResetTableRowSelection } from '@/ui/table/hooks/useResetTableRowSelection';
import { selectedRowIdsSelector } from '@/ui/table/states/selectedRowIdsSelector';
import { tableRowIdsState } from '@/ui/table/states/tableRowIdsState';
import { useDeleteManyPersonMutation } from '~/generated/graphql';
export function TableActionBarButtonDeletePeople() {
const selectedRowIds = useRecoilValue(selectedRowIdsSelector);
const [tableRowIds, setTableRowIds] = useRecoilState(tableRowIdsState);
const resetRowSelection = useResetTableRowSelection();
@ -26,6 +28,17 @@ export function TableActionBarButtonDeletePeople() {
variables: {
ids: rowIdsToDelete,
},
optimisticResponse: {
__typename: 'Mutation',
deleteManyPerson: {
count: rowIdsToDelete.length,
},
},
update: () => {
setTableRowIds(
tableRowIds.filter((id) => !rowIdsToDelete.includes(id)),
);
},
});
}

View File

@ -2,27 +2,16 @@ import { SortOrder as Order_By } from '~/generated/graphql';
import { SelectedSortType } from './types/interface';
const mapOrderToOrder_By = (order: string) => {
if (order === 'asc') return Order_By.Asc;
return Order_By.Desc;
};
export const defaultOrderByTemplateFactory =
(key: string) => (order: string) => ({
[key]: order,
});
export const reduceSortsToOrderBy = <OrderByTemplate>(
sorts: Array<SelectedSortType<OrderByTemplate>>,
): OrderByTemplate[] => {
const mappedSorts = sorts.map((sort) => {
if (sort.orderByTemplates) {
return sort.orderByTemplates?.map((orderByTemplate) =>
orderByTemplate(mapOrderToOrder_By(sort.order)),
sorts: SelectedSortType<OrderByTemplate>[],
): OrderByTemplate[] =>
sorts
.map((sort) => {
const order = sort.order === 'asc' ? Order_By.Asc : Order_By.Desc;
return (
sort.orderByTemplate?.(order) || [
{ [sort.key]: order } as OrderByTemplate,
]
);
}
return defaultOrderByTemplateFactory(sort.key as string)(sort.order);
});
return mappedSorts.flat() as OrderByTemplate[];
};
})
.flat();

View File

@ -1,8 +1,28 @@
import { atomFamily } from 'recoil';
import { atomFamily, selectorFamily } from 'recoil';
import { Filter } from '../types/Filter';
import { reduceSortsToOrderBy } from '../helpers';
import { SelectedSortType } from '../types/interface';
export const sortScopedState = atomFamily<Filter[], string>({
export const sortScopedState = atomFamily<SelectedSortType<any>[], string>({
key: 'sortScopedState',
default: [],
});
export const sortsByKeyScopedState = selectorFamily({
key: 'sortsByKeyScopedState',
get:
(param: string) =>
({ get }) =>
get(sortScopedState(param)).reduce<Record<string, SelectedSortType<any>>>(
(result, sort) => ({ ...result, [sort.key]: sort }),
{},
),
});
export const sortsOrderByScopedState = selectorFamily({
key: 'sortsOrderByScopedState',
get:
(param: string) =>
({ get }) =>
reduceSortsToOrderBy(get(sortScopedState(param))),
});

View File

@ -6,7 +6,7 @@ export type SortType<OrderByTemplate> = {
label: string;
key: string;
icon?: ReactNode;
orderByTemplates?: Array<(order: Order_By) => OrderByTemplate>;
orderByTemplate?: (order: Order_By) => OrderByTemplate[];
};
export type SelectedSortType<OrderByTemplate> = SortType<OrderByTemplate> & {

View File

@ -0,0 +1,17 @@
import { IconCheckbox } from '@/ui/icon/index';
import { EntityTableActionBarButton } from './EntityTableActionBarButton';
type OwnProps = {
onClick: () => void;
};
export function TableActionBarButtonToggleTasks({ onClick }: OwnProps) {
return (
<EntityTableActionBarButton
label="Task"
icon={<IconCheckbox size={16} />}
onClick={onClick}
/>
);
}

View File

@ -5,19 +5,20 @@ import styled from '@emotion/styled';
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
import { IconButton } from '@/ui/button/components/IconButton';
import type {
ViewFieldDefinition,
ViewFieldMetadata,
} from '@/ui/editable-field/types/ViewField';
import { IconPlus } from '@/ui/icon';
import { useTrackPointer } from '@/ui/utilities/pointer-event/hooks/useTrackPointer';
import { GET_VIEW_FIELDS } from '@/views/queries/select';
import { currentViewIdState } from '@/views/states/currentViewIdState';
import {
useCreateViewFieldMutation,
useUpdateViewFieldMutation,
} from '~/generated/graphql';
import type {
ViewFieldDefinition,
ViewFieldMetadata,
} from '../../editable-field/types/ViewField';
import { toViewFieldInput } from '../hooks/useLoadView';
import { toViewFieldInput } from '../hooks/useLoadViewFields';
import { resizeFieldOffsetState } from '../states/resizeFieldOffsetState';
import {
addableViewFieldDefinitionsState,
@ -89,6 +90,7 @@ export function EntityTableHeader() {
const theme = useTheme();
const [{ objectName }, setViewFieldsState] = useRecoilState(viewFieldsState);
const currentViewId = useRecoilValue(currentViewIdState);
const viewFields = useRecoilValue(visibleViewFieldsState);
const columnWidths = useRecoilValue(columnWidthByViewFieldIdState);
const addableViewFieldDefinitions = useRecoilValue(
@ -176,15 +178,18 @@ export function EntityTableHeader() {
createViewFieldMutation({
variables: {
data: toViewFieldInput(objectName, {
...viewFieldDefinition,
columnOrder: viewFields.length + 1,
}),
data: {
...toViewFieldInput(objectName, {
...viewFieldDefinition,
columnOrder: viewFields.length + 1,
}),
view: { connect: { id: currentViewId } },
},
},
refetchQueries: [getOperationName(GET_VIEW_FIELDS) ?? ''],
});
},
[createViewFieldMutation, objectName, viewFields.length],
[createViewFieldMutation, currentViewId, objectName, viewFields.length],
);
return (

View File

@ -6,7 +6,7 @@ import {
import { FilterDefinition } from '@/ui/filter-n-sort/types/FilterDefinition';
import { useSetEntityTableData } from '@/ui/table/hooks/useSetEntityTableData';
import { useLoadView } from '../hooks/useLoadView';
import { useLoadViewFields } from '../hooks/useLoadViewFields';
export function GenericEntityTableData({
objectName,
@ -27,7 +27,7 @@ export function GenericEntityTableData({
}) {
const setEntityTableData = useSetEntityTableData();
useLoadView({ objectName, viewFieldDefinitions });
useLoadViewFields({ objectName, viewFieldDefinitions });
useGetRequest({
variables: { orderBy, where: whereFilters },

View File

@ -40,7 +40,8 @@ export function GenericEditableDoubleTextChipCellDisplayMode({
}),
);
const displayName = `${firstValue} ${secondValue}`;
const displayName =
firstValue || secondValue ? `${firstValue} ${secondValue}` : ' ';
switch (viewField.metadata.entityType) {
case Entity.Company: {

View File

@ -7,6 +7,7 @@ import {
import { useCurrentRowEntityId } from '@/ui/table/hooks/useCurrentEntityId';
import { useUpdateEntityField } from '@/ui/table/hooks/useUpdateEntityField';
import { tableEntityFieldFamilySelector } from '@/ui/table/states/tableEntityFieldFamilySelector';
import { isURL } from '~/utils/is-url';
import { TextCellEdit } from './TextCellEdit';
@ -30,6 +31,8 @@ export function GenericEditableURLCellEditMode({ viewField }: OwnProps) {
function handleSubmit(newText: string) {
if (newText === fieldValue) return;
if (!isURL(newText)) return;
setFieldValue(newText);
if (currentRowEntityId && updateField) {

View File

@ -1,18 +1,19 @@
import { getOperationName } from '@apollo/client/utilities';
import { useSetRecoilState } from 'recoil';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import type {
ViewFieldDefinition,
ViewFieldMetadata,
ViewFieldTextMetadata,
} from '@/ui/editable-field/types/ViewField';
import { GET_VIEW_FIELDS } from '@/views/queries/select';
import { currentViewIdState } from '@/views/states/currentViewIdState';
import {
SortOrder,
useCreateViewFieldsMutation,
useGetViewFieldsQuery,
} from '~/generated/graphql';
import type {
ViewFieldDefinition,
ViewFieldMetadata,
ViewFieldTextMetadata,
} from '../../editable-field/types/ViewField';
import { entityTableDimensionsState } from '../states/entityTableDimensionsState';
import { viewFieldsState } from '../states/viewFieldsState';
@ -33,13 +34,14 @@ export const toViewFieldInput = (
sizeInPx: viewFieldDefinition.columnSize,
});
export const useLoadView = ({
export const useLoadViewFields = ({
objectName,
viewFieldDefinitions,
}: {
objectName: 'company' | 'person';
viewFieldDefinitions: ViewFieldDefinition<ViewFieldMetadata>[];
}) => {
const currentViewId = useRecoilValue(currentViewIdState);
const setEntityTableDimensions = useSetRecoilState(
entityTableDimensionsState,
);
@ -50,7 +52,10 @@ export const useLoadView = ({
useGetViewFieldsQuery({
variables: {
orderBy: { index: SortOrder.Asc },
where: { objectName: { equals: objectName } },
where: {
objectName: { equals: objectName },
viewId: { equals: currentViewId ?? null },
},
},
onCompleted: (data) => {
if (data.viewFields.length) {
@ -79,9 +84,10 @@ export const useLoadView = ({
// Populate if empty
createViewFieldsMutation({
variables: {
data: viewFieldDefinitions.map((viewFieldDefinition) =>
toViewFieldInput(objectName, viewFieldDefinition),
),
data: viewFieldDefinitions.map((viewFieldDefinition) => ({
...toViewFieldInput(objectName, viewFieldDefinition),
viewId: currentViewId,
})),
},
refetchQueries: [getOperationName(GET_VIEW_FIELDS) ?? ''],
});

View File

@ -1,12 +1,14 @@
import { ReactNode, useCallback, useState } from 'react';
import { ReactNode, useCallback } from 'react';
import styled from '@emotion/styled';
import { FilterDropdownButton } from '@/ui/filter-n-sort/components/FilterDropdownButton';
import SortAndFilterBar from '@/ui/filter-n-sort/components/SortAndFilterBar';
import { SortDropdownButton } from '@/ui/filter-n-sort/components/SortDropdownButton';
import { sortScopedState } from '@/ui/filter-n-sort/states/sortScopedState';
import { FiltersHotkeyScope } from '@/ui/filter-n-sort/types/FiltersHotkeyScope';
import { SelectedSortType, SortType } from '@/ui/filter-n-sort/types/interface';
import { TopBar } from '@/ui/top-bar/TopBar';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { OptionsDropdownButton } from '@/views/components/OptionsDropdownButton';
import { TableContext } from '../../states/TableContext';
@ -34,26 +36,26 @@ export function TableHeader<SortField>({
availableSorts,
onSortsUpdate,
}: OwnProps<SortField>) {
const [sorts, innerSetSorts] = useState<Array<SelectedSortType<SortField>>>(
[],
const [sorts, setSorts] = useRecoilScopedState<SelectedSortType<SortField>[]>(
sortScopedState,
TableContext,
);
const handleSortsUpdate = onSortsUpdate ?? setSorts;
const sortSelect = useCallback(
(newSort: SelectedSortType<SortField>) => {
const newSorts = updateSortOrFilterByKey(sorts, newSort);
innerSetSorts(newSorts);
onSortsUpdate && onSortsUpdate(newSorts);
handleSortsUpdate(newSorts);
},
[onSortsUpdate, sorts],
[handleSortsUpdate, sorts],
);
const sortUnselect = useCallback(
(sortKey: string) => {
const newSorts = sorts.filter((sort) => sort.key !== sortKey);
innerSetSorts(newSorts);
onSortsUpdate && onSortsUpdate(newSorts);
handleSortsUpdate(newSorts);
},
[onSortsUpdate, sorts],
[handleSortsUpdate, sorts],
);
return (
@ -88,8 +90,7 @@ export function TableHeader<SortField>({
sorts={sorts}
onRemoveSort={sortUnselect}
onCancelClick={() => {
innerSetSorts([]);
onSortsUpdate && onSortsUpdate([]);
handleSortsUpdate([]);
}}
/>
}

View File

@ -1,10 +1,10 @@
import { Context, useContext } from 'react';
import { RecoilState, useRecoilValue } from 'recoil';
import { RecoilState, RecoilValueReadOnly, useRecoilValue } from 'recoil';
import { RecoilScopeContext } from '../states/RecoilScopeContext';
export function useRecoilScopedValue<T>(
recoilState: (param: string) => RecoilState<T>,
recoilState: (param: string) => RecoilState<T> | RecoilValueReadOnly<T>,
SpecificContext?: Context<string | null>,
) {
const recoilScopeId = useContext(SpecificContext ?? RecoilScopeContext);

View File

@ -0,0 +1,152 @@
import { Context, useCallback } from 'react';
import { getOperationName } from '@apollo/client/utilities';
import { useRecoilValue } from 'recoil';
import {
sortsByKeyScopedState,
sortScopedState,
} from '@/ui/filter-n-sort/states/sortScopedState';
import type {
SelectedSortType,
SortType,
} from '@/ui/filter-n-sort/types/interface';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { currentViewIdState } from '@/views/states/currentViewIdState';
import {
useCreateViewSortsMutation,
useDeleteViewSortsMutation,
useGetViewSortsQuery,
useUpdateViewSortMutation,
ViewSortDirection,
} from '~/generated/graphql';
import { GET_VIEW_SORTS } from '../queries/select';
export const useViewSorts = <SortField>({
availableSorts,
Context,
}: {
availableSorts: SortType<SortField>[];
Context?: Context<string | null>;
}) => {
const currentViewId = useRecoilValue(currentViewIdState);
const [, setSorts] = useRecoilScopedState(sortScopedState, Context);
const sortsByKey = useRecoilScopedValue(sortsByKeyScopedState, Context);
useGetViewSortsQuery({
skip: !currentViewId,
variables: {
where: {
viewId: { equals: currentViewId },
},
},
onCompleted: (data) => {
setSorts(
data.viewSorts
.map((viewSort) => ({
...availableSorts.find((sort) => sort.key === viewSort.key),
label: viewSort.name,
order: viewSort.direction.toLowerCase(),
}))
.filter((sort): sort is SelectedSortType<SortField> => !!sort),
);
},
});
const [createViewSortsMutation] = useCreateViewSortsMutation();
const [updateViewSortMutation] = useUpdateViewSortMutation();
const [deleteViewSortsMutation] = useDeleteViewSortsMutation();
const createViewSorts = useCallback(
(sorts: SelectedSortType<SortField>[]) => {
if (!currentViewId || !sorts.length) return;
return createViewSortsMutation({
variables: {
data: sorts.map((sort) => ({
key: sort.key,
direction: sort.order as ViewSortDirection,
name: sort.label,
viewId: currentViewId,
})),
},
refetchQueries: [getOperationName(GET_VIEW_SORTS) ?? ''],
});
},
[createViewSortsMutation, currentViewId],
);
const updateViewSorts = useCallback(
(sorts: SelectedSortType<SortField>[]) => {
if (!currentViewId || !sorts.length) return;
return Promise.all(
sorts.map((sort) =>
updateViewSortMutation({
variables: {
data: {
direction: sort.order as ViewSortDirection,
},
where: {
viewId_key: { key: sort.key, viewId: currentViewId },
},
},
refetchQueries: [getOperationName(GET_VIEW_SORTS) ?? ''],
}),
),
);
},
[currentViewId, updateViewSortMutation],
);
const deleteViewSorts = useCallback(
(sortKeys: string[]) => {
if (!currentViewId || !sortKeys.length) return;
return deleteViewSortsMutation({
variables: {
where: {
key: { in: sortKeys },
viewId: { equals: currentViewId },
},
},
refetchQueries: [getOperationName(GET_VIEW_SORTS) ?? ''],
});
},
[currentViewId, deleteViewSortsMutation],
);
const updateSorts = useCallback(
async (nextSorts: SelectedSortType<SortField>[]) => {
if (!currentViewId) return;
const sortsToCreate = nextSorts.filter(
(nextSort) => !sortsByKey[nextSort.key],
);
await createViewSorts(sortsToCreate);
const sortsToUpdate = nextSorts.filter(
(nextSort) =>
sortsByKey[nextSort.key] &&
sortsByKey[nextSort.key].order !== nextSort.order,
);
await updateViewSorts(sortsToUpdate);
const nextSortKeys = nextSorts.map((nextSort) => nextSort.key);
const sortKeysToDelete = Object.keys(sortsByKey).filter(
(previousSortKey) => !nextSortKeys.includes(previousSortKey),
);
return deleteViewSorts(sortKeysToDelete);
},
[
createViewSorts,
currentViewId,
deleteViewSorts,
sortsByKey,
updateViewSorts,
],
);
return { updateSorts };
};

View File

@ -19,3 +19,11 @@ export const CREATE_VIEW_FIELDS = gql`
}
}
`;
export const CREATE_VIEW_SORTS = gql`
mutation CreateViewSorts($data: [ViewSortCreateManyInput!]!) {
createManyViewSort(data: $data) {
count
}
}
`;

View File

@ -0,0 +1,9 @@
import { gql } from '@apollo/client';
export const DELETE_VIEW_SORTS = gql`
mutation DeleteViewSorts($where: ViewSortWhereInput!) {
deleteManyViewSort(where: $where) {
count
}
}
`;

View File

@ -14,3 +14,13 @@ export const GET_VIEW_FIELDS = gql`
}
}
`;
export const GET_VIEW_SORTS = gql`
query GetViewSorts($where: ViewSortWhereInput) {
viewSorts: findManyViewSort(where: $where) {
direction
key
name
}
}
`;

View File

@ -14,3 +14,16 @@ export const UPDATE_VIEW_FIELD = gql`
}
}
`;
export const UPDATE_VIEW_SORT = gql`
mutation UpdateViewSort(
$data: ViewSortUpdateInput!
$where: ViewSortWhereUniqueInput!
) {
viewSort: updateOneViewSort(data: $data, where: $where) {
direction
key
name
}
}
`;

View File

@ -0,0 +1,6 @@
import { atom } from 'recoil';
export const currentViewIdState = atom<string | undefined>({
key: 'currentViewIdState',
default: undefined,
});

View File

@ -1,20 +1,21 @@
import { getOperationName } from '@apollo/client/utilities';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useRecoilState } from 'recoil';
import { v4 } from 'uuid';
import { GET_COMPANIES } from '@/companies/queries';
import { CompanyTable } from '@/companies/table/components/CompanyTable';
import { TableActionBarButtonCreateActivityCompany } from '@/companies/table/components/TableActionBarButtonCreateActivityCompany';
import { TableActionBarButtonDeleteCompanies } from '@/companies/table/components/TableActionBarButtonDeleteCompanies';
import { SEARCH_COMPANY_QUERY } from '@/search/queries/search';
import { IconBuildingSkyscraper } from '@/ui/icon';
import { WithTopBarContainer } from '@/ui/layout/components/WithTopBarContainer';
import { EntityTableActionBar } from '@/ui/table/action-bar/components/EntityTableActionBar';
import { TableContext } from '@/ui/table/states/TableContext';
import { tableRowIdsState } from '@/ui/table/states/tableRowIdsState';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { useInsertOneCompanyMutation } from '~/generated/graphql';
import { SEARCH_COMPANY_QUERY } from '../../modules/search/queries/search';
const StyledTableContainer = styled.div`
display: flex;
width: 100%;
@ -22,20 +23,35 @@ const StyledTableContainer = styled.div`
export function Companies() {
const [insertCompany] = useInsertOneCompanyMutation();
const [tableRowIds, setTableRowIds] = useRecoilState(tableRowIdsState);
async function handleAddButtonClick() {
const newCompanyId: string = v4();
await insertCompany({
variables: {
data: {
id: newCompanyId,
name: '',
domainName: '',
address: '',
},
},
refetchQueries: [
getOperationName(GET_COMPANIES) ?? '',
getOperationName(SEARCH_COMPANY_QUERY) ?? '',
],
optimisticResponse: {
__typename: 'Mutation',
createOneCompany: {
__typename: 'Company',
id: newCompanyId,
name: '',
domainName: '',
address: '',
createdAt: '',
},
},
update: (cache, { data }) => {
data?.createOneCompany.id &&
setTableRowIds([data?.createOneCompany.id, ...tableRowIds]);
},
refetchQueries: [getOperationName(SEARCH_COMPANY_QUERY) ?? ''],
});
}

View File

@ -8,7 +8,7 @@ import {
} from '@/ui/icon/index';
import { CompanyOrderByWithRelationInput as Companies_Order_By } from '~/generated/graphql';
export const availableSorts = [
export const availableSorts: SortType<Companies_Order_By>[] = [
{
key: 'name',
label: 'Name',
@ -34,4 +34,4 @@ export const availableSorts = [
label: 'Creation',
icon: <IconCalendarEvent size={16} />,
},
] satisfies Array<SortType<Companies_Order_By>>;
];

View File

@ -1,8 +1,8 @@
import { getOperationName } from '@apollo/client/utilities';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useRecoilState } from 'recoil';
import { v4 } from 'uuid';
import { GET_PEOPLE } from '@/people/queries';
import { PeopleTable } from '@/people/table/components/PeopleTable';
import { TableActionBarButtonCreateActivityPeople } from '@/people/table/components/TableActionBarButtonCreateActivityPeople';
import { TableActionBarButtonDeletePeople } from '@/people/table/components/TableActionBarButtonDeletePeople';
@ -10,6 +10,7 @@ import { IconUser } from '@/ui/icon';
import { WithTopBarContainer } from '@/ui/layout/components/WithTopBarContainer';
import { EntityTableActionBar } from '@/ui/table/action-bar/components/EntityTableActionBar';
import { TableContext } from '@/ui/table/states/TableContext';
import { tableRowIdsState } from '@/ui/table/states/tableRowIdsState';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { useInsertOnePersonMutation } from '~/generated/graphql';
@ -20,16 +21,33 @@ const StyledTableContainer = styled.div`
export function People() {
const [insertOnePerson] = useInsertOnePersonMutation();
const [tableRowIds, setTableRowIds] = useRecoilState(tableRowIdsState);
async function handleAddButtonClick() {
const newPersonId: string = v4();
await insertOnePerson({
variables: {
data: {
id: newPersonId,
firstName: '',
lastName: '',
},
},
refetchQueries: [getOperationName(GET_PEOPLE) ?? ''],
optimisticResponse: {
__typename: 'Mutation',
createOnePerson: {
__typename: 'Person',
id: newPersonId,
firstName: '',
lastName: '',
displayName: '',
createdAt: '',
},
},
update: (cache, { data }) => {
data?.createOnePerson?.id &&
setTableRowIds([data?.createOnePerson.id, ...tableRowIds]);
},
});
}

View File

@ -12,19 +12,15 @@ import {
SortOrder as Order_By,
} from '~/generated/graphql';
export const availableSorts = [
export const availableSorts: SortType<People_Order_By>[] = [
{
key: 'fullname',
label: 'People',
icon: <IconUser size={16} />,
orderByTemplates: [
(order: Order_By) => ({
firstName: order,
}),
(order: Order_By) => ({
lastName: order,
}),
orderByTemplate: (order: Order_By) => [
{ firstName: order },
{ lastName: order },
],
},
{
@ -32,7 +28,7 @@ export const availableSorts = [
label: 'Company',
icon: <IconBuildingSkyscraper size={16} />,
orderByTemplates: [(order: Order_By) => ({ company: { name: order } })],
orderByTemplate: (order: Order_By) => [{ company: { name: order } }],
},
{
key: 'email',
@ -54,4 +50,4 @@ export const availableSorts = [
label: 'City',
icon: <IconMap size={16} />,
},
] satisfies Array<SortType<People_Order_By>>;
];

View File

@ -186,14 +186,22 @@ export function AuthAutoRouter() {
label: 'Create Task',
type: CommandType.Create,
icon: <IconCheckbox />,
onCommandClick: () => openCreateActivity(ActivityType.Task, entity),
onCommandClick: () =>
openCreateActivity(
ActivityType.Task,
entity ? [entity] : undefined,
),
},
{
to: '',
label: 'Create Note',
type: CommandType.Create,
icon: <IconNotes />,
onCommandClick: () => openCreateActivity(ActivityType.Note, entity),
onCommandClick: () =>
openCreateActivity(
ActivityType.Note,
entity ? [entity] : undefined,
),
},
]);
break;
@ -212,14 +220,22 @@ export function AuthAutoRouter() {
label: 'Create Task',
type: CommandType.Create,
icon: <IconCheckbox />,
onCommandClick: () => openCreateActivity(ActivityType.Task, entity),
onCommandClick: () =>
openCreateActivity(
ActivityType.Task,
entity ? [entity] : undefined,
),
},
{
to: '',
label: 'Create Note',
type: CommandType.Create,
icon: <IconNotes />,
onCommandClick: () => openCreateActivity(ActivityType.Note, entity),
onCommandClick: () =>
openCreateActivity(
ActivityType.Note,
entity ? [entity] : undefined,
),
},
]);
break;

View File

@ -0,0 +1,35 @@
import { isURL } from '~/utils/is-url';
describe('isURL', () => {
it(`should return false if null`, () => {
expect(isURL(null)).toBeFalsy();
});
it(`should return false if undefined`, () => {
expect(isURL(undefined)).toBeFalsy();
});
it(`should return true if string google`, () => {
expect(isURL('google')).toBeFalsy();
});
it(`should return true if string google.com`, () => {
expect(isURL('google.com')).toBeTruthy();
});
it(`should return true if string bbc.co.uk`, () => {
expect(isURL('bbc.co.uk')).toBeTruthy();
});
it(`should return true if string web.io`, () => {
expect(isURL('web.io')).toBeTruthy();
});
it(`should return true if string x.com`, () => {
expect(isURL('x.com')).toBeTruthy();
});
it(`should return true if string 2.com`, () => {
expect(isURL('2.com')).toBeTruthy();
});
});

10
front/src/utils/is-url.ts Normal file
View File

@ -0,0 +1,10 @@
import { isDefined } from './isDefined';
export function isURL(url: string | undefined | null) {
return (
isDefined(url) &&
/^((?!-))(xn--)?[a-z0-9][a-z0-9-_]{0,61}[a-z0-9]{0,1}\.(xn--)?([a-z0-9-]{1,61}|[a-z0-9-]{1,30}\.[a-z]{2,})$/.test(
url,
)
);
}