This reverts commit cc71394863.
Regression introduced in https://github.com/twentyhq/twenty/pull/13213
The import/export use an upsert logic and when it goes through the
"update" path it fails due to the connect not being implemented yet
(should be in https://github.com/twentyhq/core-team-issues/issues/1230)
---------
Co-authored-by: prastoin <paul@twenty.com>
This commit is contained in:
+4
@@ -1,6 +1,7 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { StepNavigationButton } from '@/spreadsheet-import/components/StepNavigationButton';
|
||||
import { useHideStepBar } from '@/spreadsheet-import/hooks/useHideStepBar';
|
||||
import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpreadsheetImportInternal';
|
||||
import { spreadsheetImportCreatedRecordsProgressState } from '@/spreadsheet-import/states/spreadsheetImportCreatedRecordsProgressState';
|
||||
import { Modal } from '@/ui/layout/modal/components/Modal';
|
||||
@@ -37,6 +38,9 @@ type ImportDataStepProps = {
|
||||
export const ImportDataStep = ({
|
||||
recordsToImportCount,
|
||||
}: ImportDataStepProps) => {
|
||||
const hideStepBar = useHideStepBar();
|
||||
hideStepBar();
|
||||
|
||||
const { onClose } = useSpreadsheetImportInternal();
|
||||
const spreadsheetImportCreatedRecordsProgress = useRecoilValue(
|
||||
spreadsheetImportCreatedRecordsProgressState,
|
||||
|
||||
+8
-8
@@ -64,7 +64,7 @@ export type MatchColumnsStepProps = {
|
||||
onError: (message: string) => void;
|
||||
};
|
||||
|
||||
export const MatchColumnsStep = ({
|
||||
export const MatchColumnsStep = <T extends string>({
|
||||
data,
|
||||
headerValues,
|
||||
onBack,
|
||||
@@ -76,7 +76,7 @@ export const MatchColumnsStep = ({
|
||||
}: MatchColumnsStepProps) => {
|
||||
const { enqueueDialog } = useDialogManager();
|
||||
const dataExample = data.slice(0, 2);
|
||||
const { spreadsheetImportFields: fields } = useSpreadsheetImportInternal();
|
||||
const { fields } = useSpreadsheetImportInternal<T>();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [columns, setColumns] = useRecoilState(
|
||||
initialComputedColumnsSelector(headerValues),
|
||||
@@ -90,7 +90,7 @@ export const MatchColumnsStep = ({
|
||||
(columnIndex: number) => {
|
||||
setColumns(
|
||||
columns.map((column, index) =>
|
||||
columnIndex === index ? setIgnoreColumn(column) : column,
|
||||
columnIndex === index ? setIgnoreColumn<string>(column) : column,
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -109,7 +109,7 @@ export const MatchColumnsStep = ({
|
||||
);
|
||||
|
||||
const onChange = useCallback(
|
||||
(value: string, columnIndex: number) => {
|
||||
(value: T, columnIndex: number) => {
|
||||
if (value === DO_NOT_IMPORT_OPTION_KEY) {
|
||||
if (columns[columnIndex].type === SpreadsheetColumnType.ignored) {
|
||||
onRevertIgnore(columnIndex);
|
||||
@@ -119,12 +119,12 @@ export const MatchColumnsStep = ({
|
||||
} else {
|
||||
const field = fields.find(
|
||||
(field) => field.key === value,
|
||||
) as unknown as SpreadsheetImportField;
|
||||
) as unknown as SpreadsheetImportField<T>;
|
||||
const existingFieldIndex = columns.findIndex(
|
||||
(column) => 'value' in column && column.value === field.key,
|
||||
);
|
||||
setColumns(
|
||||
columns.map<SpreadsheetColumn>((column, index) => {
|
||||
columns.map<SpreadsheetColumn<string>>((column, index) => {
|
||||
if (columnIndex === index) {
|
||||
return setColumn(column, field, data);
|
||||
} else if (index === existingFieldIndex) {
|
||||
@@ -141,9 +141,9 @@ export const MatchColumnsStep = ({
|
||||
|
||||
const handleContinue = useCallback(
|
||||
async (
|
||||
values: ImportedStructuredRow[],
|
||||
values: ImportedStructuredRow<string>[],
|
||||
rawData: ImportedRow[],
|
||||
columns: SpreadsheetColumns,
|
||||
columns: SpreadsheetColumns<string>,
|
||||
) => {
|
||||
try {
|
||||
const data = await matchColumnsStepHook(values, rawData, columns);
|
||||
|
||||
+7
-7
@@ -82,28 +82,28 @@ const StyledGridHeader = styled.div<PositionProps>`
|
||||
padding-right: ${({ theme }) => theme.spacing(4)};
|
||||
`;
|
||||
|
||||
type ColumnGridProps = {
|
||||
columns: SpreadsheetColumns;
|
||||
type ColumnGridProps<T extends string> = {
|
||||
columns: SpreadsheetColumns<T>;
|
||||
renderUserColumn: (
|
||||
columns: SpreadsheetColumns,
|
||||
columns: SpreadsheetColumns<T>,
|
||||
columnIndex: number,
|
||||
) => React.ReactNode;
|
||||
renderTemplateColumn: (
|
||||
columns: SpreadsheetColumns,
|
||||
columns: SpreadsheetColumns<T>,
|
||||
columnIndex: number,
|
||||
) => React.ReactNode;
|
||||
renderUnmatchedColumn: (
|
||||
columns: SpreadsheetColumns,
|
||||
columns: SpreadsheetColumns<T>,
|
||||
columnIndex: number,
|
||||
) => React.ReactNode;
|
||||
};
|
||||
|
||||
export const ColumnGrid = ({
|
||||
export const ColumnGrid = <T extends string>({
|
||||
columns,
|
||||
renderUserColumn,
|
||||
renderTemplateColumn,
|
||||
renderUnmatchedColumn,
|
||||
}: ColumnGridProps) => {
|
||||
}: ColumnGridProps<T>) => {
|
||||
return (
|
||||
<>
|
||||
<StyledGridContainer>
|
||||
|
||||
+7
-7
@@ -16,20 +16,20 @@ const StyledIconChevronDown = styled(IconChevronDown)`
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
`;
|
||||
|
||||
export type SubMatchingSelectDropdownButtonProps = {
|
||||
option: SpreadsheetMatchedOptions | Partial<SpreadsheetMatchedOptions>;
|
||||
export type SubMatchingSelectDropdownButtonProps<T> = {
|
||||
option: SpreadsheetMatchedOptions<T> | Partial<SpreadsheetMatchedOptions<T>>;
|
||||
column:
|
||||
| SpreadsheetMatchedSelectColumn
|
||||
| SpreadsheetMatchedSelectOptionsColumn;
|
||||
| SpreadsheetMatchedSelectColumn<T>
|
||||
| SpreadsheetMatchedSelectOptionsColumn<T>;
|
||||
placeholder: string;
|
||||
};
|
||||
|
||||
export const SubMatchingSelectDropdownButton = ({
|
||||
export const SubMatchingSelectDropdownButton = <T extends string>({
|
||||
option,
|
||||
column,
|
||||
placeholder,
|
||||
}: SubMatchingSelectDropdownButtonProps) => {
|
||||
const { spreadsheetImportFields: fields } = useSpreadsheetImportInternal();
|
||||
}: SubMatchingSelectDropdownButtonProps<T>) => {
|
||||
const { fields } = useSpreadsheetImportInternal<T>();
|
||||
const options = getFieldOptions(fields, column.value) as SelectOption[];
|
||||
const value = options.find((opt) => opt.value === option.value);
|
||||
|
||||
|
||||
+9
-9
@@ -15,23 +15,23 @@ const StyledRowContainer = styled.div`
|
||||
padding-bottom: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
interface SubMatchingSelectRowProps {
|
||||
option: SpreadsheetMatchedOptions | Partial<SpreadsheetMatchedOptions>;
|
||||
interface SubMatchingSelectRowProps<T> {
|
||||
option: SpreadsheetMatchedOptions<T> | Partial<SpreadsheetMatchedOptions<T>>;
|
||||
column:
|
||||
| SpreadsheetMatchedSelectColumn
|
||||
| SpreadsheetMatchedSelectOptionsColumn;
|
||||
onSubChange: (val: string, index: number, option: string) => void;
|
||||
| SpreadsheetMatchedSelectColumn<T>
|
||||
| SpreadsheetMatchedSelectOptionsColumn<T>;
|
||||
onSubChange: (val: T, index: number, option: string) => void;
|
||||
placeholder: string;
|
||||
selectedOption?:
|
||||
| SpreadsheetMatchedOptions
|
||||
| Partial<SpreadsheetMatchedOptions>;
|
||||
| SpreadsheetMatchedOptions<T>
|
||||
| Partial<SpreadsheetMatchedOptions<T>>;
|
||||
}
|
||||
export const SubMatchingSelectRow = ({
|
||||
export const SubMatchingSelectRow = <T extends string>({
|
||||
option,
|
||||
column,
|
||||
onSubChange,
|
||||
placeholder,
|
||||
}: SubMatchingSelectRowProps) => {
|
||||
}: SubMatchingSelectRowProps<T>) => {
|
||||
return (
|
||||
<StyledRowContainer>
|
||||
<SubMatchingSelectRowLeftSelect option={option} />
|
||||
|
||||
+4
-4
@@ -15,13 +15,13 @@ const StyledControlLabel = styled.div`
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
export type SubMatchingSelectRowLeftSelectProps = {
|
||||
option: SpreadsheetMatchedOptions | Partial<SpreadsheetMatchedOptions>;
|
||||
export type SubMatchingSelectRowLeftSelectProps<T> = {
|
||||
option: SpreadsheetMatchedOptions<T> | Partial<SpreadsheetMatchedOptions<T>>;
|
||||
};
|
||||
|
||||
export const SubMatchingSelectRowLeftSelect = ({
|
||||
export const SubMatchingSelectRowLeftSelect = <T extends string>({
|
||||
option,
|
||||
}: SubMatchingSelectRowLeftSelectProps) => {
|
||||
}: SubMatchingSelectRowLeftSelectProps<T>) => {
|
||||
return (
|
||||
<SubMatchingSelectControlContainer cursor="default">
|
||||
<StyledControlLabel>
|
||||
|
||||
+11
-11
@@ -18,34 +18,34 @@ const StyledDropdownContainer = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
interface SubMatchingSelectRowRightDropdownProps {
|
||||
option: SpreadsheetMatchedOptions | Partial<SpreadsheetMatchedOptions>;
|
||||
interface SubMatchingSelectRowRightDropdownProps<T> {
|
||||
option: SpreadsheetMatchedOptions<T> | Partial<SpreadsheetMatchedOptions<T>>;
|
||||
column:
|
||||
| SpreadsheetMatchedSelectColumn
|
||||
| SpreadsheetMatchedSelectOptionsColumn;
|
||||
onSubChange: (val: string, index: number, option: string) => void;
|
||||
| SpreadsheetMatchedSelectColumn<T>
|
||||
| SpreadsheetMatchedSelectOptionsColumn<T>;
|
||||
onSubChange: (val: T, index: number, option: string) => void;
|
||||
placeholder: string;
|
||||
selectedOption?:
|
||||
| SpreadsheetMatchedOptions
|
||||
| Partial<SpreadsheetMatchedOptions>;
|
||||
| SpreadsheetMatchedOptions<T>
|
||||
| Partial<SpreadsheetMatchedOptions<T>>;
|
||||
}
|
||||
|
||||
export const SubMatchingSelectRowRightDropdown = ({
|
||||
export const SubMatchingSelectRowRightDropdown = <T extends string>({
|
||||
option,
|
||||
column,
|
||||
onSubChange,
|
||||
placeholder,
|
||||
}: SubMatchingSelectRowRightDropdownProps) => {
|
||||
}: SubMatchingSelectRowRightDropdownProps<T>) => {
|
||||
const dropdownId = `sub-matching-select-dropdown-${option.entry}`;
|
||||
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
|
||||
const { spreadsheetImportFields: fields } = useSpreadsheetImportInternal();
|
||||
const { fields } = useSpreadsheetImportInternal<T>();
|
||||
const options = getFieldOptions(fields, column.value) as SelectOption[];
|
||||
const value = options.find((opt) => opt.value === option.value);
|
||||
|
||||
const handleSelect = (selectedOption: SelectOption) => {
|
||||
onSubChange(selectedOption.value, column.index, option.entry ?? '');
|
||||
onSubChange(selectedOption.value as T, column.index, option.entry ?? '');
|
||||
closeDropdown(dropdownId);
|
||||
};
|
||||
|
||||
|
||||
+10
-10
@@ -6,7 +6,7 @@ import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpre
|
||||
import { suggestedFieldsByColumnHeaderState } from '@/spreadsheet-import/steps/components/MatchColumnsStep/components/states/suggestedFieldsByColumnHeaderState';
|
||||
import { SpreadsheetColumnType } from '@/spreadsheet-import/types/SpreadsheetColumnType';
|
||||
import { SpreadsheetColumns } from '@/spreadsheet-import/types/SpreadsheetColumns';
|
||||
import { spreadsheetImportBuildFieldOptions } from '@/spreadsheet-import/utils/spreadsheetImportBuildFieldOptions';
|
||||
import { spreadsheetBuildFieldOptions } from '@/spreadsheet-import/utils/spreadsheetBuildFieldOptions';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { IconForbid } from 'twenty-ui/display';
|
||||
@@ -25,18 +25,18 @@ const StyledErrorMessage = styled.span`
|
||||
margin-top: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
type TemplateColumnProps = {
|
||||
columns: SpreadsheetColumns;
|
||||
type TemplateColumnProps<T extends string> = {
|
||||
columns: SpreadsheetColumns<string>;
|
||||
columnIndex: number;
|
||||
onChange: (val: string, index: number) => void;
|
||||
onChange: (val: T, index: number) => void;
|
||||
};
|
||||
|
||||
export const TemplateColumn = ({
|
||||
export const TemplateColumn = <T extends string>({
|
||||
columns,
|
||||
columnIndex,
|
||||
onChange,
|
||||
}: TemplateColumnProps) => {
|
||||
const { spreadsheetImportFields: fields } = useSpreadsheetImportInternal();
|
||||
}: TemplateColumnProps<T>) => {
|
||||
const { fields } = useSpreadsheetImportInternal<T>();
|
||||
const suggestedFieldsByColumnHeader = useRecoilValue(
|
||||
suggestedFieldsByColumnHeaderState,
|
||||
);
|
||||
@@ -46,8 +46,8 @@ export const TemplateColumn = ({
|
||||
|
||||
const { t } = useLingui();
|
||||
|
||||
const fieldOptions = spreadsheetImportBuildFieldOptions(fields, columns);
|
||||
const suggestedFieldOptions = spreadsheetImportBuildFieldOptions(
|
||||
const fieldOptions = spreadsheetBuildFieldOptions(fields, columns);
|
||||
const suggestedFieldOptions = spreadsheetBuildFieldOptions(
|
||||
suggestedFieldsByColumnHeader[column.header] ?? [],
|
||||
columns,
|
||||
);
|
||||
@@ -74,7 +74,7 @@ export const TemplateColumn = ({
|
||||
<MatchColumnToFieldSelect
|
||||
placeholder={t`Select column...`}
|
||||
value={isIgnored ? ignoreValue : selectValue}
|
||||
onChange={(value) => onChange(value?.value as string, column.index)}
|
||||
onChange={(value) => onChange(value?.value as T, column.index)}
|
||||
options={selectOptions}
|
||||
suggestedOptions={suggestedFieldOptions}
|
||||
columnIndex={column.index.toString()}
|
||||
|
||||
+9
-9
@@ -11,9 +11,9 @@ import { useState } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { AnimatedExpandableContainer } from 'twenty-ui/layout';
|
||||
|
||||
const getExpandableContainerTitle = (
|
||||
fields: SpreadsheetImportFields,
|
||||
column: SpreadsheetColumn,
|
||||
const getExpandableContainerTitle = <T extends string>(
|
||||
fields: SpreadsheetImportFields<T>,
|
||||
column: SpreadsheetColumn<T>,
|
||||
) => {
|
||||
const fieldLabel = fields.find(
|
||||
(field) => 'value' in column && field.key === column.value,
|
||||
@@ -25,10 +25,10 @@ const getExpandableContainerTitle = (
|
||||
} Unmatched)`;
|
||||
};
|
||||
|
||||
type UnmatchColumnProps = {
|
||||
columns: SpreadsheetColumns;
|
||||
type UnmatchColumnProps<T extends string> = {
|
||||
columns: SpreadsheetColumns<T>;
|
||||
columnIndex: number;
|
||||
onSubChange: (val: string, index: number, option: string) => void;
|
||||
onSubChange: (val: T, index: number, option: string) => void;
|
||||
};
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
@@ -44,12 +44,12 @@ const StyledContentWrapper = styled.div`
|
||||
padding-bottom: ${({ theme }) => theme.spacing(4)};
|
||||
`;
|
||||
|
||||
export const UnmatchColumn = ({
|
||||
export const UnmatchColumn = <T extends string>({
|
||||
columns,
|
||||
columnIndex,
|
||||
onSubChange,
|
||||
}: UnmatchColumnProps) => {
|
||||
const { spreadsheetImportFields: fields } = useSpreadsheetImportInternal();
|
||||
}: UnmatchColumnProps<T>) => {
|
||||
const { fields } = useSpreadsheetImportInternal<T>();
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
const column = columns[columnIndex];
|
||||
const isSelect = 'matchedOptions' in column;
|
||||
|
||||
+4
-4
@@ -29,15 +29,15 @@ const StyledExample = styled.span`
|
||||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
type UserTableColumnProps = {
|
||||
column: SpreadsheetColumn;
|
||||
type UserTableColumnProps<T extends string> = {
|
||||
column: SpreadsheetColumn<T>;
|
||||
importedRow: ImportedRow;
|
||||
};
|
||||
|
||||
export const UserTableColumn = ({
|
||||
export const UserTableColumn = <T extends string>({
|
||||
column,
|
||||
importedRow,
|
||||
}: UserTableColumnProps) => {
|
||||
}: UserTableColumnProps<T>) => {
|
||||
const { header } = column;
|
||||
const firstDefinedValue = importedRow.find(isDefined);
|
||||
|
||||
|
||||
+5
-5
@@ -5,18 +5,18 @@ import { atom, selectorFamily } from 'recoil';
|
||||
|
||||
export const matchColumnsState = atom({
|
||||
key: 'MatchColumnsState',
|
||||
default: [] as SpreadsheetColumns,
|
||||
default: [] as SpreadsheetColumns<string>,
|
||||
});
|
||||
|
||||
export const initialComputedColumnsSelector = selectorFamily<
|
||||
SpreadsheetColumns,
|
||||
SpreadsheetColumns<string>,
|
||||
ImportedRow
|
||||
>({
|
||||
key: 'initialComputedColumnsSelector',
|
||||
get:
|
||||
(headerValues: ImportedRow) =>
|
||||
({ get }) => {
|
||||
const currentState = get(matchColumnsState) as SpreadsheetColumns;
|
||||
const currentState = get(matchColumnsState) as SpreadsheetColumns<string>;
|
||||
if (currentState.length === 0) {
|
||||
// Do not remove spread, it indexes empty array elements, otherwise map() skips over them
|
||||
const initialState = ([...headerValues] as string[]).map(
|
||||
@@ -26,7 +26,7 @@ export const initialComputedColumnsSelector = selectorFamily<
|
||||
header: value ?? '',
|
||||
}),
|
||||
);
|
||||
return initialState as SpreadsheetColumns;
|
||||
return initialState as SpreadsheetColumns<string>;
|
||||
} else {
|
||||
return currentState;
|
||||
}
|
||||
@@ -34,6 +34,6 @@ export const initialComputedColumnsSelector = selectorFamily<
|
||||
set:
|
||||
() =>
|
||||
({ set }, newValue) => {
|
||||
set(matchColumnsState, newValue as SpreadsheetColumns);
|
||||
set(matchColumnsState, newValue as SpreadsheetColumns<string>);
|
||||
},
|
||||
});
|
||||
|
||||
+1
-1
@@ -3,5 +3,5 @@ import { createState } from 'twenty-ui/utilities';
|
||||
|
||||
export const suggestedFieldsByColumnHeaderState = createState({
|
||||
key: 'suggestedFieldsByColumnHeaderState',
|
||||
defaultValue: {} as Record<string, SpreadsheetImportField[]>,
|
||||
defaultValue: {} as Record<string, SpreadsheetImportField<string>[]>,
|
||||
});
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
import styled from '@emotion/styled';
|
||||
// @ts-expect-error // Todo: remove usage of react-data-grid
|
||||
import { Column } from 'react-data-grid';
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
import { SpreadsheetImportFields } from '@/spreadsheet-import/types';
|
||||
import { AppTooltip } from 'twenty-ui/display';
|
||||
|
||||
const StyledHeaderContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const StyledHeaderLabel = styled.span`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
`;
|
||||
|
||||
const StyledDefaultContainer = styled.div`
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
`;
|
||||
|
||||
export const generateColumns = <T extends string>(
|
||||
fields: SpreadsheetImportFields<T>,
|
||||
) =>
|
||||
fields.map(
|
||||
(column): Column<any> => ({
|
||||
key: column.key,
|
||||
name: column.label,
|
||||
minWidth: 150,
|
||||
headerRenderer: () => (
|
||||
<StyledHeaderContainer>
|
||||
<StyledHeaderLabel id={`${column.key}`}>
|
||||
{column.label}
|
||||
</StyledHeaderLabel>
|
||||
{column.description &&
|
||||
createPortal(
|
||||
<AppTooltip
|
||||
anchorSelect={`#${column.key}`}
|
||||
place="top"
|
||||
content={column.description}
|
||||
/>,
|
||||
document.body,
|
||||
)}
|
||||
</StyledHeaderContainer>
|
||||
),
|
||||
formatter: ({ row }: any) => (
|
||||
<StyledDefaultContainer>{row[column.key]}</StyledDefaultContainer>
|
||||
),
|
||||
}),
|
||||
);
|
||||
+3
-4
@@ -1,6 +1,5 @@
|
||||
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
|
||||
import { spreadsheetImportFilterAvailableFieldMetadataItems } from '@/object-record/spreadsheet-import/utils/spreadsheetImportFilterAvailableFieldMetadataItems';
|
||||
import { getCompositeSubFieldLabelWithFieldLabel } from '@/object-record/spreadsheet-import/utils/spreadsheetImportGetCompositeSubFieldLabelWithFieldLabel';
|
||||
import { spreadsheetImportFilterAvailableFieldMetadataItems } from '@/object-record/spreadsheet-import/utils/spreadsheetImportFilterAvailableFieldMetadataItems.ts';
|
||||
import { SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsCompositeFieldTypeConfigs';
|
||||
import { SETTINGS_NON_COMPOSITE_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsNonCompositeFieldTypeConfigs';
|
||||
import { escapeCSVValue } from '@/spreadsheet-import/utils/escapeCSVValue';
|
||||
@@ -59,8 +58,8 @@ export const useDownloadFakeRecords = () => {
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[field.type].exampleValues;
|
||||
|
||||
headerRow.push(
|
||||
...subFields.map(({ subFieldLabel }) =>
|
||||
getCompositeSubFieldLabelWithFieldLabel(field, subFieldLabel),
|
||||
...subFields.map(
|
||||
({ subFieldLabel }) => `${field.label} / ${subFieldLabel}`,
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
+17
-24
@@ -1,6 +1,5 @@
|
||||
import { SpreadsheetImportTable } from '@/spreadsheet-import/components/SpreadsheetImportTable';
|
||||
import { StepNavigationButton } from '@/spreadsheet-import/components/StepNavigationButton';
|
||||
import { useHideStepBar } from '@/spreadsheet-import/hooks/useHideStepBar';
|
||||
import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpreadsheetImportInternal';
|
||||
import { SpreadsheetImportStep } from '@/spreadsheet-import/steps/types/SpreadsheetImportStep';
|
||||
import { SpreadsheetImportStepType } from '@/spreadsheet-import/steps/types/SpreadsheetImportStepType';
|
||||
@@ -92,36 +91,30 @@ const StyledNoRowsWithErrorsContainer = styled.div`
|
||||
margin: auto 0;
|
||||
`;
|
||||
|
||||
type ValidationStepProps = {
|
||||
initialData: ImportedStructuredRow[];
|
||||
importedColumns: SpreadsheetColumns;
|
||||
type ValidationStepProps<T extends string> = {
|
||||
initialData: ImportedStructuredRow<T>[];
|
||||
importedColumns: SpreadsheetColumns<string>;
|
||||
file: File;
|
||||
onBack: () => void;
|
||||
setCurrentStepState: Dispatch<SetStateAction<SpreadsheetImportStep>>;
|
||||
};
|
||||
|
||||
export const ValidationStep = ({
|
||||
export const ValidationStep = <T extends string>({
|
||||
initialData,
|
||||
importedColumns,
|
||||
file,
|
||||
setCurrentStepState,
|
||||
onBack,
|
||||
}: ValidationStepProps) => {
|
||||
const hideStepBar = useHideStepBar();
|
||||
}: ValidationStepProps<T>) => {
|
||||
const { enqueueDialog } = useDialogManager();
|
||||
const {
|
||||
spreadsheetImportFields: fields,
|
||||
onClose,
|
||||
onSubmit,
|
||||
rowHook,
|
||||
tableHook,
|
||||
} = useSpreadsheetImportInternal();
|
||||
const { fields, onClose, onSubmit, rowHook, tableHook } =
|
||||
useSpreadsheetImportInternal<T>();
|
||||
|
||||
const [data, setData] = useState<
|
||||
(ImportedStructuredRow & ImportedStructuredRowMetadata)[]
|
||||
(ImportedStructuredRow<T> & ImportedStructuredRowMetadata)[]
|
||||
>(
|
||||
useMemo(
|
||||
() => addErrorsAndRunHooks(initialData, fields, rowHook, tableHook),
|
||||
() => addErrorsAndRunHooks<T>(initialData, fields, rowHook, tableHook),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[],
|
||||
),
|
||||
@@ -133,7 +126,7 @@ export const ValidationStep = ({
|
||||
|
||||
const updateData = useCallback(
|
||||
(rows: typeof data) => {
|
||||
setData(addErrorsAndRunHooks(rows, fields, rowHook, tableHook));
|
||||
setData(addErrorsAndRunHooks<T>(rows, fields, rowHook, tableHook));
|
||||
},
|
||||
[setData, rowHook, tableHook, fields],
|
||||
);
|
||||
@@ -212,7 +205,8 @@ export const ValidationStep = ({
|
||||
}, [data, filterByErrors]);
|
||||
|
||||
const rowKeyGetter = useCallback(
|
||||
(row: ImportedStructuredRow & ImportedStructuredRowMetadata) => row.__index,
|
||||
(row: ImportedStructuredRow<T> & ImportedStructuredRowMetadata) =>
|
||||
row.__index,
|
||||
[],
|
||||
);
|
||||
|
||||
@@ -224,29 +218,28 @@ export const ValidationStep = ({
|
||||
for (const key in __errors) {
|
||||
if (__errors[key].level === 'error') {
|
||||
acc.invalidStructuredRows.push(
|
||||
values as unknown as ImportedStructuredRow,
|
||||
values as unknown as ImportedStructuredRow<T>,
|
||||
);
|
||||
return acc;
|
||||
}
|
||||
}
|
||||
}
|
||||
acc.validStructuredRows.push(
|
||||
values as unknown as ImportedStructuredRow,
|
||||
values as unknown as ImportedStructuredRow<T>,
|
||||
);
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
validStructuredRows: [] as ImportedStructuredRow[],
|
||||
invalidStructuredRows: [] as ImportedStructuredRow[],
|
||||
validStructuredRows: [] as ImportedStructuredRow<T>[],
|
||||
invalidStructuredRows: [] as ImportedStructuredRow<T>[],
|
||||
allStructuredRows: data,
|
||||
} satisfies SpreadsheetImportImportValidationResult,
|
||||
} satisfies SpreadsheetImportImportValidationResult<T>,
|
||||
);
|
||||
|
||||
setCurrentStepState({
|
||||
type: SpreadsheetImportStepType.importData,
|
||||
recordsToImportCount: calculatedData.validStructuredRows.length,
|
||||
});
|
||||
hideStepBar();
|
||||
|
||||
await onSubmit(calculatedData, file);
|
||||
onClose();
|
||||
|
||||
+7
-7
@@ -71,9 +71,9 @@ const formatSafeId = (columnKey: string) => {
|
||||
return camelCase(columnKey.replace('(', '').replace(')', ''));
|
||||
};
|
||||
|
||||
export const generateColumns = (
|
||||
fields: SpreadsheetImportFields,
|
||||
): Column<ImportedStructuredRow & ImportedStructuredRowMetadata>[] => [
|
||||
export const generateColumns = <T extends string>(
|
||||
fields: SpreadsheetImportFields<T>,
|
||||
): Column<ImportedStructuredRow<T> & ImportedStructuredRowMetadata>[] => [
|
||||
{
|
||||
key: SELECT_COLUMN_KEY,
|
||||
name: '',
|
||||
@@ -108,7 +108,7 @@ export const generateColumns = (
|
||||
...fields.map(
|
||||
(
|
||||
column,
|
||||
): Column<ImportedStructuredRow & ImportedStructuredRowMetadata> => ({
|
||||
): Column<ImportedStructuredRow<T> & ImportedStructuredRowMetadata> => ({
|
||||
key: column.key,
|
||||
name: column.label,
|
||||
minWidth: 150,
|
||||
@@ -132,7 +132,7 @@ export const generateColumns = (
|
||||
editable: column.fieldType.type !== 'checkbox',
|
||||
// Todo: remove usage of react-data-grid
|
||||
editor: ({ row, onRowChange, onClose }: any) => {
|
||||
const columnKey = column.key as keyof (ImportedStructuredRow &
|
||||
const columnKey = column.key as keyof (ImportedStructuredRow<T> &
|
||||
ImportedStructuredRowMetadata);
|
||||
let component;
|
||||
|
||||
@@ -166,7 +166,7 @@ export const generateColumns = (
|
||||
},
|
||||
// Todo: remove usage of react-data-grid
|
||||
formatter: ({ row, onRowChange }: { row: any; onRowChange: any }) => {
|
||||
const columnKey = column.key as keyof (ImportedStructuredRow &
|
||||
const columnKey = column.key as keyof (ImportedStructuredRow<T> &
|
||||
ImportedStructuredRowMetadata);
|
||||
let component;
|
||||
|
||||
@@ -197,7 +197,7 @@ export const generateColumns = (
|
||||
id={formatSafeId(`${columnKey}-${row.__index}`)}
|
||||
>
|
||||
{column.fieldType.options.find(
|
||||
(option) => option.value === row[columnKey],
|
||||
(option) => option.value === row[columnKey as T],
|
||||
)?.label || null}
|
||||
</StyledDefaultContainer>
|
||||
);
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ export type SpreadsheetImportStep =
|
||||
| {
|
||||
type: SpreadsheetImportStepType.validateData;
|
||||
data: any[];
|
||||
importedColumns: SpreadsheetColumns;
|
||||
importedColumns: SpreadsheetColumns<string>;
|
||||
}
|
||||
| {
|
||||
type: SpreadsheetImportStepType.loading;
|
||||
|
||||
Reference in New Issue
Block a user