@ -953,6 +953,7 @@ export type Mutation = {
|
|||||||
createEvent: Analytics;
|
createEvent: Analytics;
|
||||||
createFavoriteForCompany: Favorite;
|
createFavoriteForCompany: Favorite;
|
||||||
createFavoriteForPerson: Favorite;
|
createFavoriteForPerson: Favorite;
|
||||||
|
createManyView: AffectedRows;
|
||||||
createManyViewField: AffectedRows;
|
createManyViewField: AffectedRows;
|
||||||
createManyViewSort: AffectedRows;
|
createManyViewSort: AffectedRows;
|
||||||
createOneActivity: Activity;
|
createOneActivity: Activity;
|
||||||
@ -978,6 +979,7 @@ export type Mutation = {
|
|||||||
updateOnePerson?: Maybe<Person>;
|
updateOnePerson?: Maybe<Person>;
|
||||||
updateOnePipelineProgress?: Maybe<PipelineProgress>;
|
updateOnePipelineProgress?: Maybe<PipelineProgress>;
|
||||||
updateOnePipelineStage?: Maybe<PipelineStage>;
|
updateOnePipelineStage?: Maybe<PipelineStage>;
|
||||||
|
updateOneView: View;
|
||||||
updateOneViewField: ViewField;
|
updateOneViewField: ViewField;
|
||||||
updateOneViewSort: ViewSort;
|
updateOneViewSort: ViewSort;
|
||||||
updateUser: User;
|
updateUser: User;
|
||||||
@ -1019,6 +1021,12 @@ export type MutationCreateFavoriteForPersonArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationCreateManyViewArgs = {
|
||||||
|
data: Array<ViewCreateManyInput>;
|
||||||
|
skipDuplicates?: InputMaybe<Scalars['Boolean']>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationCreateManyViewFieldArgs = {
|
export type MutationCreateManyViewFieldArgs = {
|
||||||
data: Array<ViewFieldCreateManyInput>;
|
data: Array<ViewFieldCreateManyInput>;
|
||||||
skipDuplicates?: InputMaybe<Scalars['Boolean']>;
|
skipDuplicates?: InputMaybe<Scalars['Boolean']>;
|
||||||
@ -1143,6 +1151,12 @@ export type MutationUpdateOnePipelineStageArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationUpdateOneViewArgs = {
|
||||||
|
data: ViewUpdateInput;
|
||||||
|
where: ViewWhereUniqueInput;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationUpdateOneViewFieldArgs = {
|
export type MutationUpdateOneViewFieldArgs = {
|
||||||
data: ViewFieldUpdateInput;
|
data: ViewFieldUpdateInput;
|
||||||
where: ViewFieldWhereUniqueInput;
|
where: ViewFieldWhereUniqueInput;
|
||||||
@ -1866,6 +1880,7 @@ export type Query = {
|
|||||||
findManyPipelineProgress: Array<PipelineProgress>;
|
findManyPipelineProgress: Array<PipelineProgress>;
|
||||||
findManyPipelineStage: Array<PipelineStage>;
|
findManyPipelineStage: Array<PipelineStage>;
|
||||||
findManyUser: Array<User>;
|
findManyUser: Array<User>;
|
||||||
|
findManyView: Array<View>;
|
||||||
findManyViewField: Array<ViewField>;
|
findManyViewField: Array<ViewField>;
|
||||||
findManyViewSort: Array<ViewSort>;
|
findManyViewSort: Array<ViewSort>;
|
||||||
findManyWorkspaceMember: Array<WorkspaceMember>;
|
findManyWorkspaceMember: Array<WorkspaceMember>;
|
||||||
@ -1955,6 +1970,16 @@ export type QueryFindManyUserArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type QueryFindManyViewArgs = {
|
||||||
|
cursor?: InputMaybe<ViewWhereUniqueInput>;
|
||||||
|
distinct?: InputMaybe<Array<ViewScalarFieldEnum>>;
|
||||||
|
orderBy?: InputMaybe<Array<ViewOrderByWithRelationInput>>;
|
||||||
|
skip?: InputMaybe<Scalars['Int']>;
|
||||||
|
take?: InputMaybe<Scalars['Int']>;
|
||||||
|
where?: InputMaybe<ViewWhereInput>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type QueryFindManyViewFieldArgs = {
|
export type QueryFindManyViewFieldArgs = {
|
||||||
cursor?: InputMaybe<ViewFieldWhereUniqueInput>;
|
cursor?: InputMaybe<ViewFieldWhereUniqueInput>;
|
||||||
distinct?: InputMaybe<Array<ViewFieldScalarFieldEnum>>;
|
distinct?: InputMaybe<Array<ViewFieldScalarFieldEnum>>;
|
||||||
@ -2283,6 +2308,13 @@ export type View = {
|
|||||||
type: ViewType;
|
type: ViewType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ViewCreateManyInput = {
|
||||||
|
id?: InputMaybe<Scalars['String']>;
|
||||||
|
name: Scalars['String'];
|
||||||
|
objectId: Scalars['String'];
|
||||||
|
type: ViewType;
|
||||||
|
};
|
||||||
|
|
||||||
export type ViewCreateNestedOneWithoutFieldsInput = {
|
export type ViewCreateNestedOneWithoutFieldsInput = {
|
||||||
connect?: InputMaybe<ViewWhereUniqueInput>;
|
connect?: InputMaybe<ViewWhereUniqueInput>;
|
||||||
};
|
};
|
||||||
@ -2361,6 +2393,12 @@ export type ViewFieldUpdateInput = {
|
|||||||
view?: InputMaybe<ViewUpdateOneWithoutFieldsNestedInput>;
|
view?: InputMaybe<ViewUpdateOneWithoutFieldsNestedInput>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ViewFieldUpdateManyWithoutViewNestedInput = {
|
||||||
|
connect?: InputMaybe<Array<ViewFieldWhereUniqueInput>>;
|
||||||
|
disconnect?: InputMaybe<Array<ViewFieldWhereUniqueInput>>;
|
||||||
|
set?: InputMaybe<Array<ViewFieldWhereUniqueInput>>;
|
||||||
|
};
|
||||||
|
|
||||||
export type ViewFieldUpdateManyWithoutWorkspaceNestedInput = {
|
export type ViewFieldUpdateManyWithoutWorkspaceNestedInput = {
|
||||||
connect?: InputMaybe<Array<ViewFieldWhereUniqueInput>>;
|
connect?: InputMaybe<Array<ViewFieldWhereUniqueInput>>;
|
||||||
disconnect?: InputMaybe<Array<ViewFieldWhereUniqueInput>>;
|
disconnect?: InputMaybe<Array<ViewFieldWhereUniqueInput>>;
|
||||||
@ -2406,6 +2444,14 @@ export type ViewRelationFilter = {
|
|||||||
isNot?: InputMaybe<ViewWhereInput>;
|
isNot?: InputMaybe<ViewWhereInput>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export enum ViewScalarFieldEnum {
|
||||||
|
Id = 'id',
|
||||||
|
Name = 'name',
|
||||||
|
ObjectId = 'objectId',
|
||||||
|
Type = 'type',
|
||||||
|
WorkspaceId = 'workspaceId'
|
||||||
|
}
|
||||||
|
|
||||||
export type ViewSort = {
|
export type ViewSort = {
|
||||||
__typename?: 'ViewSort';
|
__typename?: 'ViewSort';
|
||||||
direction: ViewSortDirection;
|
direction: ViewSortDirection;
|
||||||
@ -2460,6 +2506,12 @@ export type ViewSortUpdateInput = {
|
|||||||
view?: InputMaybe<ViewUpdateOneRequiredWithoutSortsNestedInput>;
|
view?: InputMaybe<ViewUpdateOneRequiredWithoutSortsNestedInput>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ViewSortUpdateManyWithoutViewNestedInput = {
|
||||||
|
connect?: InputMaybe<Array<ViewSortWhereUniqueInput>>;
|
||||||
|
disconnect?: InputMaybe<Array<ViewSortWhereUniqueInput>>;
|
||||||
|
set?: InputMaybe<Array<ViewSortWhereUniqueInput>>;
|
||||||
|
};
|
||||||
|
|
||||||
export type ViewSortUpdateManyWithoutWorkspaceNestedInput = {
|
export type ViewSortUpdateManyWithoutWorkspaceNestedInput = {
|
||||||
connect?: InputMaybe<Array<ViewSortWhereUniqueInput>>;
|
connect?: InputMaybe<Array<ViewSortWhereUniqueInput>>;
|
||||||
disconnect?: InputMaybe<Array<ViewSortWhereUniqueInput>>;
|
disconnect?: InputMaybe<Array<ViewSortWhereUniqueInput>>;
|
||||||
@ -2491,6 +2543,15 @@ export enum ViewType {
|
|||||||
Table = 'Table'
|
Table = 'Table'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ViewUpdateInput = {
|
||||||
|
fields?: InputMaybe<ViewFieldUpdateManyWithoutViewNestedInput>;
|
||||||
|
id?: InputMaybe<Scalars['String']>;
|
||||||
|
name?: InputMaybe<Scalars['String']>;
|
||||||
|
objectId?: InputMaybe<Scalars['String']>;
|
||||||
|
sorts?: InputMaybe<ViewSortUpdateManyWithoutViewNestedInput>;
|
||||||
|
type?: InputMaybe<ViewType>;
|
||||||
|
};
|
||||||
|
|
||||||
export type ViewUpdateManyWithoutWorkspaceNestedInput = {
|
export type ViewUpdateManyWithoutWorkspaceNestedInput = {
|
||||||
connect?: InputMaybe<Array<ViewWhereUniqueInput>>;
|
connect?: InputMaybe<Array<ViewWhereUniqueInput>>;
|
||||||
disconnect?: InputMaybe<Array<ViewWhereUniqueInput>>;
|
disconnect?: InputMaybe<Array<ViewWhereUniqueInput>>;
|
||||||
@ -3086,6 +3147,13 @@ export type GetUsersQueryVariables = Exact<{ [key: string]: never; }>;
|
|||||||
|
|
||||||
export type GetUsersQuery = { __typename?: 'Query', findManyUser: Array<{ __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null }> };
|
export type GetUsersQuery = { __typename?: 'Query', findManyUser: Array<{ __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null }> };
|
||||||
|
|
||||||
|
export type CreateViewsMutationVariables = Exact<{
|
||||||
|
data: Array<ViewCreateManyInput> | ViewCreateManyInput;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type CreateViewsMutation = { __typename?: 'Mutation', createManyView: { __typename?: 'AffectedRows', count: number } };
|
||||||
|
|
||||||
export type CreateViewFieldsMutationVariables = Exact<{
|
export type CreateViewFieldsMutationVariables = Exact<{
|
||||||
data: Array<ViewFieldCreateManyInput> | ViewFieldCreateManyInput;
|
data: Array<ViewFieldCreateManyInput> | ViewFieldCreateManyInput;
|
||||||
}>;
|
}>;
|
||||||
@ -3107,6 +3175,14 @@ export type DeleteViewSortsMutationVariables = Exact<{
|
|||||||
|
|
||||||
export type DeleteViewSortsMutation = { __typename?: 'Mutation', deleteManyViewSort: { __typename?: 'AffectedRows', count: number } };
|
export type DeleteViewSortsMutation = { __typename?: 'Mutation', deleteManyViewSort: { __typename?: 'AffectedRows', count: number } };
|
||||||
|
|
||||||
|
export type UpdateViewMutationVariables = Exact<{
|
||||||
|
data: ViewUpdateInput;
|
||||||
|
where: ViewWhereUniqueInput;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type UpdateViewMutation = { __typename?: 'Mutation', updateOneView: { __typename?: 'View', id: string, name: string } };
|
||||||
|
|
||||||
export type UpdateViewFieldMutationVariables = Exact<{
|
export type UpdateViewFieldMutationVariables = Exact<{
|
||||||
data: ViewFieldUpdateInput;
|
data: ViewFieldUpdateInput;
|
||||||
where: ViewFieldWhereUniqueInput;
|
where: ViewFieldWhereUniqueInput;
|
||||||
@ -3123,6 +3199,13 @@ export type UpdateViewSortMutationVariables = Exact<{
|
|||||||
|
|
||||||
export type UpdateViewSortMutation = { __typename?: 'Mutation', viewSort: { __typename?: 'ViewSort', direction: ViewSortDirection, key: string, name: string } };
|
export type UpdateViewSortMutation = { __typename?: 'Mutation', viewSort: { __typename?: 'ViewSort', direction: ViewSortDirection, key: string, name: string } };
|
||||||
|
|
||||||
|
export type GetViewsQueryVariables = Exact<{
|
||||||
|
where?: InputMaybe<ViewWhereInput>;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type GetViewsQuery = { __typename?: 'Query', views: Array<{ __typename?: 'View', id: string, name: string }> };
|
||||||
|
|
||||||
export type GetViewFieldsQueryVariables = Exact<{
|
export type GetViewFieldsQueryVariables = Exact<{
|
||||||
where?: InputMaybe<ViewFieldWhereInput>;
|
where?: InputMaybe<ViewFieldWhereInput>;
|
||||||
orderBy?: InputMaybe<Array<ViewFieldOrderByWithRelationInput> | ViewFieldOrderByWithRelationInput>;
|
orderBy?: InputMaybe<Array<ViewFieldOrderByWithRelationInput> | ViewFieldOrderByWithRelationInput>;
|
||||||
@ -5680,6 +5763,39 @@ export function useGetUsersLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<G
|
|||||||
export type GetUsersQueryHookResult = ReturnType<typeof useGetUsersQuery>;
|
export type GetUsersQueryHookResult = ReturnType<typeof useGetUsersQuery>;
|
||||||
export type GetUsersLazyQueryHookResult = ReturnType<typeof useGetUsersLazyQuery>;
|
export type GetUsersLazyQueryHookResult = ReturnType<typeof useGetUsersLazyQuery>;
|
||||||
export type GetUsersQueryResult = Apollo.QueryResult<GetUsersQuery, GetUsersQueryVariables>;
|
export type GetUsersQueryResult = Apollo.QueryResult<GetUsersQuery, GetUsersQueryVariables>;
|
||||||
|
export const CreateViewsDocument = gql`
|
||||||
|
mutation CreateViews($data: [ViewCreateManyInput!]!) {
|
||||||
|
createManyView(data: $data) {
|
||||||
|
count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type CreateViewsMutationFn = Apollo.MutationFunction<CreateViewsMutation, CreateViewsMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useCreateViewsMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useCreateViewsMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useCreateViewsMutation` 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 [createViewsMutation, { data, loading, error }] = useCreateViewsMutation({
|
||||||
|
* variables: {
|
||||||
|
* data: // value for 'data'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useCreateViewsMutation(baseOptions?: Apollo.MutationHookOptions<CreateViewsMutation, CreateViewsMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useMutation<CreateViewsMutation, CreateViewsMutationVariables>(CreateViewsDocument, options);
|
||||||
|
}
|
||||||
|
export type CreateViewsMutationHookResult = ReturnType<typeof useCreateViewsMutation>;
|
||||||
|
export type CreateViewsMutationResult = Apollo.MutationResult<CreateViewsMutation>;
|
||||||
|
export type CreateViewsMutationOptions = Apollo.BaseMutationOptions<CreateViewsMutation, CreateViewsMutationVariables>;
|
||||||
export const CreateViewFieldsDocument = gql`
|
export const CreateViewFieldsDocument = gql`
|
||||||
mutation CreateViewFields($data: [ViewFieldCreateManyInput!]!) {
|
mutation CreateViewFields($data: [ViewFieldCreateManyInput!]!) {
|
||||||
createManyViewField(data: $data) {
|
createManyViewField(data: $data) {
|
||||||
@ -5779,6 +5895,41 @@ export function useDeleteViewSortsMutation(baseOptions?: Apollo.MutationHookOpti
|
|||||||
export type DeleteViewSortsMutationHookResult = ReturnType<typeof useDeleteViewSortsMutation>;
|
export type DeleteViewSortsMutationHookResult = ReturnType<typeof useDeleteViewSortsMutation>;
|
||||||
export type DeleteViewSortsMutationResult = Apollo.MutationResult<DeleteViewSortsMutation>;
|
export type DeleteViewSortsMutationResult = Apollo.MutationResult<DeleteViewSortsMutation>;
|
||||||
export type DeleteViewSortsMutationOptions = Apollo.BaseMutationOptions<DeleteViewSortsMutation, DeleteViewSortsMutationVariables>;
|
export type DeleteViewSortsMutationOptions = Apollo.BaseMutationOptions<DeleteViewSortsMutation, DeleteViewSortsMutationVariables>;
|
||||||
|
export const UpdateViewDocument = gql`
|
||||||
|
mutation UpdateView($data: ViewUpdateInput!, $where: ViewWhereUniqueInput!) {
|
||||||
|
updateOneView(data: $data, where: $where) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type UpdateViewMutationFn = Apollo.MutationFunction<UpdateViewMutation, UpdateViewMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useUpdateViewMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useUpdateViewMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useUpdateViewMutation` 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 [updateViewMutation, { data, loading, error }] = useUpdateViewMutation({
|
||||||
|
* variables: {
|
||||||
|
* data: // value for 'data'
|
||||||
|
* where: // value for 'where'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useUpdateViewMutation(baseOptions?: Apollo.MutationHookOptions<UpdateViewMutation, UpdateViewMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useMutation<UpdateViewMutation, UpdateViewMutationVariables>(UpdateViewDocument, options);
|
||||||
|
}
|
||||||
|
export type UpdateViewMutationHookResult = ReturnType<typeof useUpdateViewMutation>;
|
||||||
|
export type UpdateViewMutationResult = Apollo.MutationResult<UpdateViewMutation>;
|
||||||
|
export type UpdateViewMutationOptions = Apollo.BaseMutationOptions<UpdateViewMutation, UpdateViewMutationVariables>;
|
||||||
export const UpdateViewFieldDocument = gql`
|
export const UpdateViewFieldDocument = gql`
|
||||||
mutation UpdateViewField($data: ViewFieldUpdateInput!, $where: ViewFieldWhereUniqueInput!) {
|
mutation UpdateViewField($data: ViewFieldUpdateInput!, $where: ViewFieldWhereUniqueInput!) {
|
||||||
updateOneViewField(data: $data, where: $where) {
|
updateOneViewField(data: $data, where: $where) {
|
||||||
@ -5853,6 +6004,42 @@ export function useUpdateViewSortMutation(baseOptions?: Apollo.MutationHookOptio
|
|||||||
export type UpdateViewSortMutationHookResult = ReturnType<typeof useUpdateViewSortMutation>;
|
export type UpdateViewSortMutationHookResult = ReturnType<typeof useUpdateViewSortMutation>;
|
||||||
export type UpdateViewSortMutationResult = Apollo.MutationResult<UpdateViewSortMutation>;
|
export type UpdateViewSortMutationResult = Apollo.MutationResult<UpdateViewSortMutation>;
|
||||||
export type UpdateViewSortMutationOptions = Apollo.BaseMutationOptions<UpdateViewSortMutation, UpdateViewSortMutationVariables>;
|
export type UpdateViewSortMutationOptions = Apollo.BaseMutationOptions<UpdateViewSortMutation, UpdateViewSortMutationVariables>;
|
||||||
|
export const GetViewsDocument = gql`
|
||||||
|
query GetViews($where: ViewWhereInput) {
|
||||||
|
views: findManyView(where: $where) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useGetViewsQuery__
|
||||||
|
*
|
||||||
|
* To run a query within a React component, call `useGetViewsQuery` and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useGetViewsQuery` 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 } = useGetViewsQuery({
|
||||||
|
* variables: {
|
||||||
|
* where: // value for 'where'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useGetViewsQuery(baseOptions?: Apollo.QueryHookOptions<GetViewsQuery, GetViewsQueryVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useQuery<GetViewsQuery, GetViewsQueryVariables>(GetViewsDocument, options);
|
||||||
|
}
|
||||||
|
export function useGetViewsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetViewsQuery, GetViewsQueryVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useLazyQuery<GetViewsQuery, GetViewsQueryVariables>(GetViewsDocument, options);
|
||||||
|
}
|
||||||
|
export type GetViewsQueryHookResult = ReturnType<typeof useGetViewsQuery>;
|
||||||
|
export type GetViewsLazyQueryHookResult = ReturnType<typeof useGetViewsLazyQuery>;
|
||||||
|
export type GetViewsQueryResult = Apollo.QueryResult<GetViewsQuery, GetViewsQueryVariables>;
|
||||||
export const GetViewFieldsDocument = gql`
|
export const GetViewFieldsDocument = gql`
|
||||||
query GetViewFields($where: ViewFieldWhereInput, $orderBy: [ViewFieldOrderByWithRelationInput!]) {
|
query GetViewFields($where: ViewFieldWhereInput, $orderBy: [ViewFieldOrderByWithRelationInput!]) {
|
||||||
viewFields: findManyViewField(where: $where, orderBy: $orderBy) {
|
viewFields: findManyViewField(where: $where, orderBy: $orderBy) {
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
|
|
||||||
import { companyViewFields } from '@/companies/constants/companyViewFields';
|
import { companyViewFields } from '@/companies/constants/companyViewFields';
|
||||||
import { useCompanyTableActionBarEntries } from '@/companies/hooks/useCompanyTableActionBarEntries';
|
import { useCompanyTableActionBarEntries } from '@/companies/hooks/useCompanyTableActionBarEntries';
|
||||||
@ -7,15 +6,15 @@ import { useCompanyTableContextMenuEntries } from '@/companies/hooks/useCompanyT
|
|||||||
import { filtersScopedState } from '@/ui/filter-n-sort/states/filtersScopedState';
|
import { filtersScopedState } from '@/ui/filter-n-sort/states/filtersScopedState';
|
||||||
import { sortsOrderByScopedState } from '@/ui/filter-n-sort/states/sortScopedState';
|
import { sortsOrderByScopedState } from '@/ui/filter-n-sort/states/sortScopedState';
|
||||||
import { turnFilterIntoWhereClause } from '@/ui/filter-n-sort/utils/turnFilterIntoWhereClause';
|
import { turnFilterIntoWhereClause } from '@/ui/filter-n-sort/utils/turnFilterIntoWhereClause';
|
||||||
import { IconList } from '@/ui/icon';
|
|
||||||
import { EntityTable } from '@/ui/table/components/EntityTable';
|
import { EntityTable } from '@/ui/table/components/EntityTable';
|
||||||
import { GenericEntityTableData } from '@/ui/table/components/GenericEntityTableData';
|
import { GenericEntityTableData } from '@/ui/table/components/GenericEntityTableData';
|
||||||
import { useUpsertEntityTableItem } from '@/ui/table/hooks/useUpsertEntityTableItem';
|
import { useUpsertEntityTableItem } from '@/ui/table/hooks/useUpsertEntityTableItem';
|
||||||
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
|
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
|
||||||
|
import { currentTableViewIdState } from '@/ui/table/states/tableViewsState';
|
||||||
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
import { useTableViewFields } from '@/views/hooks/useTableViewFields';
|
import { useTableViewFields } from '@/views/hooks/useTableViewFields';
|
||||||
|
import { useTableViews } from '@/views/hooks/useTableViews';
|
||||||
import { useViewSorts } from '@/views/hooks/useViewSorts';
|
import { useViewSorts } from '@/views/hooks/useViewSorts';
|
||||||
import { currentViewIdState } from '@/views/states/currentViewIdState';
|
|
||||||
import {
|
import {
|
||||||
SortOrder,
|
SortOrder,
|
||||||
UpdateOneCompanyMutationVariables,
|
UpdateOneCompanyMutationVariables,
|
||||||
@ -26,7 +25,10 @@ import { companiesFilters } from '~/pages/companies/companies-filters';
|
|||||||
import { availableSorts } from '~/pages/companies/companies-sorts';
|
import { availableSorts } from '~/pages/companies/companies-sorts';
|
||||||
|
|
||||||
export function CompanyTable() {
|
export function CompanyTable() {
|
||||||
const currentViewId = useRecoilValue(currentViewIdState);
|
const currentViewId = useRecoilScopedValue(
|
||||||
|
currentTableViewIdState,
|
||||||
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
const orderBy = useRecoilScopedValue(
|
const orderBy = useRecoilScopedValue(
|
||||||
sortsOrderByScopedState,
|
sortsOrderByScopedState,
|
||||||
TableRecoilScopeContext,
|
TableRecoilScopeContext,
|
||||||
@ -34,14 +36,13 @@ export function CompanyTable() {
|
|||||||
const [updateEntityMutation] = useUpdateOneCompanyMutation();
|
const [updateEntityMutation] = useUpdateOneCompanyMutation();
|
||||||
const upsertEntityTableItem = useUpsertEntityTableItem();
|
const upsertEntityTableItem = useUpsertEntityTableItem();
|
||||||
|
|
||||||
|
const objectId = 'company';
|
||||||
|
const { handleViewsChange } = useTableViews({ objectId });
|
||||||
const { handleColumnsChange } = useTableViewFields({
|
const { handleColumnsChange } = useTableViewFields({
|
||||||
objectName: 'company',
|
objectName: objectId,
|
||||||
viewFieldDefinitions: companyViewFields,
|
viewFieldDefinitions: companyViewFields,
|
||||||
});
|
});
|
||||||
const { updateSorts } = useViewSorts({
|
const { updateSorts } = useViewSorts({ availableSorts });
|
||||||
availableSorts,
|
|
||||||
Context: TableRecoilScopeContext,
|
|
||||||
});
|
|
||||||
|
|
||||||
const filters = useRecoilScopedValue(
|
const filters = useRecoilScopedValue(
|
||||||
filtersScopedState,
|
filtersScopedState,
|
||||||
@ -76,10 +77,10 @@ export function CompanyTable() {
|
|||||||
/>
|
/>
|
||||||
<EntityTable
|
<EntityTable
|
||||||
viewName="All Companies"
|
viewName="All Companies"
|
||||||
viewIcon={<IconList size={16} />}
|
|
||||||
availableSorts={availableSorts}
|
availableSorts={availableSorts}
|
||||||
onColumnsChange={handleColumnsChange}
|
onColumnsChange={handleColumnsChange}
|
||||||
onSortsUpdate={currentViewId ? updateSorts : undefined}
|
onSortsUpdate={currentViewId ? updateSorts : undefined}
|
||||||
|
onViewsChange={handleViewsChange}
|
||||||
updateEntityMutation={({
|
updateEntityMutation={({
|
||||||
variables,
|
variables,
|
||||||
}: {
|
}: {
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { IconList } from '@/ui/icon';
|
|
||||||
import { EntityTable } from '@/ui/table/components/EntityTable';
|
import { EntityTable } from '@/ui/table/components/EntityTable';
|
||||||
import { useUpdateOneCompanyMutation } from '~/generated/graphql';
|
import { useUpdateOneCompanyMutation } from '~/generated/graphql';
|
||||||
import { availableSorts } from '~/pages/companies/companies-sorts';
|
import { availableSorts } from '~/pages/companies/companies-sorts';
|
||||||
@ -11,7 +10,6 @@ export function CompanyTableMockMode() {
|
|||||||
<CompanyTableMockData />
|
<CompanyTableMockData />
|
||||||
<EntityTable
|
<EntityTable
|
||||||
viewName="All Companies"
|
viewName="All Companies"
|
||||||
viewIcon={<IconList size={16} />}
|
|
||||||
availableSorts={availableSorts}
|
availableSorts={availableSorts}
|
||||||
updateEntityMutation={[useUpdateOneCompanyMutation()]}
|
updateEntityMutation={[useUpdateOneCompanyMutation()]}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
|
|
||||||
import { peopleViewFields } from '@/people/constants/peopleViewFields';
|
import { peopleViewFields } from '@/people/constants/peopleViewFields';
|
||||||
import { usePersonTableContextMenuEntries } from '@/people/hooks/usePeopleTableContextMenuEntries';
|
import { usePersonTableContextMenuEntries } from '@/people/hooks/usePeopleTableContextMenuEntries';
|
||||||
@ -7,15 +6,15 @@ import { usePersonTableActionBarEntries } from '@/people/hooks/usePersonTableAct
|
|||||||
import { filtersScopedState } from '@/ui/filter-n-sort/states/filtersScopedState';
|
import { filtersScopedState } from '@/ui/filter-n-sort/states/filtersScopedState';
|
||||||
import { sortsOrderByScopedState } from '@/ui/filter-n-sort/states/sortScopedState';
|
import { sortsOrderByScopedState } from '@/ui/filter-n-sort/states/sortScopedState';
|
||||||
import { turnFilterIntoWhereClause } from '@/ui/filter-n-sort/utils/turnFilterIntoWhereClause';
|
import { turnFilterIntoWhereClause } from '@/ui/filter-n-sort/utils/turnFilterIntoWhereClause';
|
||||||
import { IconList } from '@/ui/icon';
|
|
||||||
import { EntityTable } from '@/ui/table/components/EntityTable';
|
import { EntityTable } from '@/ui/table/components/EntityTable';
|
||||||
import { GenericEntityTableData } from '@/ui/table/components/GenericEntityTableData';
|
import { GenericEntityTableData } from '@/ui/table/components/GenericEntityTableData';
|
||||||
import { useUpsertEntityTableItem } from '@/ui/table/hooks/useUpsertEntityTableItem';
|
import { useUpsertEntityTableItem } from '@/ui/table/hooks/useUpsertEntityTableItem';
|
||||||
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
|
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
|
||||||
|
import { currentTableViewIdState } from '@/ui/table/states/tableViewsState';
|
||||||
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
import { useTableViewFields } from '@/views/hooks/useTableViewFields';
|
import { useTableViewFields } from '@/views/hooks/useTableViewFields';
|
||||||
|
import { useTableViews } from '@/views/hooks/useTableViews';
|
||||||
import { useViewSorts } from '@/views/hooks/useViewSorts';
|
import { useViewSorts } from '@/views/hooks/useViewSorts';
|
||||||
import { currentViewIdState } from '@/views/states/currentViewIdState';
|
|
||||||
import {
|
import {
|
||||||
SortOrder,
|
SortOrder,
|
||||||
UpdateOnePersonMutationVariables,
|
UpdateOnePersonMutationVariables,
|
||||||
@ -26,7 +25,10 @@ import { peopleFilters } from '~/pages/people/people-filters';
|
|||||||
import { availableSorts } from '~/pages/people/people-sorts';
|
import { availableSorts } from '~/pages/people/people-sorts';
|
||||||
|
|
||||||
export function PeopleTable() {
|
export function PeopleTable() {
|
||||||
const currentViewId = useRecoilValue(currentViewIdState);
|
const currentViewId = useRecoilScopedValue(
|
||||||
|
currentTableViewIdState,
|
||||||
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
const orderBy = useRecoilScopedValue(
|
const orderBy = useRecoilScopedValue(
|
||||||
sortsOrderByScopedState,
|
sortsOrderByScopedState,
|
||||||
TableRecoilScopeContext,
|
TableRecoilScopeContext,
|
||||||
@ -34,14 +36,13 @@ export function PeopleTable() {
|
|||||||
const [updateEntityMutation] = useUpdateOnePersonMutation();
|
const [updateEntityMutation] = useUpdateOnePersonMutation();
|
||||||
const upsertEntityTableItem = useUpsertEntityTableItem();
|
const upsertEntityTableItem = useUpsertEntityTableItem();
|
||||||
|
|
||||||
|
const objectId = 'person';
|
||||||
|
const { handleViewsChange } = useTableViews({ objectId });
|
||||||
const { handleColumnsChange } = useTableViewFields({
|
const { handleColumnsChange } = useTableViewFields({
|
||||||
objectName: 'person',
|
objectName: objectId,
|
||||||
viewFieldDefinitions: peopleViewFields,
|
viewFieldDefinitions: peopleViewFields,
|
||||||
});
|
});
|
||||||
const { updateSorts } = useViewSorts({
|
const { updateSorts } = useViewSorts({ availableSorts });
|
||||||
availableSorts,
|
|
||||||
Context: TableRecoilScopeContext,
|
|
||||||
});
|
|
||||||
|
|
||||||
const filters = useRecoilScopedValue(
|
const filters = useRecoilScopedValue(
|
||||||
filtersScopedState,
|
filtersScopedState,
|
||||||
@ -76,10 +77,10 @@ export function PeopleTable() {
|
|||||||
/>
|
/>
|
||||||
<EntityTable
|
<EntityTable
|
||||||
viewName="All People"
|
viewName="All People"
|
||||||
viewIcon={<IconList size={16} />}
|
|
||||||
availableSorts={availableSorts}
|
availableSorts={availableSorts}
|
||||||
onColumnsChange={handleColumnsChange}
|
onColumnsChange={handleColumnsChange}
|
||||||
onSortsUpdate={currentViewId ? updateSorts : undefined}
|
onSortsUpdate={currentViewId ? updateSorts : undefined}
|
||||||
|
onViewsChange={handleViewsChange}
|
||||||
updateEntityMutation={({
|
updateEntityMutation={({
|
||||||
variables,
|
variables,
|
||||||
}: {
|
}: {
|
||||||
|
|||||||
@ -0,0 +1,34 @@
|
|||||||
|
import { forwardRef, InputHTMLAttributes } from 'react';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import { textInputStyle } from '@/ui/theme/constants/effects';
|
||||||
|
|
||||||
|
export const DropdownMenuInputContainer = styled.div`
|
||||||
|
--vertical-padding: ${({ theme }) => theme.spacing(1)};
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
height: calc(36px - 2 * var(--vertical-padding));
|
||||||
|
padding: var(--vertical-padding) 0;
|
||||||
|
|
||||||
|
width: calc(100%);
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledInput = styled.input`
|
||||||
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
|
|
||||||
|
${textInputStyle}
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const DropdownMenuInput = forwardRef<
|
||||||
|
HTMLInputElement,
|
||||||
|
InputHTMLAttributes<HTMLInputElement>
|
||||||
|
>((props, ref) => (
|
||||||
|
<DropdownMenuInputContainer>
|
||||||
|
<StyledInput autoComplete="off" placeholder="Search" {...props} ref={ref} />
|
||||||
|
</DropdownMenuInputContainer>
|
||||||
|
));
|
||||||
@ -1,39 +0,0 @@
|
|||||||
import { InputHTMLAttributes } from 'react';
|
|
||||||
import styled from '@emotion/styled';
|
|
||||||
|
|
||||||
import { textInputStyle } from '@/ui/theme/constants/effects';
|
|
||||||
|
|
||||||
export const DropdownMenuSearchContainer = styled.div`
|
|
||||||
--vertical-padding: ${({ theme }) => theme.spacing(1)};
|
|
||||||
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
height: calc(36px - 2 * var(--vertical-padding));
|
|
||||||
padding: var(--vertical-padding) 0;
|
|
||||||
|
|
||||||
width: calc(100%);
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledEditModeSearchInput = styled.input`
|
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
|
||||||
|
|
||||||
${textInputStyle}
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export function DropdownMenuSearch(
|
|
||||||
props: InputHTMLAttributes<HTMLInputElement>,
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
<DropdownMenuSearchContainer>
|
|
||||||
<StyledEditModeSearchInput
|
|
||||||
autoComplete="off"
|
|
||||||
{...props}
|
|
||||||
placeholder={props.placeholder ?? 'Search'}
|
|
||||||
/>
|
|
||||||
</DropdownMenuSearchContainer>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -11,9 +11,9 @@ import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
|||||||
import { DropdownMenu } from '../DropdownMenu';
|
import { DropdownMenu } from '../DropdownMenu';
|
||||||
import { DropdownMenuCheckableItem } from '../DropdownMenuCheckableItem';
|
import { DropdownMenuCheckableItem } from '../DropdownMenuCheckableItem';
|
||||||
import { DropdownMenuHeader } from '../DropdownMenuHeader';
|
import { DropdownMenuHeader } from '../DropdownMenuHeader';
|
||||||
|
import { DropdownMenuInput } from '../DropdownMenuInput';
|
||||||
import { DropdownMenuItem } from '../DropdownMenuItem';
|
import { DropdownMenuItem } from '../DropdownMenuItem';
|
||||||
import { DropdownMenuItemsContainer } from '../DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '../DropdownMenuItemsContainer';
|
||||||
import { DropdownMenuSearch } from '../DropdownMenuSearch';
|
|
||||||
import { DropdownMenuSelectableItem } from '../DropdownMenuSelectableItem';
|
import { DropdownMenuSelectableItem } from '../DropdownMenuSelectableItem';
|
||||||
import { DropdownMenuSeparator } from '../DropdownMenuSeparator';
|
import { DropdownMenuSeparator } from '../DropdownMenuSeparator';
|
||||||
import { DropdownMenuSubheader } from '../DropdownMenuSubheader';
|
import { DropdownMenuSubheader } from '../DropdownMenuSubheader';
|
||||||
@ -256,7 +256,7 @@ export const LoadingMenu: Story = {
|
|||||||
...WithContentBelow,
|
...WithContentBelow,
|
||||||
render: () => (
|
render: () => (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuSearch value={'query'} autoFocus />
|
<DropdownMenuInput value={'query'} autoFocus />
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItemsContainer hasMaxHeight>
|
<DropdownMenuItemsContainer hasMaxHeight>
|
||||||
<DropdownMenuSkeletonItem />
|
<DropdownMenuSkeletonItem />
|
||||||
@ -269,7 +269,7 @@ export const Search: Story = {
|
|||||||
...WithContentBelow,
|
...WithContentBelow,
|
||||||
render: (args) => (
|
render: (args) => (
|
||||||
<DropdownMenu {...args}>
|
<DropdownMenu {...args}>
|
||||||
<DropdownMenuSearch />
|
<DropdownMenuInput />
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItemsContainer hasMaxHeight>
|
<DropdownMenuItemsContainer hasMaxHeight>
|
||||||
{mockSelectArray.map(({ name }) => (
|
{mockSelectArray.map(({ name }) => (
|
||||||
|
|||||||
@ -4,19 +4,18 @@ import { Key } from 'ts-key-enum';
|
|||||||
|
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
|
|
||||||
import { FiltersHotkeyScope } from '../types/FiltersHotkeyScope';
|
|
||||||
|
|
||||||
import { DropdownMenuContainer } from './DropdownMenuContainer';
|
import { DropdownMenuContainer } from './DropdownMenuContainer';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
label: string;
|
anchor?: 'left' | 'right';
|
||||||
|
label: ReactNode;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
isUnfolded?: boolean;
|
isUnfolded?: boolean;
|
||||||
icon?: ReactNode;
|
icon?: ReactNode;
|
||||||
onIsUnfoldedChange?: (newIsUnfolded: boolean) => void;
|
onIsUnfoldedChange?: (newIsUnfolded: boolean) => void;
|
||||||
resetState?: () => void;
|
resetState?: () => void;
|
||||||
HotkeyScope: FiltersHotkeyScope;
|
HotkeyScope: string;
|
||||||
color?: string;
|
color?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -59,7 +58,12 @@ const StyledDropdownButton = styled.div<StyledDropdownButtonProps>`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledDropdownMenuContainer = styled(DropdownMenuContainer)`
|
||||||
|
z-index: 2;
|
||||||
|
`;
|
||||||
|
|
||||||
function DropdownButton({
|
function DropdownButton({
|
||||||
|
anchor,
|
||||||
label,
|
label,
|
||||||
isActive,
|
isActive,
|
||||||
children,
|
children,
|
||||||
@ -99,9 +103,9 @@ function DropdownButton({
|
|||||||
{label}
|
{label}
|
||||||
</StyledDropdownButton>
|
</StyledDropdownButton>
|
||||||
{isUnfolded && (
|
{isUnfolded && (
|
||||||
<DropdownMenuContainer onClose={onOutsideClick}>
|
<StyledDropdownMenuContainer anchor={anchor} onClose={onOutsideClick}>
|
||||||
{children}
|
{children}
|
||||||
</DropdownMenuContainer>
|
</StyledDropdownMenuContainer>
|
||||||
)}
|
)}
|
||||||
</StyledDropdownButtonContainer>
|
</StyledDropdownButtonContainer>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,23 +1,32 @@
|
|||||||
import { useRef } from 'react';
|
import { type HTMLAttributes, useRef } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import { DropdownMenu } from '@/ui/dropdown/components/DropdownMenu';
|
||||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||||
|
|
||||||
import { DropdownMenu } from '../../dropdown/components/DropdownMenu';
|
export const StyledDropdownMenuContainer = styled.ul<{
|
||||||
|
anchor: 'left' | 'right';
|
||||||
export const StyledDropdownMenuContainer = styled.ul`
|
}>`
|
||||||
|
padding: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
${({ anchor }) => {
|
||||||
|
if (anchor === 'right') return 'right: 0';
|
||||||
|
}};
|
||||||
top: 14px;
|
top: 14px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export function DropdownMenuContainer({
|
type DropdownMenuContainerProps = {
|
||||||
children,
|
anchor?: 'left' | 'right';
|
||||||
onClose,
|
|
||||||
}: {
|
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
}) {
|
} & HTMLAttributes<HTMLUListElement>;
|
||||||
|
|
||||||
|
export function DropdownMenuContainer({
|
||||||
|
anchor = 'right',
|
||||||
|
children,
|
||||||
|
onClose,
|
||||||
|
...props
|
||||||
|
}: DropdownMenuContainerProps) {
|
||||||
const dropdownRef = useRef(null);
|
const dropdownRef = useRef(null);
|
||||||
|
|
||||||
useListenClickOutside({
|
useListenClickOutside({
|
||||||
@ -28,7 +37,7 @@ export function DropdownMenuContainer({
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledDropdownMenuContainer data-select-disable>
|
<StyledDropdownMenuContainer data-select-disable {...props} anchor={anchor}>
|
||||||
<DropdownMenu ref={dropdownRef}>{children}</DropdownMenu>
|
<DropdownMenu ref={dropdownRef}>{children}</DropdownMenu>
|
||||||
</StyledDropdownMenuContainer>
|
</StyledDropdownMenuContainer>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ChangeEvent, Context } from 'react';
|
import { ChangeEvent, Context } from 'react';
|
||||||
|
|
||||||
import { DropdownMenuSearch } from '@/ui/dropdown/components/DropdownMenuSearch';
|
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
||||||
import { filterDefinitionUsedInDropdownScopedState } from '@/ui/filter-n-sort/states/filterDefinitionUsedInDropdownScopedState';
|
import { filterDefinitionUsedInDropdownScopedState } from '@/ui/filter-n-sort/states/filterDefinitionUsedInDropdownScopedState';
|
||||||
import { filterDropdownSearchInputScopedState } from '@/ui/filter-n-sort/states/filterDropdownSearchInputScopedState';
|
import { filterDropdownSearchInputScopedState } from '@/ui/filter-n-sort/states/filterDropdownSearchInputScopedState';
|
||||||
import { selectedOperandInDropdownScopedState } from '@/ui/filter-n-sort/states/selectedOperandInDropdownScopedState';
|
import { selectedOperandInDropdownScopedState } from '@/ui/filter-n-sort/states/selectedOperandInDropdownScopedState';
|
||||||
@ -27,7 +27,7 @@ export function FilterDropdownEntitySearchInput({
|
|||||||
return (
|
return (
|
||||||
filterDefinitionUsedInDropdown &&
|
filterDefinitionUsedInDropdown &&
|
||||||
selectedOperandInDropdown && (
|
selectedOperandInDropdown && (
|
||||||
<DropdownMenuSearch
|
<DropdownMenuInput
|
||||||
type="text"
|
type="text"
|
||||||
value={filterDropdownSearchInput}
|
value={filterDropdownSearchInput}
|
||||||
placeholder={filterDefinitionUsedInDropdown.label}
|
placeholder={filterDefinitionUsedInDropdown.label}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ChangeEvent, Context } from 'react';
|
import { ChangeEvent, Context } from 'react';
|
||||||
|
|
||||||
import { DropdownMenuSearch } from '@/ui/dropdown/components/DropdownMenuSearch';
|
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
||||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
|
|
||||||
import { useRemoveFilter } from '../hooks/useRemoveFilter';
|
import { useRemoveFilter } from '../hooks/useRemoveFilter';
|
||||||
@ -29,7 +29,7 @@ export function FilterDropdownNumberSearchInput({
|
|||||||
return (
|
return (
|
||||||
filterDefinitionUsedInDropdown &&
|
filterDefinitionUsedInDropdown &&
|
||||||
selectedOperandInDropdown && (
|
selectedOperandInDropdown && (
|
||||||
<DropdownMenuSearch
|
<DropdownMenuInput
|
||||||
type="number"
|
type="number"
|
||||||
placeholder={filterDefinitionUsedInDropdown.label}
|
placeholder={filterDefinitionUsedInDropdown.label}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ChangeEvent, Context } from 'react';
|
import { ChangeEvent, Context } from 'react';
|
||||||
|
|
||||||
import { DropdownMenuSearch } from '@/ui/dropdown/components/DropdownMenuSearch';
|
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
||||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
|
|
||||||
import { useFilterCurrentlyEdited } from '../hooks/useFilterCurrentlyEdited';
|
import { useFilterCurrentlyEdited } from '../hooks/useFilterCurrentlyEdited';
|
||||||
@ -36,7 +36,7 @@ export function FilterDropdownTextSearchInput({
|
|||||||
return (
|
return (
|
||||||
filterDefinitionUsedInDropdown &&
|
filterDefinitionUsedInDropdown &&
|
||||||
selectedOperandInDropdown && (
|
selectedOperandInDropdown && (
|
||||||
<DropdownMenuSearch
|
<DropdownMenuInput
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={filterDefinitionUsedInDropdown.label}
|
placeholder={filterDefinitionUsedInDropdown.label}
|
||||||
value={filterCurrentlyEdited?.value ?? filterDropdownSearchInput}
|
value={filterCurrentlyEdited?.value ?? filterDropdownSearchInput}
|
||||||
|
|||||||
@ -1,58 +1,60 @@
|
|||||||
export { IconAddressBook } from './components/IconAddressBook';
|
export { IconAddressBook } from './components/IconAddressBook';
|
||||||
export { IconBuildingSkyscraper } from '@tabler/icons-react';
|
export {
|
||||||
export { IconMessageCircle as IconComment } from '@tabler/icons-react';
|
IconAlertCircle,
|
||||||
export { IconCheck } from '@tabler/icons-react';
|
IconAlertTriangle,
|
||||||
export { IconTrash } from '@tabler/icons-react';
|
IconArchive,
|
||||||
export { IconLayoutSidebarRightCollapse } from '@tabler/icons-react';
|
IconArrowNarrowDown,
|
||||||
export { IconLayoutSidebarLeftCollapse } from '@tabler/icons-react';
|
IconArrowNarrowUp,
|
||||||
export { IconUser } from '@tabler/icons-react';
|
IconArrowRight,
|
||||||
export { IconBell } from '@tabler/icons-react';
|
IconArrowUpRight,
|
||||||
export { IconList } from '@tabler/icons-react';
|
IconBell,
|
||||||
export { IconInbox } from '@tabler/icons-react';
|
IconBrandGithub,
|
||||||
export { IconSearch } from '@tabler/icons-react';
|
IconBrandGoogle,
|
||||||
export { IconArchive } from '@tabler/icons-react';
|
IconBrandLinkedin,
|
||||||
export { IconSettings } from '@tabler/icons-react';
|
IconBrandX,
|
||||||
export { IconLogout } from '@tabler/icons-react';
|
IconBriefcase,
|
||||||
export { IconColorSwatch } from '@tabler/icons-react';
|
IconBuildingSkyscraper,
|
||||||
export { IconProgressCheck } from '@tabler/icons-react';
|
IconCalendar,
|
||||||
export { IconX } from '@tabler/icons-react';
|
IconCalendarEvent,
|
||||||
export { IconChevronLeft } from '@tabler/icons-react';
|
IconCheck,
|
||||||
export { IconBriefcase } from '@tabler/icons-react';
|
IconCheckbox,
|
||||||
export { IconPlus } from '@tabler/icons-react';
|
IconChevronDown,
|
||||||
export { IconMinus } from '@tabler/icons-react';
|
IconChevronLeft,
|
||||||
export { IconLink } from '@tabler/icons-react';
|
IconChevronsRight,
|
||||||
export { IconBrandLinkedin } from '@tabler/icons-react';
|
IconCircleDot,
|
||||||
export { IconUsers } from '@tabler/icons-react';
|
IconCirclePlus,
|
||||||
export { IconCalendarEvent } from '@tabler/icons-react';
|
IconColorSwatch,
|
||||||
export { IconMap } from '@tabler/icons-react';
|
IconMessageCircle as IconComment,
|
||||||
export { IconMail } from '@tabler/icons-react';
|
IconCopy,
|
||||||
export { IconPhone } from '@tabler/icons-react';
|
IconCurrencyDollar,
|
||||||
export { IconTargetArrow } from '@tabler/icons-react';
|
IconEye,
|
||||||
export { IconChevronDown } from '@tabler/icons-react';
|
IconEyeOff,
|
||||||
export { IconArrowNarrowDown } from '@tabler/icons-react';
|
IconFileUpload,
|
||||||
export { IconArrowNarrowUp } from '@tabler/icons-react';
|
IconHeart,
|
||||||
export { IconArrowRight } from '@tabler/icons-react';
|
IconHelpCircle,
|
||||||
export { IconArrowUpRight } from '@tabler/icons-react';
|
IconInbox,
|
||||||
export { IconBrandGoogle } from '@tabler/icons-react';
|
IconLayoutSidebarLeftCollapse,
|
||||||
export { IconUpload } from '@tabler/icons-react';
|
IconLayoutSidebarRightCollapse,
|
||||||
export { IconFileUpload } from '@tabler/icons-react';
|
IconLink,
|
||||||
export { IconChevronsRight } from '@tabler/icons-react';
|
IconList,
|
||||||
export { IconNotes } from '@tabler/icons-react';
|
IconLogout,
|
||||||
export { IconCirclePlus } from '@tabler/icons-react';
|
IconMail,
|
||||||
export { IconCheckbox } from '@tabler/icons-react';
|
IconMap,
|
||||||
export { IconTimelineEvent } from '@tabler/icons-react';
|
IconMinus,
|
||||||
export { IconAlertCircle } from '@tabler/icons-react';
|
IconNotes,
|
||||||
export { IconEye } from '@tabler/icons-react';
|
IconPencil,
|
||||||
export { IconEyeOff } from '@tabler/icons-react';
|
IconPhone,
|
||||||
export { IconAlertTriangle } from '@tabler/icons-react';
|
IconPlus,
|
||||||
export { IconCopy } from '@tabler/icons-react';
|
IconProgressCheck,
|
||||||
export { IconCurrencyDollar } from '@tabler/icons-react';
|
IconSearch,
|
||||||
export { IconUserCircle } from '@tabler/icons-react';
|
IconSettings,
|
||||||
export { IconCalendar } from '@tabler/icons-react';
|
IconTag,
|
||||||
export { IconPencil } from '@tabler/icons-react';
|
IconTargetArrow,
|
||||||
export { IconCircleDot } from '@tabler/icons-react';
|
IconTimelineEvent,
|
||||||
export { IconHeart } from '@tabler/icons-react';
|
IconTrash,
|
||||||
export { IconBrandX } from '@tabler/icons-react';
|
IconUpload,
|
||||||
export { IconTag } from '@tabler/icons-react';
|
IconUser,
|
||||||
export { IconHelpCircle } from '@tabler/icons-react';
|
IconUserCircle,
|
||||||
export { IconBrandGithub } from '@tabler/icons-react';
|
IconUsers,
|
||||||
|
IconX,
|
||||||
|
} from '@tabler/icons-react';
|
||||||
|
|||||||
@ -3,9 +3,9 @@ import debounce from 'lodash.debounce';
|
|||||||
|
|
||||||
import { DropdownMenu } from '@/ui/dropdown/components/DropdownMenu';
|
import { DropdownMenu } from '@/ui/dropdown/components/DropdownMenu';
|
||||||
import { DropdownMenuCheckableItem } from '@/ui/dropdown/components/DropdownMenuCheckableItem';
|
import { DropdownMenuCheckableItem } from '@/ui/dropdown/components/DropdownMenuCheckableItem';
|
||||||
|
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
||||||
import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem';
|
import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem';
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { DropdownMenuSearch } from '@/ui/dropdown/components/DropdownMenuSearch';
|
|
||||||
import { DropdownMenuSeparator } from '@/ui/dropdown/components/DropdownMenuSeparator';
|
import { DropdownMenuSeparator } from '@/ui/dropdown/components/DropdownMenuSeparator';
|
||||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||||
import { Avatar } from '@/users/components/Avatar';
|
import { Avatar } from '@/users/components/Avatar';
|
||||||
@ -73,7 +73,7 @@ export function MultipleEntitySelect<
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu ref={containerRef}>
|
<DropdownMenu ref={containerRef}>
|
||||||
<DropdownMenuSearch
|
<DropdownMenuInput
|
||||||
value={searchFilter}
|
value={searchFilter}
|
||||||
onChange={handleFilterChange}
|
onChange={handleFilterChange}
|
||||||
autoFocus
|
autoFocus
|
||||||
|
|||||||
@ -2,9 +2,9 @@ import { useRef } from 'react';
|
|||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
|
|
||||||
import { DropdownMenu } from '@/ui/dropdown/components/DropdownMenu';
|
import { DropdownMenu } from '@/ui/dropdown/components/DropdownMenu';
|
||||||
|
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
||||||
import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem';
|
import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem';
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { DropdownMenuSearch } from '@/ui/dropdown/components/DropdownMenuSearch';
|
|
||||||
import { DropdownMenuSeparator } from '@/ui/dropdown/components/DropdownMenuSeparator';
|
import { DropdownMenuSeparator } from '@/ui/dropdown/components/DropdownMenuSeparator';
|
||||||
import { IconPlus } from '@/ui/icon';
|
import { IconPlus } from '@/ui/icon';
|
||||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||||
@ -65,7 +65,7 @@ export function SingleEntitySelect<
|
|||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
width={width}
|
width={width}
|
||||||
>
|
>
|
||||||
<DropdownMenuSearch
|
<DropdownMenuInput
|
||||||
value={searchFilter}
|
value={searchFilter}
|
||||||
onChange={handleSearchFilterChange}
|
onChange={handleSearchFilterChange}
|
||||||
autoFocus
|
autoFocus
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import { useLeaveTableFocus } from '../hooks/useLeaveTableFocus';
|
|||||||
import { useMapKeyboardToSoftFocus } from '../hooks/useMapKeyboardToSoftFocus';
|
import { useMapKeyboardToSoftFocus } from '../hooks/useMapKeyboardToSoftFocus';
|
||||||
import { useResetTableRowSelection } from '../hooks/useResetTableRowSelection';
|
import { useResetTableRowSelection } from '../hooks/useResetTableRowSelection';
|
||||||
import { useSetRowSelectedState } from '../hooks/useSetRowSelectedState';
|
import { useSetRowSelectedState } from '../hooks/useSetRowSelectedState';
|
||||||
|
import type { TableView } from '../states/tableViewsState';
|
||||||
import { TableHeader } from '../table-header/components/TableHeader';
|
import { TableHeader } from '../table-header/components/TableHeader';
|
||||||
|
|
||||||
import { EntityTableBody } from './EntityTableBody';
|
import { EntityTableBody } from './EntityTableBody';
|
||||||
@ -97,16 +98,16 @@ type OwnProps<SortField> = {
|
|||||||
availableSorts?: Array<SortType<SortField>>;
|
availableSorts?: Array<SortType<SortField>>;
|
||||||
onColumnsChange?: (columns: ViewFieldDefinition<ViewFieldMetadata>[]) => void;
|
onColumnsChange?: (columns: ViewFieldDefinition<ViewFieldMetadata>[]) => void;
|
||||||
onSortsUpdate?: (sorts: Array<SelectedSortType<SortField>>) => void;
|
onSortsUpdate?: (sorts: Array<SelectedSortType<SortField>>) => void;
|
||||||
onRowSelectionChange?: (rowSelection: string[]) => void;
|
onViewsChange?: (views: TableView[]) => void;
|
||||||
updateEntityMutation: any;
|
updateEntityMutation: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function EntityTable<SortField>({
|
export function EntityTable<SortField>({
|
||||||
viewName,
|
viewName,
|
||||||
viewIcon,
|
|
||||||
availableSorts,
|
availableSorts,
|
||||||
onColumnsChange,
|
onColumnsChange,
|
||||||
onSortsUpdate,
|
onSortsUpdate,
|
||||||
|
onViewsChange,
|
||||||
updateEntityMutation,
|
updateEntityMutation,
|
||||||
}: OwnProps<SortField>) {
|
}: OwnProps<SortField>) {
|
||||||
const tableBodyRef = useRef<HTMLDivElement>(null);
|
const tableBodyRef = useRef<HTMLDivElement>(null);
|
||||||
@ -131,10 +132,10 @@ export function EntityTable<SortField>({
|
|||||||
<StyledTableContainer ref={tableBodyRef}>
|
<StyledTableContainer ref={tableBodyRef}>
|
||||||
<TableHeader
|
<TableHeader
|
||||||
viewName={viewName}
|
viewName={viewName}
|
||||||
viewIcon={viewIcon}
|
|
||||||
availableSorts={availableSorts}
|
availableSorts={availableSorts}
|
||||||
onColumnsChange={onColumnsChange}
|
onColumnsChange={onColumnsChange}
|
||||||
onSortsUpdate={onSortsUpdate}
|
onSortsUpdate={onSortsUpdate}
|
||||||
|
onViewsChange={onViewsChange}
|
||||||
/>
|
/>
|
||||||
<StyledTableWrapper>
|
<StyledTableWrapper>
|
||||||
<StyledTable>
|
<StyledTable>
|
||||||
|
|||||||
@ -1,30 +1,50 @@
|
|||||||
import { useCallback, useState } from 'react';
|
import {
|
||||||
|
type FormEvent,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { IconButton } from '@/ui/button/components/IconButton';
|
import { IconButton } from '@/ui/button/components/IconButton';
|
||||||
import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader';
|
import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader';
|
||||||
|
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
||||||
import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem';
|
import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem';
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { DropdownMenuSeparator } from '@/ui/dropdown/components/DropdownMenuSeparator';
|
import { DropdownMenuSeparator } from '@/ui/dropdown/components/DropdownMenuSeparator';
|
||||||
import {
|
import type {
|
||||||
ViewFieldDefinition,
|
ViewFieldDefinition,
|
||||||
ViewFieldMetadata,
|
ViewFieldMetadata,
|
||||||
} from '@/ui/editable-field/types/ViewField';
|
} from '@/ui/editable-field/types/ViewField';
|
||||||
import DropdownButton from '@/ui/filter-n-sort/components/DropdownButton';
|
import DropdownButton from '@/ui/filter-n-sort/components/DropdownButton';
|
||||||
import { FiltersHotkeyScope } from '@/ui/filter-n-sort/types/FiltersHotkeyScope';
|
|
||||||
import { IconChevronLeft, IconMinus, IconPlus, IconTag } from '@/ui/icon';
|
import { IconChevronLeft, IconMinus, IconPlus, IconTag } from '@/ui/icon';
|
||||||
import {
|
import {
|
||||||
hiddenTableColumnsState,
|
hiddenTableColumnsState,
|
||||||
tableColumnsState,
|
tableColumnsState,
|
||||||
visibleTableColumnsState,
|
visibleTableColumnsState,
|
||||||
} from '@/ui/table/states/tableColumnsState';
|
} from '@/ui/table/states/tableColumnsState';
|
||||||
|
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||||
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
|
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
|
|
||||||
|
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
|
||||||
|
import {
|
||||||
|
type TableView,
|
||||||
|
tableViewEditModeState,
|
||||||
|
tableViewsByIdState,
|
||||||
|
tableViewsState,
|
||||||
|
} from '../../states/tableViewsState';
|
||||||
|
import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope';
|
||||||
|
|
||||||
import { TableOptionsDropdownSection } from './TableOptionsDropdownSection';
|
import { TableOptionsDropdownSection } from './TableOptionsDropdownSection';
|
||||||
|
|
||||||
type TableOptionsDropdownButtonProps = {
|
type TableOptionsDropdownButtonProps = {
|
||||||
onColumnsChange?: (columns: ViewFieldDefinition<ViewFieldMetadata>[]) => void;
|
onColumnsChange?: (columns: ViewFieldDefinition<ViewFieldMetadata>[]) => void;
|
||||||
HotkeyScope: FiltersHotkeyScope;
|
onViewsChange?: (views: TableView[]) => void;
|
||||||
|
HotkeyScope: TableOptionsHotkeyScope;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Option {
|
enum Option {
|
||||||
@ -33,17 +53,37 @@ enum Option {
|
|||||||
|
|
||||||
export const TableOptionsDropdownButton = ({
|
export const TableOptionsDropdownButton = ({
|
||||||
onColumnsChange,
|
onColumnsChange,
|
||||||
|
onViewsChange,
|
||||||
HotkeyScope,
|
HotkeyScope,
|
||||||
}: TableOptionsDropdownButtonProps) => {
|
}: TableOptionsDropdownButtonProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const [isUnfolded, setIsUnfolded] = useState(false);
|
const [isUnfolded, setIsUnfolded] = useState(false);
|
||||||
const [selectedOption, setSelectedOption] = useState<Option | undefined>(
|
const [selectedOption, setSelectedOption] = useState<Option | undefined>(
|
||||||
undefined,
|
undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const viewEditInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const [columns, setColumns] = useRecoilState(tableColumnsState);
|
const [columns, setColumns] = useRecoilState(tableColumnsState);
|
||||||
|
const [viewEditMode, setViewEditMode] = useRecoilState(
|
||||||
|
tableViewEditModeState,
|
||||||
|
);
|
||||||
|
const [views, setViews] = useRecoilScopedState(
|
||||||
|
tableViewsState,
|
||||||
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
const visibleColumns = useRecoilValue(visibleTableColumnsState);
|
const visibleColumns = useRecoilValue(visibleTableColumnsState);
|
||||||
const hiddenColumns = useRecoilValue(hiddenTableColumnsState);
|
const hiddenColumns = useRecoilValue(hiddenTableColumnsState);
|
||||||
|
const viewsById = useRecoilScopedValue(
|
||||||
|
tableViewsByIdState,
|
||||||
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
|
|
||||||
|
const {
|
||||||
|
goBackToPreviousHotkeyScope,
|
||||||
|
setHotkeyScopeAndMemorizePreviousScope,
|
||||||
|
} = usePreviousHotkeyScope();
|
||||||
|
|
||||||
const handleColumnVisibilityChange = useCallback(
|
const handleColumnVisibilityChange = useCallback(
|
||||||
(columnId: string, nextIsVisible: boolean) => {
|
(columnId: string, nextIsVisible: boolean) => {
|
||||||
@ -79,25 +119,109 @@ export const TableOptionsDropdownButton = ({
|
|||||||
[handleColumnVisibilityChange, theme.icon.size.sm, visibleColumns.length],
|
[handleColumnVisibilityChange, theme.icon.size.sm, visibleColumns.length],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const resetViewEditMode = useCallback(() => {
|
||||||
|
setViewEditMode({ mode: undefined, viewId: undefined });
|
||||||
|
|
||||||
|
if (viewEditInputRef.current) {
|
||||||
|
viewEditInputRef.current.value = '';
|
||||||
|
}
|
||||||
|
}, [setViewEditMode]);
|
||||||
|
|
||||||
|
const handleViewNameSubmit = useCallback(
|
||||||
|
(event?: FormEvent) => {
|
||||||
|
event?.preventDefault();
|
||||||
|
|
||||||
|
if (viewEditMode.mode && viewEditInputRef.current?.value) {
|
||||||
|
const name = viewEditInputRef.current.value;
|
||||||
|
const nextViews =
|
||||||
|
viewEditMode.mode === 'create'
|
||||||
|
? [...views, { id: v4(), name }]
|
||||||
|
: views.map((view) =>
|
||||||
|
view.id === viewEditMode.viewId ? { ...view, name } : view,
|
||||||
|
);
|
||||||
|
|
||||||
|
(onViewsChange ?? setViews)(nextViews);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetViewEditMode();
|
||||||
|
},
|
||||||
|
[
|
||||||
|
onViewsChange,
|
||||||
|
resetViewEditMode,
|
||||||
|
setViews,
|
||||||
|
viewEditMode.mode,
|
||||||
|
viewEditMode.viewId,
|
||||||
|
views,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSelectOption = useCallback(
|
||||||
|
(option: Option) => {
|
||||||
|
handleViewNameSubmit();
|
||||||
|
setIsUnfolded(true);
|
||||||
|
setSelectedOption(option);
|
||||||
|
},
|
||||||
|
[handleViewNameSubmit],
|
||||||
|
);
|
||||||
|
|
||||||
const resetSelectedOption = useCallback(() => {
|
const resetSelectedOption = useCallback(() => {
|
||||||
setSelectedOption(undefined);
|
setSelectedOption(undefined);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const handleUnfoldedChange = useCallback(
|
||||||
|
(nextIsUnfolded: boolean) => {
|
||||||
|
setIsUnfolded(nextIsUnfolded);
|
||||||
|
|
||||||
|
if (!nextIsUnfolded) {
|
||||||
|
handleViewNameSubmit();
|
||||||
|
resetSelectedOption();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[handleViewNameSubmit, resetSelectedOption],
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
isUnfolded || viewEditMode.mode
|
||||||
|
? setHotkeyScopeAndMemorizePreviousScope(HotkeyScope)
|
||||||
|
: goBackToPreviousHotkeyScope();
|
||||||
|
}, [
|
||||||
|
HotkeyScope,
|
||||||
|
goBackToPreviousHotkeyScope,
|
||||||
|
isUnfolded,
|
||||||
|
setHotkeyScopeAndMemorizePreviousScope,
|
||||||
|
viewEditMode.mode,
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
label="Options"
|
label="Options"
|
||||||
isActive={false}
|
isActive={false}
|
||||||
isUnfolded={isUnfolded}
|
isUnfolded={isUnfolded || !!viewEditMode.mode}
|
||||||
onIsUnfoldedChange={setIsUnfolded}
|
onIsUnfoldedChange={handleUnfoldedChange}
|
||||||
HotkeyScope={HotkeyScope}
|
HotkeyScope={HotkeyScope}
|
||||||
>
|
>
|
||||||
{!selectedOption && (
|
{!selectedOption && (
|
||||||
<>
|
<>
|
||||||
<DropdownMenuHeader>View settings</DropdownMenuHeader>
|
{!!viewEditMode.mode ? (
|
||||||
|
<DropdownMenuInput
|
||||||
|
ref={viewEditInputRef}
|
||||||
|
autoFocus
|
||||||
|
placeholder={
|
||||||
|
viewEditMode.mode === 'create' ? 'New view' : 'View name'
|
||||||
|
}
|
||||||
|
defaultValue={
|
||||||
|
viewEditMode.viewId
|
||||||
|
? viewsById[viewEditMode.viewId]?.name
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<DropdownMenuHeader>View settings</DropdownMenuHeader>
|
||||||
|
)}
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuItemsContainer>
|
<DropdownMenuItemsContainer>
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={() => setSelectedOption(Option.Properties)}
|
onClick={() => handleSelectOption(Option.Properties)}
|
||||||
>
|
>
|
||||||
<IconTag size={theme.icon.size.md} />
|
<IconTag size={theme.icon.size.md} />
|
||||||
Properties
|
Properties
|
||||||
|
|||||||
@ -0,0 +1,149 @@
|
|||||||
|
import { type MouseEvent, useCallback, useEffect, useState } from 'react';
|
||||||
|
import { useTheme } from '@emotion/react';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
|
import { useSetRecoilState } from 'recoil';
|
||||||
|
|
||||||
|
import { IconButton } from '@/ui/button/components/IconButton';
|
||||||
|
import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem';
|
||||||
|
import { DropdownMenuItemsContainer } from '@/ui/dropdown/components/DropdownMenuItemsContainer';
|
||||||
|
import { DropdownMenuSeparator } from '@/ui/dropdown/components/DropdownMenuSeparator';
|
||||||
|
import DropdownButton from '@/ui/filter-n-sort/components/DropdownButton';
|
||||||
|
import { IconChevronDown, IconList, IconPencil, IconPlus } from '@/ui/icon';
|
||||||
|
import {
|
||||||
|
currentTableViewIdState,
|
||||||
|
currentTableViewState,
|
||||||
|
tableViewEditModeState,
|
||||||
|
tableViewsState,
|
||||||
|
} from '@/ui/table/states/tableViewsState';
|
||||||
|
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||||
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
|
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
|
|
||||||
|
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
|
||||||
|
import { TableViewsHotkeyScope } from '../../types/TableViewsHotkeyScope';
|
||||||
|
|
||||||
|
const StyledDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)`
|
||||||
|
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledDropdownLabelAdornments = styled.span`
|
||||||
|
align-items: center;
|
||||||
|
color: ${({ theme }) => theme.grayScale.gray35};
|
||||||
|
display: inline-flex;
|
||||||
|
gap: ${({ theme }) => theme.spacing(1)};
|
||||||
|
margin-left: ${({ theme }) => theme.spacing(1)};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledViewIcon = styled(IconList)`
|
||||||
|
margin-right: ${({ theme }) => theme.spacing(1)};
|
||||||
|
`;
|
||||||
|
|
||||||
|
type TableViewsDropdownButtonProps = {
|
||||||
|
defaultViewName: string;
|
||||||
|
HotkeyScope: TableViewsHotkeyScope;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TableViewsDropdownButton = ({
|
||||||
|
defaultViewName,
|
||||||
|
HotkeyScope,
|
||||||
|
}: TableViewsDropdownButtonProps) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const [isUnfolded, setIsUnfolded] = useState(false);
|
||||||
|
|
||||||
|
const currentView = useRecoilScopedValue(
|
||||||
|
currentTableViewState,
|
||||||
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
|
const views = useRecoilScopedValue(tableViewsState, TableRecoilScopeContext);
|
||||||
|
const [, setCurrentViewId] = useRecoilScopedState(
|
||||||
|
currentTableViewIdState,
|
||||||
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
|
const setViewEditMode = useSetRecoilState(tableViewEditModeState);
|
||||||
|
|
||||||
|
const {
|
||||||
|
goBackToPreviousHotkeyScope,
|
||||||
|
setHotkeyScopeAndMemorizePreviousScope,
|
||||||
|
} = usePreviousHotkeyScope();
|
||||||
|
|
||||||
|
const handleViewSelect = useCallback(
|
||||||
|
(viewId?: string) => {
|
||||||
|
setCurrentViewId(viewId);
|
||||||
|
setIsUnfolded(false);
|
||||||
|
},
|
||||||
|
[setCurrentViewId],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleAddViewButtonClick = useCallback(() => {
|
||||||
|
setViewEditMode({ mode: 'create', viewId: undefined });
|
||||||
|
setIsUnfolded(false);
|
||||||
|
}, [setViewEditMode]);
|
||||||
|
|
||||||
|
const handleEditViewButtonClick = useCallback(
|
||||||
|
(event: MouseEvent<HTMLButtonElement>, viewId: string) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
setViewEditMode({ mode: 'edit', viewId });
|
||||||
|
setIsUnfolded(false);
|
||||||
|
},
|
||||||
|
[setViewEditMode],
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
isUnfolded
|
||||||
|
? setHotkeyScopeAndMemorizePreviousScope(HotkeyScope)
|
||||||
|
: goBackToPreviousHotkeyScope();
|
||||||
|
}, [
|
||||||
|
HotkeyScope,
|
||||||
|
goBackToPreviousHotkeyScope,
|
||||||
|
isUnfolded,
|
||||||
|
setHotkeyScopeAndMemorizePreviousScope,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DropdownButton
|
||||||
|
label={
|
||||||
|
<>
|
||||||
|
<StyledViewIcon size={theme.icon.size.md} />
|
||||||
|
{currentView?.name || defaultViewName}{' '}
|
||||||
|
<StyledDropdownLabelAdornments>
|
||||||
|
· {views.length + 1} <IconChevronDown size={theme.icon.size.sm} />
|
||||||
|
</StyledDropdownLabelAdornments>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
isActive={false}
|
||||||
|
isUnfolded={isUnfolded}
|
||||||
|
onIsUnfoldedChange={setIsUnfolded}
|
||||||
|
anchor="left"
|
||||||
|
HotkeyScope={HotkeyScope}
|
||||||
|
>
|
||||||
|
<StyledDropdownMenuItemsContainer>
|
||||||
|
<DropdownMenuItem onClick={() => handleViewSelect(undefined)}>
|
||||||
|
<IconList size={theme.icon.size.md} />
|
||||||
|
{defaultViewName}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
{views.map((view) => (
|
||||||
|
<DropdownMenuItem
|
||||||
|
key={view.id}
|
||||||
|
actions={
|
||||||
|
<IconButton
|
||||||
|
onClick={(event) => handleEditViewButtonClick(event, view.id)}
|
||||||
|
icon={<IconPencil size={theme.icon.size.sm} />}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
onClick={() => handleViewSelect(view.id)}
|
||||||
|
>
|
||||||
|
<IconList size={theme.icon.size.md} />
|
||||||
|
{view.name}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
))}
|
||||||
|
</StyledDropdownMenuItemsContainer>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<StyledDropdownMenuItemsContainer>
|
||||||
|
<DropdownMenuItem onClick={handleAddViewButtonClick}>
|
||||||
|
<IconPlus size={theme.icon.size.md} />
|
||||||
|
Add view
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</StyledDropdownMenuItemsContainer>
|
||||||
|
</DropdownButton>
|
||||||
|
);
|
||||||
|
};
|
||||||
50
front/src/modules/ui/table/states/tableViewsState.ts
Normal file
50
front/src/modules/ui/table/states/tableViewsState.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { atom, atomFamily, selectorFamily } from 'recoil';
|
||||||
|
|
||||||
|
export type TableView = { id: string; name: string };
|
||||||
|
|
||||||
|
export const tableViewsState = atomFamily<TableView[], string>({
|
||||||
|
key: 'tableViewsState',
|
||||||
|
default: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const tableViewsByIdState = selectorFamily<
|
||||||
|
Record<string, TableView>,
|
||||||
|
string
|
||||||
|
>({
|
||||||
|
key: 'tableViewsByIdState',
|
||||||
|
get:
|
||||||
|
(scopeId) =>
|
||||||
|
({ get }) =>
|
||||||
|
get(tableViewsState(scopeId)).reduce<Record<string, TableView>>(
|
||||||
|
(result, view) => ({ ...result, [view.id]: view }),
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const currentTableViewIdState = atomFamily<string | undefined, string>({
|
||||||
|
key: 'currentTableViewIdState',
|
||||||
|
default: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const currentTableViewState = selectorFamily<
|
||||||
|
TableView | undefined,
|
||||||
|
string
|
||||||
|
>({
|
||||||
|
key: 'currentTableViewState',
|
||||||
|
get:
|
||||||
|
(scopeId) =>
|
||||||
|
({ get }) => {
|
||||||
|
const currentViewId = get(currentTableViewIdState(scopeId));
|
||||||
|
return currentViewId
|
||||||
|
? get(tableViewsByIdState(scopeId))[currentViewId]
|
||||||
|
: undefined;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const tableViewEditModeState = atom<{
|
||||||
|
mode: 'create' | 'edit' | undefined;
|
||||||
|
viewId: string | undefined;
|
||||||
|
}>({
|
||||||
|
key: 'tableViewEditModeState',
|
||||||
|
default: { mode: undefined, viewId: undefined },
|
||||||
|
});
|
||||||
@ -1,5 +1,4 @@
|
|||||||
import { ReactNode, useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import styled from '@emotion/styled';
|
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ViewFieldDefinition,
|
ViewFieldDefinition,
|
||||||
@ -15,32 +14,26 @@ import { TableOptionsDropdownButton } from '@/ui/table/options/components/TableO
|
|||||||
import { TopBar } from '@/ui/top-bar/TopBar';
|
import { TopBar } from '@/ui/top-bar/TopBar';
|
||||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
|
|
||||||
|
import { TableViewsDropdownButton } from '../../options/components/TableViewsDropdownButton';
|
||||||
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
|
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
|
||||||
|
import type { TableView } from '../../states/tableViewsState';
|
||||||
|
import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope';
|
||||||
|
import { TableViewsHotkeyScope } from '../../types/TableViewsHotkeyScope';
|
||||||
|
|
||||||
type OwnProps<SortField> = {
|
type OwnProps<SortField> = {
|
||||||
viewName: string;
|
viewName: string;
|
||||||
viewIcon?: ReactNode;
|
|
||||||
availableSorts?: Array<SortType<SortField>>;
|
availableSorts?: Array<SortType<SortField>>;
|
||||||
onColumnsChange?: (columns: ViewFieldDefinition<ViewFieldMetadata>[]) => void;
|
onColumnsChange?: (columns: ViewFieldDefinition<ViewFieldMetadata>[]) => void;
|
||||||
onSortsUpdate?: (sorts: Array<SelectedSortType<SortField>>) => void;
|
onSortsUpdate?: (sorts: Array<SelectedSortType<SortField>>) => void;
|
||||||
|
onViewsChange?: (views: TableView[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledIcon = styled.div`
|
|
||||||
display: flex;
|
|
||||||
margin-left: ${({ theme }) => theme.spacing(1)};
|
|
||||||
margin-right: ${({ theme }) => theme.spacing(2)};
|
|
||||||
|
|
||||||
& > svg {
|
|
||||||
font-size: ${({ theme }) => theme.icon.size.sm};
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export function TableHeader<SortField>({
|
export function TableHeader<SortField>({
|
||||||
viewName,
|
viewName,
|
||||||
viewIcon,
|
|
||||||
availableSorts,
|
availableSorts,
|
||||||
onColumnsChange,
|
onColumnsChange,
|
||||||
onSortsUpdate,
|
onSortsUpdate,
|
||||||
|
onViewsChange,
|
||||||
}: OwnProps<SortField>) {
|
}: OwnProps<SortField>) {
|
||||||
const [sorts, setSorts] = useRecoilScopedState<SelectedSortType<SortField>[]>(
|
const [sorts, setSorts] = useRecoilScopedState<SelectedSortType<SortField>[]>(
|
||||||
sortScopedState,
|
sortScopedState,
|
||||||
@ -67,10 +60,10 @@ export function TableHeader<SortField>({
|
|||||||
return (
|
return (
|
||||||
<TopBar
|
<TopBar
|
||||||
leftComponent={
|
leftComponent={
|
||||||
<>
|
<TableViewsDropdownButton
|
||||||
<StyledIcon>{viewIcon}</StyledIcon>
|
defaultViewName={viewName}
|
||||||
{viewName}
|
HotkeyScope={TableViewsHotkeyScope.Dropdown}
|
||||||
</>
|
/>
|
||||||
}
|
}
|
||||||
displayBottomBorder={false}
|
displayBottomBorder={false}
|
||||||
rightComponent={
|
rightComponent={
|
||||||
@ -90,7 +83,8 @@ export function TableHeader<SortField>({
|
|||||||
/>
|
/>
|
||||||
<TableOptionsDropdownButton
|
<TableOptionsDropdownButton
|
||||||
onColumnsChange={onColumnsChange}
|
onColumnsChange={onColumnsChange}
|
||||||
HotkeyScope={FiltersHotkeyScope.FilterDropdownButton}
|
onViewsChange={onViewsChange}
|
||||||
|
HotkeyScope={TableOptionsHotkeyScope.Dropdown}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
export enum TableOptionsHotkeyScope {
|
||||||
|
Dropdown = 'table-options-dropdown',
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
export enum TableViewsHotkeyScope {
|
||||||
|
Dropdown = 'table-views-dropdown',
|
||||||
|
}
|
||||||
@ -4,13 +4,15 @@ import { v4 } from 'uuid';
|
|||||||
import { RecoilScopeContext } from '../states/RecoilScopeContext';
|
import { RecoilScopeContext } from '../states/RecoilScopeContext';
|
||||||
|
|
||||||
export function RecoilScope({
|
export function RecoilScope({
|
||||||
SpecificContext,
|
|
||||||
children,
|
children,
|
||||||
|
scopeId,
|
||||||
|
SpecificContext,
|
||||||
}: {
|
}: {
|
||||||
SpecificContext?: Context<string | null>;
|
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
scopeId?: string;
|
||||||
|
SpecificContext?: Context<string | null>;
|
||||||
}) {
|
}) {
|
||||||
const currentScopeId = useRef(v4());
|
const currentScopeId = useRef(scopeId || v4());
|
||||||
|
|
||||||
return SpecificContext ? (
|
return SpecificContext ? (
|
||||||
<SpecificContext.Provider value={currentScopeId.current}>
|
<SpecificContext.Provider value={currentScopeId.current}>
|
||||||
|
|||||||
9
front/src/modules/views/graphql/mutations/createViews.ts
Normal file
9
front/src/modules/views/graphql/mutations/createViews.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
|
export const CREATE_VIEWS = gql`
|
||||||
|
mutation CreateViews($data: [ViewCreateManyInput!]!) {
|
||||||
|
createManyView(data: $data) {
|
||||||
|
count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
10
front/src/modules/views/graphql/mutations/updateView.ts
Normal file
10
front/src/modules/views/graphql/mutations/updateView.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
|
export const UPDATE_VIEW = gql`
|
||||||
|
mutation UpdateView($data: ViewUpdateInput!, $where: ViewWhereUniqueInput!) {
|
||||||
|
updateOneView(data: $data, where: $where) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
10
front/src/modules/views/graphql/queries/getViews.ts
Normal file
10
front/src/modules/views/graphql/queries/getViews.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { gql } from '@apollo/client';
|
||||||
|
|
||||||
|
export const GET_VIEWS = gql`
|
||||||
|
query GetViews($where: ViewWhereInput) {
|
||||||
|
views: findManyView(where: $where) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
@ -7,11 +7,13 @@ import {
|
|||||||
ViewFieldMetadata,
|
ViewFieldMetadata,
|
||||||
ViewFieldTextMetadata,
|
ViewFieldTextMetadata,
|
||||||
} from '@/ui/editable-field/types/ViewField';
|
} from '@/ui/editable-field/types/ViewField';
|
||||||
|
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
|
||||||
import {
|
import {
|
||||||
tableColumnsByIdState,
|
tableColumnsByIdState,
|
||||||
tableColumnsState,
|
tableColumnsState,
|
||||||
} from '@/ui/table/states/tableColumnsState';
|
} from '@/ui/table/states/tableColumnsState';
|
||||||
import { currentViewIdState } from '@/views/states/currentViewIdState';
|
import { currentTableViewIdState } from '@/ui/table/states/tableViewsState';
|
||||||
|
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
import {
|
import {
|
||||||
SortOrder,
|
SortOrder,
|
||||||
useCreateViewFieldsMutation,
|
useCreateViewFieldsMutation,
|
||||||
@ -45,7 +47,10 @@ export const useTableViewFields = ({
|
|||||||
objectName: 'company' | 'person';
|
objectName: 'company' | 'person';
|
||||||
viewFieldDefinitions: ViewFieldDefinition<ViewFieldMetadata>[];
|
viewFieldDefinitions: ViewFieldDefinition<ViewFieldMetadata>[];
|
||||||
}) => {
|
}) => {
|
||||||
const currentViewId = useRecoilValue(currentViewIdState);
|
const currentViewId = useRecoilScopedValue(
|
||||||
|
currentTableViewIdState,
|
||||||
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
const setColumns = useSetRecoilState(tableColumnsState);
|
const setColumns = useSetRecoilState(tableColumnsState);
|
||||||
const columnsById = useRecoilValue(tableColumnsByIdState);
|
const columnsById = useRecoilValue(tableColumnsByIdState);
|
||||||
|
|
||||||
|
|||||||
109
front/src/modules/views/hooks/useTableViews.ts
Normal file
109
front/src/modules/views/hooks/useTableViews.ts
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import { useCallback } from 'react';
|
||||||
|
import { getOperationName } from '@apollo/client/utilities';
|
||||||
|
|
||||||
|
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
|
||||||
|
import {
|
||||||
|
type TableView,
|
||||||
|
tableViewsByIdState,
|
||||||
|
tableViewsState,
|
||||||
|
} from '@/ui/table/states/tableViewsState';
|
||||||
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
|
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
|
import {
|
||||||
|
useCreateViewsMutation,
|
||||||
|
useGetViewsQuery,
|
||||||
|
useUpdateViewMutation,
|
||||||
|
ViewType,
|
||||||
|
} from '~/generated/graphql';
|
||||||
|
|
||||||
|
import { GET_VIEWS } from '../graphql/queries/getViews';
|
||||||
|
|
||||||
|
export const useTableViews = ({
|
||||||
|
objectId,
|
||||||
|
}: {
|
||||||
|
objectId: 'company' | 'person';
|
||||||
|
}) => {
|
||||||
|
const [, setViews] = useRecoilScopedState(
|
||||||
|
tableViewsState,
|
||||||
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
|
const viewsById = useRecoilScopedValue(
|
||||||
|
tableViewsByIdState,
|
||||||
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
|
|
||||||
|
const [createViewsMutation] = useCreateViewsMutation();
|
||||||
|
const [updateViewMutation] = useUpdateViewMutation();
|
||||||
|
|
||||||
|
const createViews = useCallback(
|
||||||
|
(views: TableView[]) => {
|
||||||
|
if (!views.length) return;
|
||||||
|
|
||||||
|
return createViewsMutation({
|
||||||
|
variables: {
|
||||||
|
data: views.map((view) => ({
|
||||||
|
...view,
|
||||||
|
objectId,
|
||||||
|
type: ViewType.Table,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
refetchQueries: [getOperationName(GET_VIEWS) ?? ''],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[createViewsMutation, objectId],
|
||||||
|
);
|
||||||
|
|
||||||
|
const updateViewFields = useCallback(
|
||||||
|
(views: TableView[]) => {
|
||||||
|
if (!views.length) return;
|
||||||
|
|
||||||
|
return Promise.all(
|
||||||
|
views.map((view) =>
|
||||||
|
updateViewMutation({
|
||||||
|
variables: {
|
||||||
|
data: { name: view.name },
|
||||||
|
where: { id: view.id },
|
||||||
|
},
|
||||||
|
refetchQueries: [getOperationName(GET_VIEWS) ?? ''],
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[updateViewMutation],
|
||||||
|
);
|
||||||
|
|
||||||
|
useGetViewsQuery({
|
||||||
|
variables: {
|
||||||
|
where: {
|
||||||
|
objectId: { equals: objectId },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
onCompleted: (data) => {
|
||||||
|
setViews(
|
||||||
|
data.views.map((view) => ({
|
||||||
|
id: view.id,
|
||||||
|
name: view.name,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleViewsChange = useCallback(
|
||||||
|
async (nextViews: TableView[]) => {
|
||||||
|
const viewsToCreate = nextViews.filter(
|
||||||
|
(nextView) => !viewsById[nextView.id],
|
||||||
|
);
|
||||||
|
await createViews(viewsToCreate);
|
||||||
|
|
||||||
|
const viewsToUpdate = nextViews.filter(
|
||||||
|
(nextView) =>
|
||||||
|
viewsById[nextView.id] &&
|
||||||
|
viewsById[nextView.id].name !== nextView.name,
|
||||||
|
);
|
||||||
|
await updateViewFields(viewsToUpdate);
|
||||||
|
},
|
||||||
|
[createViews, updateViewFields, viewsById],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { handleViewsChange };
|
||||||
|
};
|
||||||
@ -1,6 +1,5 @@
|
|||||||
import { Context, useCallback } from 'react';
|
import { useCallback, useEffect } from 'react';
|
||||||
import { getOperationName } from '@apollo/client/utilities';
|
import { getOperationName } from '@apollo/client/utilities';
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
sortsByKeyScopedState,
|
sortsByKeyScopedState,
|
||||||
@ -10,9 +9,10 @@ import type {
|
|||||||
SelectedSortType,
|
SelectedSortType,
|
||||||
SortType,
|
SortType,
|
||||||
} from '@/ui/filter-n-sort/types/interface';
|
} from '@/ui/filter-n-sort/types/interface';
|
||||||
|
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
|
||||||
|
import { currentTableViewIdState } from '@/ui/table/states/tableViewsState';
|
||||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
import { currentViewIdState } from '@/views/states/currentViewIdState';
|
|
||||||
import {
|
import {
|
||||||
useCreateViewSortsMutation,
|
useCreateViewSortsMutation,
|
||||||
useDeleteViewSortsMutation,
|
useDeleteViewSortsMutation,
|
||||||
@ -25,14 +25,25 @@ import { GET_VIEW_SORTS } from '../graphql/queries/getViewSorts';
|
|||||||
|
|
||||||
export const useViewSorts = <SortField>({
|
export const useViewSorts = <SortField>({
|
||||||
availableSorts,
|
availableSorts,
|
||||||
Context,
|
|
||||||
}: {
|
}: {
|
||||||
availableSorts: SortType<SortField>[];
|
availableSorts: SortType<SortField>[];
|
||||||
Context?: Context<string | null>;
|
|
||||||
}) => {
|
}) => {
|
||||||
const currentViewId = useRecoilValue(currentViewIdState);
|
const currentViewId = useRecoilScopedValue(
|
||||||
const [, setSorts] = useRecoilScopedState(sortScopedState, Context);
|
currentTableViewIdState,
|
||||||
const sortsByKey = useRecoilScopedValue(sortsByKeyScopedState, Context);
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
|
const [, setSorts] = useRecoilScopedState(
|
||||||
|
sortScopedState,
|
||||||
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
|
const sortsByKey = useRecoilScopedValue(
|
||||||
|
sortsByKeyScopedState,
|
||||||
|
TableRecoilScopeContext,
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!currentViewId) setSorts([]);
|
||||||
|
}, [currentViewId, setSorts]);
|
||||||
|
|
||||||
useGetViewSortsQuery({
|
useGetViewSortsQuery({
|
||||||
skip: !currentViewId,
|
skip: !currentViewId,
|
||||||
@ -44,11 +55,19 @@ export const useViewSorts = <SortField>({
|
|||||||
onCompleted: (data) => {
|
onCompleted: (data) => {
|
||||||
setSorts(
|
setSorts(
|
||||||
data.viewSorts
|
data.viewSorts
|
||||||
.map((viewSort) => ({
|
.map((viewSort) => {
|
||||||
...availableSorts.find((sort) => sort.key === viewSort.key),
|
const availableSort = availableSorts.find(
|
||||||
label: viewSort.name,
|
(sort) => sort.key === viewSort.key,
|
||||||
order: viewSort.direction.toLowerCase(),
|
);
|
||||||
}))
|
|
||||||
|
return availableSort
|
||||||
|
? {
|
||||||
|
...availableSort,
|
||||||
|
label: viewSort.name,
|
||||||
|
order: viewSort.direction.toLowerCase(),
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
})
|
||||||
.filter((sort): sort is SelectedSortType<SortField> => !!sort),
|
.filter((sort): sort is SelectedSortType<SortField> => !!sort),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
import { atom } from 'recoil';
|
|
||||||
|
|
||||||
export const currentViewIdState = atom<string | undefined>({
|
|
||||||
key: 'currentViewIdState',
|
|
||||||
default: undefined,
|
|
||||||
});
|
|
||||||
@ -68,7 +68,10 @@ export function Companies() {
|
|||||||
icon={<IconBuildingSkyscraper size={theme.icon.size.md} />}
|
icon={<IconBuildingSkyscraper size={theme.icon.size.md} />}
|
||||||
onAddButtonClick={handleAddButtonClick}
|
onAddButtonClick={handleAddButtonClick}
|
||||||
>
|
>
|
||||||
<RecoilScope SpecificContext={TableRecoilScopeContext}>
|
<RecoilScope
|
||||||
|
scopeId="companies"
|
||||||
|
SpecificContext={TableRecoilScopeContext}
|
||||||
|
>
|
||||||
<StyledTableContainer>
|
<StyledTableContainer>
|
||||||
<CompanyTable />
|
<CompanyTable />
|
||||||
</StyledTableContainer>
|
</StyledTableContainer>
|
||||||
|
|||||||
@ -56,7 +56,7 @@ export function People() {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RecoilScope SpecificContext={TableRecoilScopeContext}>
|
<RecoilScope scopeId="people" SpecificContext={TableRecoilScopeContext}>
|
||||||
<WithTopBarContainer
|
<WithTopBarContainer
|
||||||
title="People"
|
title="People"
|
||||||
icon={<IconUser size={theme.icon.size.sm} />}
|
icon={<IconUser size={theme.icon.size.sm} />}
|
||||||
|
|||||||
@ -110,6 +110,11 @@ import {
|
|||||||
UpdateViewSortAbilityHandler,
|
UpdateViewSortAbilityHandler,
|
||||||
DeleteViewSortAbilityHandler,
|
DeleteViewSortAbilityHandler,
|
||||||
} from './handlers/view-sort.ability-handler';
|
} from './handlers/view-sort.ability-handler';
|
||||||
|
import {
|
||||||
|
CreateViewAbilityHandler,
|
||||||
|
ReadViewAbilityHandler,
|
||||||
|
UpdateViewAbilityHandler,
|
||||||
|
} from './handlers/view.ability-handler';
|
||||||
|
|
||||||
@Global()
|
@Global()
|
||||||
@Module({
|
@Module({
|
||||||
@ -194,14 +199,18 @@ import {
|
|||||||
CreatePipelineProgressAbilityHandler,
|
CreatePipelineProgressAbilityHandler,
|
||||||
UpdatePipelineProgressAbilityHandler,
|
UpdatePipelineProgressAbilityHandler,
|
||||||
DeletePipelineProgressAbilityHandler,
|
DeletePipelineProgressAbilityHandler,
|
||||||
// ViewField
|
|
||||||
ReadViewFieldAbilityHandler,
|
|
||||||
CreateViewFieldAbilityHandler,
|
|
||||||
UpdateViewFieldAbilityHandler,
|
|
||||||
//Favorite
|
//Favorite
|
||||||
ReadFavoriteAbilityHandler,
|
ReadFavoriteAbilityHandler,
|
||||||
CreateFavoriteAbilityHandler,
|
CreateFavoriteAbilityHandler,
|
||||||
DeleteFavoriteAbilityHandler,
|
DeleteFavoriteAbilityHandler,
|
||||||
|
// View
|
||||||
|
ReadViewAbilityHandler,
|
||||||
|
CreateViewAbilityHandler,
|
||||||
|
UpdateViewAbilityHandler,
|
||||||
|
// ViewField
|
||||||
|
ReadViewFieldAbilityHandler,
|
||||||
|
CreateViewFieldAbilityHandler,
|
||||||
|
UpdateViewFieldAbilityHandler,
|
||||||
// ViewSort
|
// ViewSort
|
||||||
ReadViewSortAbilityHandler,
|
ReadViewSortAbilityHandler,
|
||||||
CreateViewSortAbilityHandler,
|
CreateViewSortAbilityHandler,
|
||||||
@ -288,14 +297,18 @@ import {
|
|||||||
CreatePipelineProgressAbilityHandler,
|
CreatePipelineProgressAbilityHandler,
|
||||||
UpdatePipelineProgressAbilityHandler,
|
UpdatePipelineProgressAbilityHandler,
|
||||||
DeletePipelineProgressAbilityHandler,
|
DeletePipelineProgressAbilityHandler,
|
||||||
// ViewField
|
|
||||||
ReadViewFieldAbilityHandler,
|
|
||||||
CreateViewFieldAbilityHandler,
|
|
||||||
UpdateViewFieldAbilityHandler,
|
|
||||||
//Favorite
|
//Favorite
|
||||||
ReadFavoriteAbilityHandler,
|
ReadFavoriteAbilityHandler,
|
||||||
CreateFavoriteAbilityHandler,
|
CreateFavoriteAbilityHandler,
|
||||||
DeleteFavoriteAbilityHandler,
|
DeleteFavoriteAbilityHandler,
|
||||||
|
// View
|
||||||
|
ReadViewAbilityHandler,
|
||||||
|
CreateViewAbilityHandler,
|
||||||
|
UpdateViewAbilityHandler,
|
||||||
|
// ViewField
|
||||||
|
ReadViewFieldAbilityHandler,
|
||||||
|
CreateViewFieldAbilityHandler,
|
||||||
|
UpdateViewFieldAbilityHandler,
|
||||||
// ViewSort
|
// ViewSort
|
||||||
ReadViewSortAbilityHandler,
|
ReadViewSortAbilityHandler,
|
||||||
CreateViewSortAbilityHandler,
|
CreateViewSortAbilityHandler,
|
||||||
|
|||||||
87
server/src/core/view/resolvers/view.resolver.ts
Normal file
87
server/src/core/view/resolvers/view.resolver.ts
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import { UseGuards } from '@nestjs/common';
|
||||||
|
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
|
||||||
|
|
||||||
|
import { accessibleBy } from '@casl/prisma';
|
||||||
|
import { Prisma, Workspace } from '@prisma/client';
|
||||||
|
|
||||||
|
import { AppAbility } from 'src/ability/ability.factory';
|
||||||
|
import {
|
||||||
|
CreateViewAbilityHandler,
|
||||||
|
ReadViewAbilityHandler,
|
||||||
|
UpdateViewAbilityHandler,
|
||||||
|
} from 'src/ability/handlers/view.ability-handler';
|
||||||
|
import { FindManyViewArgs } from 'src/core/@generated/view/find-many-view.args';
|
||||||
|
import { View } from 'src/core/@generated/view/view.model';
|
||||||
|
import { ViewService } from 'src/core/view/services/view.service';
|
||||||
|
import { CheckAbilities } from 'src/decorators/check-abilities.decorator';
|
||||||
|
import {
|
||||||
|
PrismaSelect,
|
||||||
|
PrismaSelector,
|
||||||
|
} from 'src/decorators/prisma-select.decorator';
|
||||||
|
import { UserAbility } from 'src/decorators/user-ability.decorator';
|
||||||
|
import { AbilityGuard } from 'src/guards/ability.guard';
|
||||||
|
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
|
||||||
|
import { UpdateOneViewArgs } from 'src/core/@generated/view/update-one-view.args';
|
||||||
|
import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator';
|
||||||
|
import { AffectedRows } from 'src/core/@generated/prisma/affected-rows.output';
|
||||||
|
import { CreateManyViewArgs } from 'src/core/@generated/view/create-many-view.args';
|
||||||
|
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
|
@Resolver(() => View)
|
||||||
|
export class ViewResolver {
|
||||||
|
constructor(private readonly viewService: ViewService) {}
|
||||||
|
|
||||||
|
@Mutation(() => AffectedRows)
|
||||||
|
@UseGuards(AbilityGuard)
|
||||||
|
@CheckAbilities(CreateViewAbilityHandler)
|
||||||
|
async createManyView(
|
||||||
|
@Args() args: CreateManyViewArgs,
|
||||||
|
@AuthWorkspace() workspace: Workspace,
|
||||||
|
): Promise<AffectedRows> {
|
||||||
|
return this.viewService.createMany({
|
||||||
|
data: args.data.map((data) => ({
|
||||||
|
...data,
|
||||||
|
workspaceId: workspace.id,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Query(() => [View])
|
||||||
|
@UseGuards(AbilityGuard)
|
||||||
|
@CheckAbilities(ReadViewAbilityHandler)
|
||||||
|
async findManyView(
|
||||||
|
@Args() args: FindManyViewArgs,
|
||||||
|
@UserAbility() ability: AppAbility,
|
||||||
|
@PrismaSelector({ modelName: 'View' })
|
||||||
|
prismaSelect: PrismaSelect<'View'>,
|
||||||
|
): Promise<Partial<View>[]> {
|
||||||
|
return this.viewService.findMany({
|
||||||
|
where: args.where
|
||||||
|
? {
|
||||||
|
AND: [args.where, accessibleBy(ability).View],
|
||||||
|
}
|
||||||
|
: accessibleBy(ability).View,
|
||||||
|
orderBy: args.orderBy,
|
||||||
|
cursor: args.cursor,
|
||||||
|
take: args.take,
|
||||||
|
skip: args.skip,
|
||||||
|
distinct: args.distinct,
|
||||||
|
select: prismaSelect.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Mutation(() => View)
|
||||||
|
@UseGuards(AbilityGuard)
|
||||||
|
@CheckAbilities(UpdateViewAbilityHandler)
|
||||||
|
async updateOneView(
|
||||||
|
@Args() args: UpdateOneViewArgs,
|
||||||
|
@PrismaSelector({ modelName: 'View' })
|
||||||
|
prismaSelect: PrismaSelect<'View'>,
|
||||||
|
): Promise<Partial<View>> {
|
||||||
|
return this.viewService.update({
|
||||||
|
data: args.data,
|
||||||
|
where: args.where,
|
||||||
|
select: prismaSelect.value,
|
||||||
|
} as Prisma.ViewUpdateArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
39
server/src/core/view/services/view.service.ts
Normal file
39
server/src/core/view/services/view.service.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { PrismaService } from 'src/database/prisma.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ViewService {
|
||||||
|
constructor(private readonly prismaService: PrismaService) {}
|
||||||
|
|
||||||
|
// Find
|
||||||
|
findFirst = this.prismaService.client.view.findFirst;
|
||||||
|
findFirstOrThrow = this.prismaService.client.view.findFirstOrThrow;
|
||||||
|
|
||||||
|
findUnique = this.prismaService.client.view.findUnique;
|
||||||
|
findUniqueOrThrow = this.prismaService.client.view.findUniqueOrThrow;
|
||||||
|
|
||||||
|
findMany = this.prismaService.client.view.findMany;
|
||||||
|
|
||||||
|
// Create
|
||||||
|
create = this.prismaService.client.view.create;
|
||||||
|
createMany = this.prismaService.client.view.createMany;
|
||||||
|
|
||||||
|
// Update
|
||||||
|
update = this.prismaService.client.view.update;
|
||||||
|
upsert = this.prismaService.client.view.upsert;
|
||||||
|
updateMany = this.prismaService.client.view.updateMany;
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
delete = this.prismaService.client.view.delete;
|
||||||
|
deleteMany = this.prismaService.client.view.deleteMany;
|
||||||
|
|
||||||
|
// Aggregate
|
||||||
|
aggregate = this.prismaService.client.view.aggregate;
|
||||||
|
|
||||||
|
// Count
|
||||||
|
count = this.prismaService.client.view.count;
|
||||||
|
|
||||||
|
// GroupBy
|
||||||
|
groupBy = this.prismaService.client.view.groupBy;
|
||||||
|
}
|
||||||
@ -4,11 +4,15 @@ import { ViewFieldService } from './services/view-field.service';
|
|||||||
import { ViewFieldResolver } from './resolvers/view-field.resolver';
|
import { ViewFieldResolver } from './resolvers/view-field.resolver';
|
||||||
import { ViewSortService } from './services/view-sort.service';
|
import { ViewSortService } from './services/view-sort.service';
|
||||||
import { ViewSortResolver } from './resolvers/view-sort.resolver';
|
import { ViewSortResolver } from './resolvers/view-sort.resolver';
|
||||||
|
import { ViewService } from './services/view.service';
|
||||||
|
import { ViewResolver } from './resolvers/view.resolver';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [
|
providers: [
|
||||||
|
ViewService,
|
||||||
ViewFieldService,
|
ViewFieldService,
|
||||||
ViewSortService,
|
ViewSortService,
|
||||||
|
ViewResolver,
|
||||||
ViewFieldResolver,
|
ViewFieldResolver,
|
||||||
ViewSortResolver,
|
ViewSortResolver,
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user