Add no value column on Kanban (#6252)
<img width="1512" alt="image" src="https://github.com/user-attachments/assets/9fcdd5ca-4329-467c-ada8-4dd5d45be259"> Open questions: - the Tag component does not match Figma in term of style and API for "transparent" | "outline". We need to discuss with @Bonapara what is the desired behavior here - right now opportunity.stage is not nullable. We need to discuss with @FelixMalfait and @Bonapara what we want here. I would advocate to make a it nullable for now until we introduce settings on select fields. custom select are nullable and it could be confusing for the user Follow up: - enhance tests on Tags - add story to cover the No Value column on record board
This commit is contained in:
@ -40,6 +40,7 @@ export const formatFieldMetadataItemAsFieldDefinition = ({
|
|||||||
targetFieldMetadataName:
|
targetFieldMetadataName:
|
||||||
field.relationDefinition?.targetFieldMetadata?.name ?? '',
|
field.relationDefinition?.targetFieldMetadata?.name ?? '',
|
||||||
options: field.options,
|
options: field.options,
|
||||||
|
isNullable: field.isNullable,
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useContext, useRef } from 'react';
|
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { DragDropContext, OnDragEndResponder } from '@hello-pangea/dnd'; // Atlassian dnd does not support StrictMode from RN 18, so we use a fork @hello-pangea/dnd https://github.com/atlassian/react-beautiful-dnd/issues/2350
|
import { DragDropContext, OnDragEndResponder } from '@hello-pangea/dnd'; // Atlassian dnd does not support StrictMode from RN 18, so we use a fork @hello-pangea/dnd https://github.com/atlassian/react-beautiful-dnd/issues/2350
|
||||||
|
import { useContext, useRef } from 'react';
|
||||||
import { useRecoilCallback, useRecoilValue } from 'recoil';
|
import { useRecoilCallback, useRecoilValue } from 'recoil';
|
||||||
import { Key } from 'ts-key-enum';
|
import { Key } from 'ts-key-enum';
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
import React, { useContext, useState } from 'react';
|
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
import { useContext, useState } from 'react';
|
||||||
import { IconDotsVertical, Tag } from 'twenty-ui';
|
import { IconDotsVertical, Tag } from 'twenty-ui';
|
||||||
|
|
||||||
import { RecordBoardColumnDropdownMenu } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnDropdownMenu';
|
import { RecordBoardColumnDropdownMenu } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnDropdownMenu';
|
||||||
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
|
import { RecordBoardColumnContext } from '@/object-record/record-board/record-board-column/contexts/RecordBoardColumnContext';
|
||||||
import { RecordBoardColumnHotkeyScope } from '@/object-record/record-board/types/BoardColumnHotkeyScope';
|
import { RecordBoardColumnHotkeyScope } from '@/object-record/record-board/types/BoardColumnHotkeyScope';
|
||||||
|
import { RecordBoardColumnDefinitionType } from '@/object-record/record-board/types/RecordBoardColumnDefinition';
|
||||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||||
|
|
||||||
@ -79,14 +80,23 @@ export const RecordBoardColumnHeader = () => {
|
|||||||
>
|
>
|
||||||
<Tag
|
<Tag
|
||||||
onClick={handleBoardColumnMenuOpen}
|
onClick={handleBoardColumnMenuOpen}
|
||||||
color={columnDefinition.color}
|
variant={
|
||||||
|
columnDefinition.type === RecordBoardColumnDefinitionType.Value
|
||||||
|
? 'solid'
|
||||||
|
: 'outline'
|
||||||
|
}
|
||||||
|
color={
|
||||||
|
columnDefinition.type === RecordBoardColumnDefinitionType.Value
|
||||||
|
? columnDefinition.color
|
||||||
|
: 'transparent'
|
||||||
|
}
|
||||||
text={columnDefinition.title}
|
text={columnDefinition.title}
|
||||||
/>
|
/>
|
||||||
{!!boardColumnTotal && <StyledAmount>${boardColumnTotal}</StyledAmount>}
|
{!!boardColumnTotal && <StyledAmount>${boardColumnTotal}</StyledAmount>}
|
||||||
{!isHeaderHovered && (
|
{!isHeaderHovered && (
|
||||||
<StyledNumChildren>{recordCount}</StyledNumChildren>
|
<StyledNumChildren>{recordCount}</StyledNumChildren>
|
||||||
)}
|
)}
|
||||||
{isHeaderHovered && (
|
{isHeaderHovered && columnDefinition.actions.length > 0 && (
|
||||||
<StyledHeaderActions>
|
<StyledHeaderActions>
|
||||||
<LightIconButton
|
<LightIconButton
|
||||||
accent="tertiary"
|
accent="tertiary"
|
||||||
@ -96,7 +106,7 @@ export const RecordBoardColumnHeader = () => {
|
|||||||
</StyledHeaderActions>
|
</StyledHeaderActions>
|
||||||
)}
|
)}
|
||||||
</StyledHeader>
|
</StyledHeader>
|
||||||
{isBoardColumnMenuOpen && (
|
{isBoardColumnMenuOpen && columnDefinition.actions.length > 0 && (
|
||||||
<RecordBoardColumnDropdownMenu
|
<RecordBoardColumnDropdownMenu
|
||||||
onClose={handleBoardColumnMenuClose}
|
onClose={handleBoardColumnMenuClose}
|
||||||
stageId={columnDefinition.id}
|
stageId={columnDefinition.id}
|
||||||
|
|||||||
@ -2,11 +2,30 @@ import { ThemeColor } from 'twenty-ui';
|
|||||||
|
|
||||||
import { RecordBoardColumnAction } from '@/object-record/record-board/types/RecordBoardColumnAction';
|
import { RecordBoardColumnAction } from '@/object-record/record-board/types/RecordBoardColumnAction';
|
||||||
|
|
||||||
export type RecordBoardColumnDefinition = {
|
export const enum RecordBoardColumnDefinitionType {
|
||||||
id: string;
|
Value = 'value',
|
||||||
title: string;
|
NoValue = 'no-value',
|
||||||
value: string;
|
}
|
||||||
|
|
||||||
|
export type RecordBoardColumnDefinitionNoValue = {
|
||||||
|
id: 'no-value';
|
||||||
|
type: RecordBoardColumnDefinitionType.NoValue;
|
||||||
|
title: 'No Value';
|
||||||
position: number;
|
position: number;
|
||||||
color: ThemeColor;
|
value: null;
|
||||||
actions: RecordBoardColumnAction[];
|
actions: RecordBoardColumnAction[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type RecordBoardColumnDefinitionValue = {
|
||||||
|
id: string;
|
||||||
|
type: RecordBoardColumnDefinitionType.Value;
|
||||||
|
title: string;
|
||||||
|
value: string;
|
||||||
|
color: ThemeColor;
|
||||||
|
position: number;
|
||||||
|
actions: RecordBoardColumnAction[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RecordBoardColumnDefinition =
|
||||||
|
| RecordBoardColumnDefinitionValue
|
||||||
|
| RecordBoardColumnDefinitionNoValue;
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import {
|
|||||||
FieldSelectMetadata,
|
FieldSelectMetadata,
|
||||||
FieldTextMetadata,
|
FieldTextMetadata,
|
||||||
} from '@/object-record/record-field/types/FieldMetadata';
|
} from '@/object-record/record-field/types/FieldMetadata';
|
||||||
import { type } from 'os';
|
|
||||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||||
import {
|
import {
|
||||||
mockedCompanyObjectMetadataItem,
|
mockedCompanyObjectMetadataItem,
|
||||||
@ -44,6 +43,7 @@ export const selectFieldDefinition: FieldDefinition<FieldSelectMetadata> = {
|
|||||||
metadata: {
|
metadata: {
|
||||||
fieldName: 'accountOwner',
|
fieldName: 'accountOwner',
|
||||||
options: [{ label: 'Elon Musk', color: 'blue', value: 'userId' }],
|
options: [{ label: 'Elon Musk', color: 'blue', value: 'userId' }],
|
||||||
|
isNullable: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import React, { useRef, useState } from 'react';
|
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
import { useRef, useState } from 'react';
|
||||||
import { Key } from 'ts-key-enum';
|
import { Key } from 'ts-key-enum';
|
||||||
|
|
||||||
import { useClearField } from '@/object-record/record-field/hooks/useClearField';
|
import { useClearField } from '@/object-record/record-field/hooks/useClearField';
|
||||||
@ -98,14 +98,16 @@ export const SelectFieldInput = ({
|
|||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
|
|
||||||
<DropdownMenuItemsContainer hasMaxHeight>
|
<DropdownMenuItemsContainer hasMaxHeight>
|
||||||
<MenuItemSelectTag
|
{fieldDefinition.metadata.isNullable && (
|
||||||
key={`No ${fieldDefinition.label}`}
|
<MenuItemSelectTag
|
||||||
selected={false}
|
key={`No ${fieldDefinition.label}`}
|
||||||
text={`No ${fieldDefinition.label}`}
|
selected={false}
|
||||||
color="transparent"
|
text={`No ${fieldDefinition.label}`}
|
||||||
variant="outline"
|
color="transparent"
|
||||||
onClick={handleClearField}
|
variant="outline"
|
||||||
/>
|
onClick={handleClearField}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{optionsInDropDown.map((option) => {
|
{optionsInDropDown.map((option) => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -128,6 +128,7 @@ export type FieldSelectMetadata = {
|
|||||||
objectMetadataNameSingular?: string;
|
objectMetadataNameSingular?: string;
|
||||||
fieldName: string;
|
fieldName: string;
|
||||||
options: { label: string; color: ThemeColor; value: string }[];
|
options: { label: string; color: ThemeColor; value: string }[];
|
||||||
|
isNullable: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FieldMultiSelectMetadata = {
|
export type FieldMultiSelectMetadata = {
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export const RecordIndexBoardColumnLoaderEffect = ({
|
|||||||
}: {
|
}: {
|
||||||
recordBoardId: string;
|
recordBoardId: string;
|
||||||
objectNameSingular: string;
|
objectNameSingular: string;
|
||||||
boardFieldSelectValue: string;
|
boardFieldSelectValue: string | null;
|
||||||
boardFieldMetadataId: string | null;
|
boardFieldMetadataId: string | null;
|
||||||
columnId: string;
|
columnId: string;
|
||||||
}) => {
|
}) => {
|
||||||
|
|||||||
@ -45,6 +45,15 @@ export const RecordIndexBoardDataLoader = ({
|
|||||||
columnId={columnIds[index]}
|
columnId={columnIds[index]}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
{recordIndexKanbanFieldMetadataItem?.isNullable && (
|
||||||
|
<RecordIndexBoardColumnLoaderEffect
|
||||||
|
objectNameSingular={objectNameSingular}
|
||||||
|
boardFieldMetadataId={recordIndexKanbanFieldMetadataId}
|
||||||
|
boardFieldSelectValue={null}
|
||||||
|
recordBoardId={recordBoardId}
|
||||||
|
columnId={'no-value'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,12 +10,13 @@ import { useRecordBoardRecordGqlFields } from '@/object-record/record-index/hook
|
|||||||
import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
|
import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
|
||||||
import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState';
|
import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState';
|
||||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||||
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
type UseLoadRecordIndexBoardProps = {
|
type UseLoadRecordIndexBoardProps = {
|
||||||
objectNameSingular: string;
|
objectNameSingular: string;
|
||||||
boardFieldMetadataId: string | null;
|
boardFieldMetadataId: string | null;
|
||||||
recordBoardId: string;
|
recordBoardId: string;
|
||||||
columnFieldSelectValue: string;
|
columnFieldSelectValue: string | null;
|
||||||
columnId: string;
|
columnId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -51,9 +52,11 @@ export const useLoadRecordIndexBoardColumn = ({
|
|||||||
|
|
||||||
const filter = {
|
const filter = {
|
||||||
...requestFilters,
|
...requestFilters,
|
||||||
[recordIndexKanbanFieldMetadataItem?.name ?? '']: {
|
[recordIndexKanbanFieldMetadataItem?.name ?? '']: isDefined(
|
||||||
in: [columnFieldSelectValue],
|
columnFieldSelectValue,
|
||||||
},
|
)
|
||||||
|
? { in: [columnFieldSelectValue] }
|
||||||
|
: { is: 'NULL' },
|
||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
import { IconPencil } from 'twenty-ui';
|
import { IconPencil } from 'twenty-ui';
|
||||||
|
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
import { RecordBoardColumnDefinition } from '@/object-record/record-board/types/RecordBoardColumnDefinition';
|
import {
|
||||||
|
RecordBoardColumnDefinition,
|
||||||
|
RecordBoardColumnDefinitionNoValue,
|
||||||
|
RecordBoardColumnDefinitionType,
|
||||||
|
RecordBoardColumnDefinitionValue,
|
||||||
|
} from '@/object-record/record-board/types/RecordBoardColumnDefinition';
|
||||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||||
|
|
||||||
export const computeRecordBoardColumnDefinitionsFromObjectMetadata = (
|
export const computeRecordBoardColumnDefinitionsFromObjectMetadata = (
|
||||||
@ -25,20 +30,42 @@ export const computeRecordBoardColumnDefinitionsFromObjectMetadata = (
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return selectFieldMetadataItem.options.map((selectOption) => ({
|
const valueColumns = selectFieldMetadataItem.options.map(
|
||||||
id: selectOption.id,
|
(selectOption) =>
|
||||||
title: selectOption.label,
|
({
|
||||||
value: selectOption.value,
|
id: selectOption.id,
|
||||||
color: selectOption.color,
|
type: RecordBoardColumnDefinitionType.Value,
|
||||||
position: selectOption.position,
|
title: selectOption.label,
|
||||||
actions: [
|
value: selectOption.value,
|
||||||
{
|
color: selectOption.color,
|
||||||
id: 'edit',
|
position: selectOption.position,
|
||||||
label: 'Edit from settings',
|
actions: [
|
||||||
icon: IconPencil,
|
{
|
||||||
position: 0,
|
id: 'edit',
|
||||||
callback: navigateToSelectSettings,
|
label: 'Edit from settings',
|
||||||
},
|
icon: IconPencil,
|
||||||
],
|
position: 0,
|
||||||
}));
|
callback: navigateToSelectSettings,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}) satisfies RecordBoardColumnDefinitionValue,
|
||||||
|
);
|
||||||
|
|
||||||
|
const noValueColumn = {
|
||||||
|
id: 'no-value',
|
||||||
|
title: 'No Value',
|
||||||
|
type: RecordBoardColumnDefinitionType.NoValue,
|
||||||
|
value: null,
|
||||||
|
actions: [],
|
||||||
|
position:
|
||||||
|
selectFieldMetadataItem.options
|
||||||
|
.map((option) => option.position)
|
||||||
|
.reduce((a, b) => Math.max(a, b), 0) + 1,
|
||||||
|
} satisfies RecordBoardColumnDefinitionNoValue;
|
||||||
|
|
||||||
|
if (selectFieldMetadataItem.isNullable === true) {
|
||||||
|
return [...valueColumns, noValueColumn];
|
||||||
|
}
|
||||||
|
|
||||||
|
return valueColumns;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -41,7 +41,6 @@ export const ViewBar = ({
|
|||||||
const sortDropdownId = 'view-sort';
|
const sortDropdownId = 'view-sort';
|
||||||
|
|
||||||
const loading = useIsPrefetchLoading();
|
const loading = useIsPrefetchLoading();
|
||||||
|
|
||||||
if (!objectNamePlural) {
|
if (!objectNamePlural) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { isUndefined } from '@sniptt/guards';
|
import { isUndefined } from '@sniptt/guards';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
import { ApolloProvider } from '@apollo/client';
|
||||||
|
import { loadDevMessages } from '@apollo/client/dev';
|
||||||
|
import { Decorator } from '@storybook/react';
|
||||||
import { HelmetProvider } from 'react-helmet-async';
|
import { HelmetProvider } from 'react-helmet-async';
|
||||||
import {
|
import {
|
||||||
createMemoryRouter,
|
createMemoryRouter,
|
||||||
@ -6,9 +9,6 @@ import {
|
|||||||
Route,
|
Route,
|
||||||
RouterProvider,
|
RouterProvider,
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
import { ApolloProvider } from '@apollo/client';
|
|
||||||
import { loadDevMessages } from '@apollo/client/dev';
|
|
||||||
import { Decorator } from '@storybook/react';
|
|
||||||
import { RecoilRoot } from 'recoil';
|
import { RecoilRoot } from 'recoil';
|
||||||
|
|
||||||
import { ClientConfigProviderEffect } from '@/client-config/components/ClientConfigProviderEffect';
|
import { ClientConfigProviderEffect } from '@/client-config/components/ClientConfigProviderEffect';
|
||||||
@ -21,6 +21,7 @@ import { DefaultLayout } from '~/modules/ui/layout/page/DefaultLayout';
|
|||||||
import { UserProvider } from '~/modules/users/components/UserProvider';
|
import { UserProvider } from '~/modules/users/components/UserProvider';
|
||||||
import { mockedApolloClient } from '~/testing/mockedApolloClient';
|
import { mockedApolloClient } from '~/testing/mockedApolloClient';
|
||||||
|
|
||||||
|
import { PrefetchDataProvider } from '@/prefetch/components/PrefetchDataProvider';
|
||||||
import { FullHeightStorybookLayout } from '../FullHeightStorybookLayout';
|
import { FullHeightStorybookLayout } from '../FullHeightStorybookLayout';
|
||||||
|
|
||||||
export type PageDecoratorArgs = {
|
export type PageDecoratorArgs = {
|
||||||
@ -73,7 +74,9 @@ const Providers = () => {
|
|||||||
<HelmetProvider>
|
<HelmetProvider>
|
||||||
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
||||||
<ObjectMetadataItemsProvider>
|
<ObjectMetadataItemsProvider>
|
||||||
<Outlet />
|
<PrefetchDataProvider>
|
||||||
|
<Outlet />
|
||||||
|
</PrefetchDataProvider>
|
||||||
</ObjectMetadataItemsProvider>
|
</ObjectMetadataItemsProvider>
|
||||||
</SnackBarProviderScope>
|
</SnackBarProviderScope>
|
||||||
</HelmetProvider>
|
</HelmetProvider>
|
||||||
|
|||||||
@ -110,6 +110,57 @@ export const graphqlMocks = {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
graphql.query('CombinedFindManyRecords', () => {
|
||||||
|
return HttpResponse.json({
|
||||||
|
data: {
|
||||||
|
views: {
|
||||||
|
edges: mockedViewsData.map((view) => ({
|
||||||
|
node: {
|
||||||
|
...view,
|
||||||
|
viewFilters: {
|
||||||
|
edges: [],
|
||||||
|
totalCount: 0,
|
||||||
|
},
|
||||||
|
viewSorts: {
|
||||||
|
edges: [],
|
||||||
|
totalCount: 0,
|
||||||
|
},
|
||||||
|
viewFields: {
|
||||||
|
edges: mockedViewFieldsData
|
||||||
|
.filter((viewField) => viewField.viewId === view.id)
|
||||||
|
.map((viewField) => ({
|
||||||
|
node: viewField,
|
||||||
|
cursor: null,
|
||||||
|
})),
|
||||||
|
totalCount: mockedViewFieldsData.filter(
|
||||||
|
(viewField) => viewField.viewId === view.id,
|
||||||
|
).length,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cursor: null,
|
||||||
|
})),
|
||||||
|
pageInfo: {
|
||||||
|
hasNextPage: false,
|
||||||
|
hasPreviousPage: false,
|
||||||
|
startCursor: null,
|
||||||
|
endCursor: null,
|
||||||
|
totalCount: mockedViewsData.length,
|
||||||
|
},
|
||||||
|
totalCount: mockedViewsData.length,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
favorites: {
|
||||||
|
edges: [],
|
||||||
|
totalCount: 0,
|
||||||
|
pageInfo: {
|
||||||
|
hasNextPage: false,
|
||||||
|
hasPreviousPage: false,
|
||||||
|
startCursor: null,
|
||||||
|
endCursor: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}),
|
||||||
graphql.query('FindManyCompanies', ({ variables }) => {
|
graphql.query('FindManyCompanies', ({ variables }) => {
|
||||||
const mockedData = variables.limit
|
const mockedData = variables.limit
|
||||||
? companiesMock.slice(0, variables.limit)
|
? companiesMock.slice(0, variables.limit)
|
||||||
|
|||||||
@ -9,6 +9,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 0,
|
position: 0,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 180,
|
size: 180,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '2a96bbc8-d86d-439a-8e50-4b07ebd27750',
|
id: '2a96bbc8-d86d-439a-8e50-4b07ebd27750',
|
||||||
@ -17,6 +20,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 1,
|
position: 1,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 100,
|
size: 100,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '0c1b4c7b-6a3d-4fb0-bf2b-5d7c8fb844ed',
|
id: '0c1b4c7b-6a3d-4fb0-bf2b-5d7c8fb844ed',
|
||||||
@ -25,6 +31,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 2,
|
position: 2,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 150,
|
size: 150,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'cc7f9560-32b5-4b82-8fd9-b05fe77c8cf7',
|
id: 'cc7f9560-32b5-4b82-8fd9-b05fe77c8cf7',
|
||||||
@ -33,6 +42,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 3,
|
position: 3,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 150,
|
size: 150,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '3de4d078-3396-4480-be2d-6f3b1a228b0d',
|
id: '3de4d078-3396-4480-be2d-6f3b1a228b0d',
|
||||||
@ -41,6 +53,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 4,
|
position: 4,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 150,
|
size: 150,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '4650c8fb-0f1e-4342-88dc-adedae1445f9',
|
id: '4650c8fb-0f1e-4342-88dc-adedae1445f9',
|
||||||
@ -49,6 +64,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 5,
|
position: 5,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 170,
|
size: 170,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '727430bf-6ff8-4c85-9828-cbe72ac0fc27',
|
id: '727430bf-6ff8-4c85-9828-cbe72ac0fc27',
|
||||||
@ -57,6 +75,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 6,
|
position: 6,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 170,
|
size: 170,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
|
|
||||||
// People
|
// People
|
||||||
@ -67,6 +88,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 0,
|
position: 0,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 210,
|
size: 210,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e1e24864-8601-4cd8-8a63-09c1285f2e39',
|
id: 'e1e24864-8601-4cd8-8a63-09c1285f2e39',
|
||||||
@ -75,6 +99,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 1,
|
position: 1,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 150,
|
size: 150,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '5a1df716-7211-445a-9f16-9783a00998a7',
|
id: '5a1df716-7211-445a-9f16-9783a00998a7',
|
||||||
@ -83,6 +110,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 2,
|
position: 2,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 150,
|
size: 150,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'a6e1197a-7e84-4d92-ace2-367c0bc46c49',
|
id: 'a6e1197a-7e84-4d92-ace2-367c0bc46c49',
|
||||||
@ -91,6 +121,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 3,
|
position: 3,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 150,
|
size: 150,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'c9343097-d14b-4559-a5fa-626c1527d39f',
|
id: 'c9343097-d14b-4559-a5fa-626c1527d39f',
|
||||||
@ -99,6 +132,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 4,
|
position: 4,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 150,
|
size: 150,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'a873e5f0-fed6-47e9-a712-6854eab3ec77',
|
id: 'a873e5f0-fed6-47e9-a712-6854eab3ec77',
|
||||||
@ -107,6 +143,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 5,
|
position: 5,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 150,
|
size: 150,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '66f134b8-5329-422f-b88e-83e6bb707eb5',
|
id: '66f134b8-5329-422f-b88e-83e6bb707eb5',
|
||||||
@ -115,6 +154,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 6,
|
position: 6,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 150,
|
size: 150,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '648faa24-cabb-482a-8578-ba3f09906017',
|
id: '648faa24-cabb-482a-8578-ba3f09906017',
|
||||||
@ -123,6 +165,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 7,
|
position: 7,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 150,
|
size: 150,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '3a9e7f0d-a4ce-4ad5-aac7-3a24eb1a412d',
|
id: '3a9e7f0d-a4ce-4ad5-aac7-3a24eb1a412d',
|
||||||
@ -131,6 +176,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 8,
|
position: 8,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 150,
|
size: 150,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
|
|
||||||
// Opportunities
|
// Opportunities
|
||||||
@ -141,6 +189,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 0,
|
position: 0,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 180,
|
size: 180,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '3159acd8-463f-458d-bf9a-af8ac6f57dc0',
|
id: '3159acd8-463f-458d-bf9a-af8ac6f57dc0',
|
||||||
@ -149,6 +200,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 2,
|
position: 2,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 100,
|
size: 100,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'afc0819d-b694-4e3c-a2e6-25261aa3ed2c',
|
id: 'afc0819d-b694-4e3c-a2e6-25261aa3ed2c',
|
||||||
@ -157,6 +211,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 3,
|
position: 3,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 150,
|
size: 150,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'ec0507bb-aedc-4695-ba96-d81bdeb9db83',
|
id: 'ec0507bb-aedc-4695-ba96-d81bdeb9db83',
|
||||||
@ -165,6 +222,9 @@ export const mockedViewFieldsData = [
|
|||||||
position: 4,
|
position: 4,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 150,
|
size: 150,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '3f1585f6-44f6-45c5-b840-bc05af5d0008',
|
id: '3f1585f6-44f6-45c5-b840-bc05af5d0008',
|
||||||
@ -173,5 +233,8 @@ export const mockedViewFieldsData = [
|
|||||||
position: 5,
|
position: 5,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
size: 150,
|
size: 150,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
__typename: 'ViewField',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@ -2,25 +2,58 @@ export const mockedViewsData = [
|
|||||||
{
|
{
|
||||||
id: '37a8a866-eb17-4e76-9382-03143a2f6a80',
|
id: '37a8a866-eb17-4e76-9382-03143a2f6a80',
|
||||||
name: 'All companies',
|
name: 'All companies',
|
||||||
objectMetadataId: 'company',
|
objectMetadataId: 'f9fd99a8-108f-4066-9675-cde753cf5de9',
|
||||||
type: 'table',
|
type: 'table',
|
||||||
|
icon: 'IconSkyline',
|
||||||
|
key: 'INDEX',
|
||||||
|
kanbanFieldMetadataId: null,
|
||||||
|
position: 0,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
isCompact: false,
|
||||||
|
|
||||||
|
__typename: 'View',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '6095799e-b48f-4e00-b071-10818083593a',
|
id: '6095799e-b48f-4e00-b071-10818083593a',
|
||||||
name: 'All people',
|
name: 'All people',
|
||||||
objectMetadataId: 'person',
|
objectMetadataId: 'person',
|
||||||
type: 'table',
|
type: 'table',
|
||||||
|
icon: 'IconPerson',
|
||||||
|
key: 'INDEX',
|
||||||
|
kanbanFieldMetadataId: null,
|
||||||
|
position: 0,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
isCompact: false,
|
||||||
|
__typename: 'View',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e26f66b7-f890-4a5c-b4d2-ec09987b5308',
|
id: 'e26f66b7-f890-4a5c-b4d2-ec09987b5308',
|
||||||
name: 'All opportunities',
|
name: 'All opportunities',
|
||||||
objectMetadataId: 'company',
|
objectMetadataId: 'company',
|
||||||
type: 'kanban',
|
type: 'kanban',
|
||||||
|
icon: 'IconOpportunity',
|
||||||
|
key: 'INDEX',
|
||||||
|
kanbanFieldMetadataId: null,
|
||||||
|
position: 0,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
isCompact: false,
|
||||||
|
__typename: 'View',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '5c307222-1dd5-4ff3-ab06-8d990e9b3c74',
|
id: '5c307222-1dd5-4ff3-ab06-8d990e9b3c74',
|
||||||
name: 'All companies (v2)',
|
name: 'All companies (v2)',
|
||||||
objectMetadataId: 'a3195559-cc20-4749-9565-572a2f506581',
|
objectMetadataId: 'f9fd99a8-108f-4066-9675-cde753cf5de9',
|
||||||
type: 'table',
|
type: 'table',
|
||||||
|
icon: 'IconSkyline',
|
||||||
|
key: 'INDEX',
|
||||||
|
kanbanFieldMetadataId: null,
|
||||||
|
position: 0,
|
||||||
|
createdAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2021-09-01T00:00:00.000Z',
|
||||||
|
isCompact: false,
|
||||||
|
__typename: 'View',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useContext } from 'react';
|
|
||||||
import { styled } from '@linaria/react';
|
import { styled } from '@linaria/react';
|
||||||
|
import { useContext } from 'react';
|
||||||
|
|
||||||
import { IconComponent, OverflowingTextWithTooltip } from '@ui/display';
|
import { IconComponent, OverflowingTextWithTooltip } from '@ui/display';
|
||||||
import {
|
import {
|
||||||
|
|||||||
Reference in New Issue
Block a user