Compare commits

...

10 Commits

Author SHA1 Message Date
Weiko 7ba72db509 v0.35.3 2025-01-03 16:26:05 +01:00
nitin 53dc083a6c Fixed import modal content scroll bug (#9330)
fixes #9297
2025-01-03 16:24:50 +01:00
Guillim b67d92f4ba fix "Relations" not displayed on kanban views (#9301)
fix #7358

Problem was only for some specific relations : target tasks.
(Not related to 1o1 VS 1toMany VS MAnyto1)
2025-01-03 16:24:27 +01:00
Weiko 283c5aa5d1 0.35.2 2024-12-26 11:49:34 +01:00
Marie cc93c26786 Fix creation of a new view duplicating existing filters (#9240)
Fixes #9239
2024-12-26 11:48:37 +01:00
nitin ed381cc81d Floating inputs border radius fix (#9237)
closes #9230
2024-12-26 11:47:35 +01:00
Guillim 36f0ac4c69 quick fix for positionInViewFilterGroup (#9223)
fix 9206

In the future, we should have a look at the column naming
"positionInViewFilterGroup"
because it breaks the SQL queries in `record-position-query.factory.ts`
for viewFilter tablenames
2024-12-26 11:44:06 +01:00
Weiko 4a8a49d0d4 bump 0.35.1 2024-12-23 17:32:35 +01:00
nitin bc45cb9e8d Tablist fix (#9216) 2024-12-23 17:31:51 +01:00
Weiko dd657a498f Release 0.35.0 2024-12-23 17:09:17 +01:00
18 changed files with 107 additions and 71 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "twenty-emails",
"version": "0.40.0-canary",
"version": "0.35.3",
"description": "",
"author": "",
"private": true,
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "twenty-front",
"version": "0.40.0-canary",
"version": "0.35.3",
"private": true,
"type": "module",
"scripts": {
@@ -1,6 +1,9 @@
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getObjectMetadataIdentifierFields } from '@/object-metadata/utils/getObjectMetadataIdentifierFields';
import { hasPositionField } from '@/object-metadata/utils/hasPositionField';
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
import { recordBoardVisibleFieldDefinitionsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardVisibleFieldDefinitionsComponentSelector';
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
@@ -36,6 +39,16 @@ export const useRecordBoardRecordGqlFields = ({
identifierQueryFields[imageIdentifierFieldMetadataItem.name] = true;
}
const { objectMetadataItem: noteTargetObjectMetadataItem } =
useObjectMetadataItem({
objectNameSingular: CoreObjectNameSingular.NoteTarget,
});
const { objectMetadataItem: taskTargetObjectMetadataItem } =
useObjectMetadataItem({
objectNameSingular: CoreObjectNameSingular.TaskTarget,
});
const recordGqlFields: Record<string, any> = {
id: true,
deletedAt: true,
@@ -47,18 +60,12 @@ export const useRecordBoardRecordGqlFields = ({
),
...(hasPositionField(objectMetadataItem) ? { position: true } : undefined),
...identifierQueryFields,
noteTargets: {
note: {
id: true,
title: true,
},
},
taskTargets: {
task: {
id: true,
title: true,
},
},
noteTargets: generateDepthOneRecordGqlFields({
objectMetadataItem: noteTargetObjectMetadataItem,
}),
taskTargets: generateDepthOneRecordGqlFields({
objectMetadataItem: taskTargetObjectMetadataItem,
}),
};
if (isDefined(recordGroupFieldMetadata?.name)) {
@@ -50,7 +50,11 @@ export const RecordInlineCellEditMode = ({
data-testid="inline-cell-edit-mode-container"
>
{createPortal(
<OverlayContainer ref={refs.setFloating} style={floatingStyles}>
<OverlayContainer
ref={refs.setFloating}
style={floatingStyles}
borderRadius="sm"
>
{children}
</OverlayContainer>,
document.body,
@@ -40,7 +40,11 @@ export const RecordTableCellEditMode = ({
ref={refs.setReference}
data-testid="editable-cell-edit-mode-container"
>
<OverlayContainer ref={refs.setFloating} style={floatingStyles}>
<OverlayContainer
ref={refs.setFloating}
style={floatingStyles}
borderRadius="sm"
>
{children}
</OverlayContainer>
</StyledEditableCellEditModeContainer>
@@ -25,6 +25,7 @@ import { initialComputedColumnsSelector } from '@/spreadsheet-import/steps/compo
import { UnmatchColumn } from '@/spreadsheet-import/steps/components/MatchColumnsStep/components/UnmatchColumn';
import { SpreadsheetImportStep } from '@/spreadsheet-import/steps/types/SpreadsheetImportStep';
import { SpreadsheetImportStepType } from '@/spreadsheet-import/steps/types/SpreadsheetImportStepType';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
import { useRecoilState } from 'recoil';
import { ColumnGrid } from './components/ColumnGrid';
import { TemplateColumn } from './components/TemplateColumn';
@@ -326,37 +327,43 @@ export const MatchColumnsStep = <T extends string>({
return (
<>
<StyledContent>
<Heading
title="Match Columns"
description="Select the correct field for each column you'd like to import."
/>
<ColumnGrid
columns={columns}
renderUserColumn={(columns, columnIndex) => (
<UserTableColumn
column={columns[columnIndex]}
importedRow={dataExample.map(
(row) => row[columns[columnIndex].index],
)}
/>
)}
renderTemplateColumn={(columns, columnIndex) => (
<TemplateColumn
columns={columns}
columnIndex={columnIndex}
onChange={onChange}
/>
)}
renderUnmatchedColumn={(columns, columnIndex) => (
<UnmatchColumn
columns={columns}
columnIndex={columnIndex}
onSubChange={onSubChange}
/>
)}
/>
</StyledContent>
<ScrollWrapper
contextProviderName="modalContent"
componentInstanceId="scroll-wrapper-modal-content"
heightMode="full"
>
<StyledContent>
<Heading
title="Match Columns"
description="Select the correct field for each column you'd like to import."
/>
<ColumnGrid
columns={columns}
renderUserColumn={(columns, columnIndex) => (
<UserTableColumn
column={columns[columnIndex]}
importedRow={dataExample.map(
(row) => row[columns[columnIndex].index],
)}
/>
)}
renderTemplateColumn={(columns, columnIndex) => (
<TemplateColumn
columns={columns}
columnIndex={columnIndex}
onChange={onChange}
/>
)}
renderUnmatchedColumn={(columns, columnIndex) => (
<UnmatchColumn
columns={columns}
columnIndex={columnIndex}
onSubChange={onSubChange}
/>
)}
/>
</StyledContent>
</ScrollWrapper>
<StepNavigationButton
onClick={handleOnContinue}
isLoading={isLoading}
@@ -1,14 +1,17 @@
import styled from '@emotion/styled';
// eslint-disable-next-line @nx/workspace-styled-components-prefixed-with-styled
export const OverlayContainer = styled.div`
export const OverlayContainer = styled.div<{
borderRadius?: 'sm' | 'md';
}>`
align-items: center;
display: flex;
backdrop-filter: ${({ theme }) => theme.blur.medium};
width: fit-content;
border-radius: ${({ theme }) => theme.border.radius.md};
border-radius: ${({ theme, borderRadius }) =>
theme.border.radius[borderRadius ?? 'md']};
background: ${({ theme }) => theme.background.transparent.primary};
border: 1px solid ${({ theme }) => theme.border.color.medium};
@@ -9,7 +9,6 @@ import { recordStoreFamilyState } from '@/object-record/record-store/states/reco
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { RightDrawerFooter } from '@/ui/layout/right-drawer/components/RightDrawerFooter';
import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer';
import { ShowPageTabListFromUrlOptionalEffect } from '@/ui/layout/show-page/components/ShowPageTabListFromUrlOptionalEffect';
import { SingleTabProps, TabList } from '@/ui/layout/tab/components/TabList';
import { useTabList } from '@/ui/layout/tab/hooks/useTabList';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
@@ -126,16 +125,12 @@ export const ShowPageSubContainer = ({
)}
<StyledShowPageRightContainer isMobile={isMobile}>
<StyledTabListContainer shouldDisplay={visibleTabs.length > 1}>
<ShowPageTabListFromUrlOptionalEffect
isInRightDrawer={isInRightDrawer}
componentInstanceId={tabListComponentId}
tabListIds={tabs.map((tab) => tab.id)}
/>
<TabList
behaveAsLinks={!isInRightDrawer}
loading={loading || isNewViewableRecordLoading}
tabListInstanceId={tabListComponentId}
tabs={tabs}
isInRightDrawer={isInRightDrawer}
/>
</StyledTabListContainer>
{(isMobile || isInRightDrawer) && summaryCard}
@@ -1,3 +1,4 @@
import { TabListFromUrlOptionalEffect } from '@/ui/layout/tab/components/TabListFromUrlOptionalEffect';
import { useTabList } from '@/ui/layout/tab/hooks/useTabList';
import { TabListScope } from '@/ui/layout/tab/scopes/TabListScope';
import { LayoutCard } from '@/ui/layout/tab/types/LayoutCard';
@@ -25,6 +26,7 @@ type TabListProps = {
loading?: boolean;
behaveAsLinks?: boolean;
className?: string;
isInRightDrawer?: boolean;
};
const StyledContainer = styled.div`
@@ -41,6 +43,7 @@ export const TabList = ({
tabListInstanceId,
loading,
behaveAsLinks = true,
isInRightDrawer,
className,
}: TabListProps) => {
const visibleTabs = tabs.filter((tab) => !tab.hide);
@@ -59,6 +62,11 @@ export const TabList = ({
return (
<TabListScope tabListScopeId={tabListInstanceId}>
<TabListFromUrlOptionalEffect
isInRightDrawer={!!isInRightDrawer}
componentInstanceId={tabListInstanceId}
tabListIds={tabs.map((tab) => tab.id)}
/>
<ScrollWrapper
defaultEnableYScroll={false}
contextProviderName="tabList"
@@ -2,17 +2,17 @@ import { useTabList } from '@/ui/layout/tab/hooks/useTabList';
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
type ShowPageTabListFromUrlOptionalEffectProps = {
type TabListFromUrlOptionalEffectProps = {
componentInstanceId: string;
tabListIds: string[];
isInRightDrawer: boolean;
};
export const ShowPageTabListFromUrlOptionalEffect = ({
export const TabListFromUrlOptionalEffect = ({
componentInstanceId,
tabListIds,
isInRightDrawer,
}: ShowPageTabListFromUrlOptionalEffectProps) => {
}: TabListFromUrlOptionalEffectProps) => {
const location = useLocation();
const { activeTabId, setActiveTabId } = useTabList(componentInstanceId);
@@ -13,6 +13,7 @@ import { useDestroyOneRecordMutation } from '@/object-record/hooks/useDestroyOne
import { useUpdateOneRecordMutation } from '@/object-record/hooks/useUpdateOneRecordMutation';
import { GraphQLView } from '@/views/types/GraphQLView';
import { ViewFilter } from '@/views/types/ViewFilter';
import { v4 } from 'uuid';
export const usePersistViewFilterRecords = () => {
const { objectMetadataItem } = useObjectMetadataItem({
@@ -49,7 +50,7 @@ export const usePersistViewFilterRecords = () => {
mutation: createOneRecordMutation,
variables: {
input: {
id: viewFilter.id,
id: v4(),
fieldMetadataId: viewFilter.fieldMetadataId,
viewId: view.id,
value: viewFilter.value,
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "twenty-server",
"version": "0.40.0-canary",
"version": "0.35.3",
"description": "",
"author": "",
"private": true,
@@ -22,34 +22,34 @@ describe('QueryRunnerArgsFactory', () => {
{
type: FieldMetadataType.POSITION,
isCustom: true,
nameSingular: 'position',
name: 'position',
},
{
type: FieldMetadataType.NUMBER,
isCustom: true,
nameSingular: 'testNumber',
name: 'testNumber',
},
{
type: FieldMetadataType.TEXT,
isCustom: true,
nameSingular: 'otherField',
name: 'otherField',
},
],
fieldsByName: {
position: {
type: FieldMetadataType.POSITION,
isCustom: true,
nameSingular: 'position',
name: 'position',
},
testNumber: {
type: FieldMetadataType.NUMBER,
isCustom: true,
nameSingular: 'testNumber',
name: 'testNumber',
},
otherField: {
type: FieldMetadataType.TEXT,
isCustom: true,
nameSingular: 'otherField',
name: 'otherField',
},
} as unknown as FieldMetadataMap,
},
@@ -40,7 +40,9 @@ export class QueryRunnerArgsFactory {
const shouldBackfillPosition =
options.objectMetadataItemWithFieldMaps.fields.some(
(field) => field.type === FieldMetadataType.POSITION,
(field) =>
field.type === FieldMetadataType.POSITION &&
field.name === 'position',
);
switch (resolverArgsType) {
@@ -17,6 +17,7 @@ import {
TimeoutError,
UserInputError,
} from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
import { isDefined } from 'src/utils/is-defined';
export const workspaceQueryRunnerGraphqlApiExceptionHandler = (
error: Error,
@@ -49,7 +50,11 @@ export const workspaceQueryRunnerGraphqlApiExceptionHandler = (
return fieldMetadata?.label;
});
const columnNames = affectedColumns?.join(', ');
if (!isDefined(affectedColumns)) {
throw new UserInputError(`A duplicate entry was detected`);
}
const columnNames = affectedColumns.join(', ');
if (affectedColumns?.length === 1) {
throw new UserInputError(
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "twenty-shared",
"version": "0.40.0-canary",
"version": "0.35.3",
"license": "AGPL-3.0",
"main": "./dist/index.js",
"scripts": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "twenty-ui",
"version": "0.40.0-canary",
"version": "0.35.3",
"type": "module",
"main": "./src/index.ts",
"exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "twenty-website",
"version": "0.40.0-canary",
"version": "0.35.3",
"private": true,
"scripts": {
"nx": "NX_DEFAULT_PROJECT=twenty-website node ../../node_modules/nx/bin/nx.js",