+
+
-
diff --git a/front/src/modules/ui/data/data-table/components/DataTableEffect.tsx b/front/src/modules/ui/data/data-table/components/DataTableEffect.tsx
index 54a8cd639..c2a996af3 100644
--- a/front/src/modules/ui/data/data-table/components/DataTableEffect.tsx
+++ b/front/src/modules/ui/data/data-table/components/DataTableEffect.tsx
@@ -23,10 +23,8 @@ export const DataTableEffect = ({
getRequestResultKey,
getRequestOptimisticEffectDefinition,
- filterDefinitionArray,
setActionBarEntries,
setContextMenuEntries,
- sortDefinitionArray,
}: {
useGetRequest: typeof useGetCompaniesQuery | typeof useGetPeopleQuery;
getRequestResultKey: string;
@@ -59,7 +57,7 @@ export const DataTableEffect = ({
onCompleted: (data: any) => {
const entities = data[getRequestResultKey] ?? [];
- setDataTableData(entities, filterDefinitionArray, sortDefinitionArray);
+ setDataTableData(entities);
registerOptimisticEffect({
variables: { orderBy: sortsOrderBy, where: tablefiltersWhere },
diff --git a/front/src/modules/ui/data/data-table/hooks/useSetDataTableData.ts b/front/src/modules/ui/data/data-table/hooks/useSetDataTableData.ts
index 9e77272a5..e44858044 100644
--- a/front/src/modules/ui/data/data-table/hooks/useSetDataTableData.ts
+++ b/front/src/modules/ui/data/data-table/hooks/useSetDataTableData.ts
@@ -1,15 +1,10 @@
import { useRecoilCallback } from 'recoil';
import { entityFieldsFamilyState } from '@/ui/data/field/states/entityFieldsFamilyState';
-import { FilterDefinition } from '@/ui/data/filter/types/FilterDefinition';
-import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { useView } from '@/views/hooks/useView';
-import { availableSortDefinitionsScopedState } from '@/views/states/availableSortDefinitionsScopedState';
-import { SortDefinition } from '../../sort/types/SortDefinition';
import { isFetchingDataTableDataState } from '../states/isFetchingDataTableDataState';
import { numberOfTableRowsState } from '../states/numberOfTableRowsState';
-import { TableRecoilScopeContext } from '../states/recoil-scope-contexts/TableRecoilScopeContext';
import { tableRowIdsState } from '../states/tableRowIdsState';
import { useResetTableRowSelection } from './useResetTableRowSelection';
@@ -18,15 +13,9 @@ export const useSetDataTableData = () => {
const resetTableRowSelection = useResetTableRowSelection();
const { setEntityCountInCurrentView } = useView();
- const tableContextScopeId = useRecoilScopeId(TableRecoilScopeContext);
-
return useRecoilCallback(
({ set, snapshot }) =>
-
(
- newEntityArray: T[],
- filterDefinitionArray: FilterDefinition[],
- sortDefinitionArray: SortDefinition[],
- ) => {
+ (newEntityArray: T[]) => {
for (const entity of newEntityArray) {
const currentEntity = snapshot
.getLoadable(entityFieldsFamilyState(entity.id))
@@ -50,16 +39,9 @@ export const useSetDataTableData = () => {
resetTableRowSelection();
set(numberOfTableRowsState, entityIds.length);
-
setEntityCountInCurrentView(entityIds.length);
-
- set(
- availableSortDefinitionsScopedState({ scopeId: tableContextScopeId }),
- sortDefinitionArray,
- );
-
set(isFetchingDataTableDataState, false);
},
- [resetTableRowSelection, setEntityCountInCurrentView, tableContextScopeId],
+ [resetTableRowSelection, setEntityCountInCurrentView],
);
};
diff --git a/front/src/modules/ui/data/filter/utils/turnFiltersIntoWhereClauseV2.ts b/front/src/modules/ui/data/filter/utils/turnFiltersIntoWhereClauseV2.ts
new file mode 100644
index 000000000..7270022f6
--- /dev/null
+++ b/front/src/modules/ui/data/filter/utils/turnFiltersIntoWhereClauseV2.ts
@@ -0,0 +1,53 @@
+import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
+import { Field } from '~/generated/graphql';
+
+import { Filter } from '../types/Filter';
+
+type FilterToTurnIntoWhereClause = Omit & {
+ definition: {
+ type: Filter['definition']['type'];
+ };
+};
+
+export const turnFiltersIntoWhereClauseV2 = (
+ filters: FilterToTurnIntoWhereClause[],
+ fields: Pick[],
+) => {
+ const whereClause: Record = {};
+
+ filters.forEach((filter) => {
+ const correspondingField = fields.find(
+ (field) => field.id === filter.fieldId,
+ );
+ if (!correspondingField) {
+ throw new Error(
+ `Could not find field ${filter.fieldId} in metadata object`,
+ );
+ }
+
+ switch (filter.definition.type) {
+ case 'text':
+ switch (filter.operand) {
+ case ViewFilterOperand.Contains:
+ whereClause[correspondingField.name] = {
+ eq: filter.value,
+ };
+ return;
+ case ViewFilterOperand.DoesNotContain:
+ whereClause[correspondingField.name] = {
+ not: {
+ eq: filter.value,
+ },
+ };
+ return;
+ default:
+ throw new Error(
+ `Unknown operand ${filter.operand} for ${filter.definition.type} filter`,
+ );
+ }
+ default:
+ throw new Error('Unknown filter type');
+ }
+ });
+ return whereClause;
+};
diff --git a/front/src/modules/ui/data/sort/hooks/useSortStates.ts b/front/src/modules/ui/data/sort/hooks/useSortStates.ts
index d4662d661..4e4c79d74 100644
--- a/front/src/modules/ui/data/sort/hooks/useSortStates.ts
+++ b/front/src/modules/ui/data/sort/hooks/useSortStates.ts
@@ -1,6 +1,6 @@
import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2';
-import { availableSortDefinitionsScopedState } from '@/views/states/availableSortDefinitionsScopedState';
+import { availableSortDefinitionsScopedState } from '../states/availableSortDefinitionsScopedState';
import { isSortSelectedScopedState } from '../states/isSortSelectedScopedState';
export const useSortStates = (scopeId: string) => {
diff --git a/front/src/modules/ui/data/sort/states/availableSortsScopedState.ts b/front/src/modules/ui/data/sort/states/availableSortDefinitionsScopedState.ts
similarity index 55%
rename from front/src/modules/ui/data/sort/states/availableSortsScopedState.ts
rename to front/src/modules/ui/data/sort/states/availableSortDefinitionsScopedState.ts
index 1e8354cdb..0258a0d85 100644
--- a/front/src/modules/ui/data/sort/states/availableSortsScopedState.ts
+++ b/front/src/modules/ui/data/sort/states/availableSortDefinitionsScopedState.ts
@@ -2,7 +2,9 @@ import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScope
import { SortDefinition } from '../types/SortDefinition';
-export const availableSortsScopedState = createScopedState({
- key: 'availableSortsScopedState',
+export const availableSortDefinitionsScopedState = createScopedState<
+ SortDefinition[]
+>({
+ key: 'availableSortDefinitionsScopedState',
defaultValue: [],
});
diff --git a/front/src/modules/ui/data/sort/utils/turnSortsIntoOrderByV2.ts b/front/src/modules/ui/data/sort/utils/turnSortsIntoOrderByV2.ts
new file mode 100644
index 000000000..306a030a2
--- /dev/null
+++ b/front/src/modules/ui/data/sort/utils/turnSortsIntoOrderByV2.ts
@@ -0,0 +1,26 @@
+import { Field } from '~/generated/graphql';
+
+import { Sort } from '../types/Sort';
+
+export const turnSortsIntoOrderByV2 = (
+ sorts: Sort[],
+ fields: Pick[],
+) => {
+ const sortsObject: Record = {};
+ sorts.forEach((sort) => {
+ const correspondingField = fields.find(
+ (field) => field.id === sort.fieldId,
+ );
+ if (!correspondingField) {
+ throw new Error(
+ `Could not find field ${sort.fieldId} in metadata object`,
+ );
+ }
+ const direction =
+ sort.direction === 'asc' ? 'AscNullsFirst' : 'DescNullsLast';
+
+ sortsObject[correspondingField.name] = direction;
+ });
+
+ return sortsObject;
+};
diff --git a/front/src/modules/ui/layout/board/components/EntityBoard.tsx b/front/src/modules/ui/layout/board/components/EntityBoard.tsx
index 8880896c2..4022a69a7 100644
--- a/front/src/modules/ui/layout/board/components/EntityBoard.tsx
+++ b/front/src/modules/ui/layout/board/components/EntityBoard.tsx
@@ -42,6 +42,7 @@ const StyledWrapper = styled.div`
flex-direction: column;
height: 100%;
overflow: hidden;
+ position: relative;
width: 100%;
`;
diff --git a/front/src/modules/ui/navigation/action-bar/components/__stories__/ActionBar.stories.tsx b/front/src/modules/ui/navigation/action-bar/components/__stories__/ActionBar.stories.tsx
index 43fed4d32..28a5070d8 100644
--- a/front/src/modules/ui/navigation/action-bar/components/__stories__/ActionBar.stories.tsx
+++ b/front/src/modules/ui/navigation/action-bar/components/__stories__/ActionBar.stories.tsx
@@ -2,7 +2,7 @@ import { MemoryRouter } from 'react-router-dom';
import { Meta, StoryObj } from '@storybook/react';
import { useSetRecoilState } from 'recoil';
-import { useCompanyTableActionBarEntries } from '@/companies/hooks/useCompanyTableActionBarEntries';
+import { useCompanyTableContextMenuEntries } from '@/companies/hooks/useCompanyTableContextMenuEntries';
import { CompanyTableMockMode } from '@/companies/table/components/CompanyTableMockMode';
import { TableRecoilScopeContext } from '@/ui/data/data-table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
@@ -12,7 +12,7 @@ import { actionBarOpenState } from '../../states/actionBarIsOpenState';
import { ActionBar } from '../ActionBar';
const FilledActionBar = (props: { selectedIds: string[] }) => {
- const { setActionBarEntries } = useCompanyTableActionBarEntries();
+ const { setActionBarEntries } = useCompanyTableContextMenuEntries();
setActionBarEntries();
const setActionBarOpenState = useSetRecoilState(actionBarOpenState);
setActionBarOpenState(true);
diff --git a/front/src/pages/settings/data-model/SettingsNewObject.tsx b/front/src/pages/settings/data-model/SettingsNewObject.tsx
index 0cb777356..ce4df2da5 100644
--- a/front/src/pages/settings/data-model/SettingsNewObject.tsx
+++ b/front/src/pages/settings/data-model/SettingsNewObject.tsx
@@ -1,6 +1,7 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
+import { useCreateOneObject } from '@/metadata/hooks/useCreateOneObject';
import { useMetadataObjectForSettings } from '@/metadata/hooks/useMetadataObjectForSettings';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
@@ -17,6 +18,7 @@ import { H2Title } from '@/ui/display/typography/components/H2Title';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Section } from '@/ui/layout/section/components/Section';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
+import { ViewType } from '@/views/types/ViewType';
export const SettingsNewObject = () => {
const navigate = useNavigate();
@@ -29,6 +31,10 @@ export const SettingsNewObject = () => {
disabledMetadataObjects: disabledObjects,
} = useMetadataObjectForSettings();
+ const { createOneObject: createOneView } = useCreateOneObject({
+ objectNamePlural: 'viewsV2',
+ });
+
const [selectedStandardObjectIds, setSelectedStandardObjectIds] = useState<
Record
>({});
@@ -60,12 +66,18 @@ export const SettingsNewObject = () => {
}
if (selectedObjectType === 'Custom') {
- await createObject({
+ const createdObject = await createObject({
labelPlural: customFormValues.labelPlural,
labelSingular: customFormValues.labelSingular,
description: customFormValues.description,
icon: customFormValues.icon,
});
+
+ await createOneView?.({
+ objectId: createdObject.data?.createOneObject.id,
+ type: ViewType.Table,
+ name: `All ${customFormValues.labelPlural}`,
+ });
}
navigate('/settings/objects');
diff --git a/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx b/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx
index 42edc7b22..f2da9f63d 100644
--- a/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx
+++ b/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx
@@ -1,8 +1,11 @@
import { useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
+import { useCreateOneObject } from '@/metadata/hooks/useCreateOneObject';
+import { useFindManyObjects } from '@/metadata/hooks/useFindManyObjects';
import { useMetadataField } from '@/metadata/hooks/useMetadataField';
import { useMetadataObjectForSettings } from '@/metadata/hooks/useMetadataObjectForSettings';
+import { PaginatedObjectTypeResults } from '@/metadata/types/PaginatedObjectTypeResults';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
@@ -13,6 +16,8 @@ import { AppPath } from '@/types/AppPath';
import { IconSettings } from '@/ui/display/icon';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
+import { View } from '@/views/types/View';
+import { ViewType } from '@/views/types/ViewType';
export const SettingsObjectNewFieldStep2 = () => {
const navigate = useNavigate();
@@ -36,15 +41,47 @@ export const SettingsObjectNewFieldStep2 = () => {
type: MetadataFieldDataType;
}>({ icon: 'IconUsers', label: '', type: 'number' });
- if (!activeMetadataObject) return null;
+ const [objectViews, setObjectViews] = useState([]);
+
+ const { createOneObject: createOneViewField } = useCreateOneObject({
+ objectNamePlural: 'viewFieldsV2',
+ });
+
+ useFindManyObjects({
+ objectNamePlural: 'viewsV2',
+ filter: {
+ type: { eq: ViewType.Table },
+ objectId: { eq: activeMetadataObject?.id },
+ },
+ onCompleted: async (data: PaginatedObjectTypeResults) => {
+ const views = data.edges;
+
+ if (!views) {
+ return;
+ }
+
+ setObjectViews(data.edges.map(({ node }) => node));
+ },
+ });
+
+ if (!activeMetadataObject || !objectViews.length) return null;
const canSave = !!formValues.label;
const handleSave = async () => {
- await createMetadataField({
+ const createdField = await createMetadataField({
...formValues,
objectId: activeMetadataObject.id,
});
+ objectViews.forEach(async (view) => {
+ await createOneViewField?.({
+ viewId: view.id,
+ fieldId: createdField.data?.createOneField.id,
+ position: activeMetadataObject.fields.length,
+ isVisible: true,
+ size: 100,
+ });
+ });
navigate(`/settings/objects/${objectSlug}`);
};
diff --git a/server/src/metadata/commands/data-seed-tenant.command.ts b/server/src/metadata/commands/data-seed-tenant.command.ts
index 75e99a1e2..aa14737c8 100644
--- a/server/src/metadata/commands/data-seed-tenant.command.ts
+++ b/server/src/metadata/commands/data-seed-tenant.command.ts
@@ -1,7 +1,7 @@
import { Command, CommandRunner, Option } from 'nest-commander';
-import { TenantInitialisationService } from '../tenant-initialisation/tenant-initialisation.service';
-import { DataSourceMetadataService } from '../data-source-metadata/data-source-metadata.service';
+import { DataSourceMetadataService } from 'src/metadata/data-source-metadata/data-source-metadata.service';
+import { TenantInitialisationService } from 'src/metadata/tenant-initialisation/tenant-initialisation.service';
// TODO: implement dry-run
interface DataSeedTenantOptions {
diff --git a/server/src/metadata/field-metadata/hooks/before-create-one-field.hook.ts b/server/src/metadata/field-metadata/hooks/before-create-one-field.hook.ts
index 0bc4e7dba..1d4402578 100644
--- a/server/src/metadata/field-metadata/hooks/before-create-one-field.hook.ts
+++ b/server/src/metadata/field-metadata/hooks/before-create-one-field.hook.ts
@@ -22,7 +22,7 @@ export class BeforeCreateOneField
}
instance.input.workspaceId = workspaceId;
- instance.input.isActive = false;
+ instance.input.isActive = true;
instance.input.isCustom = true;
return instance;
}
diff --git a/server/src/metadata/object-metadata/hooks/before-create-one-object.hook.ts b/server/src/metadata/object-metadata/hooks/before-create-one-object.hook.ts
index d3b2d79bb..79f1677ff 100644
--- a/server/src/metadata/object-metadata/hooks/before-create-one-object.hook.ts
+++ b/server/src/metadata/object-metadata/hooks/before-create-one-object.hook.ts
@@ -32,7 +32,7 @@ export class BeforeCreateOneObject
instance.input.dataSourceId = lastDataSourceMetadata.id;
instance.input.targetTableName = instance.input.namePlural;
instance.input.workspaceId = workspaceId;
- instance.input.isActive = false;
+ instance.input.isActive = true;
instance.input.isCustom = true;
return instance;
}