mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 13:20:31 +00:00
fix: import resource imporements
This commit is contained in:
25
packages/webapp/src/containers/Accounts/AccountsImport.tsx
Normal file
25
packages/webapp/src/containers/Accounts/AccountsImport.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
// @ts-nocheck
|
||||
import { DashboardInsider } from '@/components';
|
||||
import { ImportView } from '../Import/ImportView';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
export default function AccountsImport() {
|
||||
const history = useHistory();
|
||||
|
||||
const handleCancelBtnClick = () => {
|
||||
history.push('/accounts');
|
||||
};
|
||||
const handleImportSuccess = () => {
|
||||
history.push('/accounts');
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardInsider name={'import-accounts'}>
|
||||
<ImportView
|
||||
resource={'accounts'}
|
||||
onCancelClick={handleCancelBtnClick}
|
||||
onImportSuccess={handleImportSuccess}
|
||||
/>
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
NavbarDivider,
|
||||
Alignment,
|
||||
} from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import {
|
||||
Icon,
|
||||
DashboardActionsBar,
|
||||
@@ -48,6 +49,8 @@ function AccountTransactionsActionsBar({
|
||||
const addMoneyInOptions = useMemo(() => getAddMoneyInOptions(), []);
|
||||
const addMoneyOutOptions = useMemo(() => getAddMoneyOutOptions(), []);
|
||||
|
||||
const history = useHistory();
|
||||
|
||||
// Handle money in form
|
||||
const handleMoneyInFormTransaction = (account) => {
|
||||
openDialog('money-in', {
|
||||
@@ -64,6 +67,11 @@ function AccountTransactionsActionsBar({
|
||||
account_name: account.name,
|
||||
});
|
||||
};
|
||||
// Handle import button click.
|
||||
const handleImportBtnClick = () => {
|
||||
history.push(`/cashflow-accounts/${accountId}/import`);
|
||||
};
|
||||
|
||||
// Refresh cashflow infinity transactions hook.
|
||||
const { refresh } = useRefreshCashflowTransactionsInfinity();
|
||||
|
||||
@@ -106,6 +114,7 @@ function AccountTransactionsActionsBar({
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon="file-import-16" iconSize={16} />}
|
||||
text={<T id={'import'} />}
|
||||
onClick={handleImportBtnClick}
|
||||
/>
|
||||
<NavbarDivider />
|
||||
<DashboardRowsHeightButton
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// @ts-nocheck
|
||||
import { DashboardInsider } from '@/components';
|
||||
import { ImportView } from '@/containers/Import/ImportView';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
|
||||
export default function ImportUncategorizedTransactions() {
|
||||
const history = useHistory();
|
||||
const params = useParams();
|
||||
|
||||
const handleImportSuccess = () => {
|
||||
history.push(
|
||||
`/cashflow-accounts/${params.id}/transactions?filter=uncategorized`,
|
||||
);
|
||||
};
|
||||
const handleCnacelBtnClick = () => {
|
||||
history.push(
|
||||
`/cashflow-accounts/${params.id}/transactions?filter=uncategorized`,
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardInsider name={'import-uncategorized-bank-transactions'}>
|
||||
<ImportView
|
||||
resource={'uncategorized_cashflow_transaction'}
|
||||
params={{ accountId: params.id }}
|
||||
onImportSuccess={handleImportSuccess}
|
||||
onCancelClick={handleCnacelBtnClick}
|
||||
sampleFileName={'sample_bank_transactions'}
|
||||
/>
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
25
packages/webapp/src/containers/Customers/CustomersImport.tsx
Normal file
25
packages/webapp/src/containers/Customers/CustomersImport.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
// @ts-nocheck
|
||||
import { DashboardInsider } from '@/components';
|
||||
import { ImportView } from '../Import/ImportView';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
export default function CustomersImport() {
|
||||
const history = useHistory();
|
||||
|
||||
const handleImportSuccess = () => {
|
||||
history.push('/customers');
|
||||
};
|
||||
const handleCancelBtnClick = () => {
|
||||
history.push('/customers');
|
||||
};
|
||||
return (
|
||||
<DashboardInsider name={'import-customers'}>
|
||||
<ImportView
|
||||
resource={'customers'}
|
||||
onImportSuccess={handleImportSuccess}
|
||||
onCancelClick={handleCancelBtnClick}
|
||||
exampleTitle="Customers Example"
|
||||
/>
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
@@ -95,6 +95,11 @@ function CustomerActionsBar({
|
||||
addSetting('customers', 'tableSize', size);
|
||||
};
|
||||
|
||||
// Handle import button click.
|
||||
const handleImportBtnClick = () => {
|
||||
history.push('/customers/import');
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardActionsBar>
|
||||
<NavbarGroup>
|
||||
@@ -142,6 +147,7 @@ function CustomerActionsBar({
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon="file-import-16" iconSize={16} />}
|
||||
onClick={handleImportBtnClick}
|
||||
text={<T id={'import'} />}
|
||||
/>
|
||||
<Button
|
||||
|
||||
@@ -9,9 +9,11 @@ import { useImportFileContext } from './ImportFileProvider';
|
||||
|
||||
export function ImportFileUploadFooterActions() {
|
||||
const { isSubmitting } = useFormikContext();
|
||||
const { setStep } = useImportFileContext();
|
||||
const { onCancelClick } = useImportFileContext();
|
||||
|
||||
const handleCancelBtnClick = () => {};
|
||||
const handleCancelBtnClick = () => {
|
||||
onCancelClick && onCancelClick();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={clsx(CLASSES.PAGE_FORM_FLOATING_ACTIONS, styles.root)}>
|
||||
|
||||
@@ -7,33 +7,38 @@ import { ImportFileMappingForm } from './ImportFileMappingForm';
|
||||
import { EntityColumn, useImportFileContext } from './ImportFileProvider';
|
||||
import { CLASSES } from '@/constants';
|
||||
import { ImportFileContainer } from './ImportFileContainer';
|
||||
import styles from './ImportFileMapping.module.scss';
|
||||
import { ImportStepperStep } from './_types';
|
||||
import { ImportFileMapBootProvider } from './ImportFileMappingBoot';
|
||||
import styles from './ImportFileMapping.module.scss';
|
||||
|
||||
export function ImportFileMapping() {
|
||||
const { importId } = useImportFileContext();
|
||||
|
||||
return (
|
||||
<ImportFileMappingForm>
|
||||
<ImportFileContainer>
|
||||
<p>
|
||||
Review and map the column headers in your csv/xlsx file with the
|
||||
Bigcapital fields.
|
||||
</p>
|
||||
<ImportFileMapBootProvider importId={importId}>
|
||||
<ImportFileMappingForm>
|
||||
<ImportFileContainer>
|
||||
<p>
|
||||
Review and map the column headers in your csv/xlsx file with the
|
||||
Bigcapital fields.
|
||||
</p>
|
||||
|
||||
<table className={clsx('bp4-html-table', styles.table)}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className={styles.label}>Bigcapital Fields</th>
|
||||
<th className={styles.field}>Sheet Column Headers</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<ImportFileMappingFields />
|
||||
</tbody>
|
||||
</table>
|
||||
</ImportFileContainer>
|
||||
<table className={clsx('bp4-html-table', styles.table)}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className={styles.label}>Bigcapital Fields</th>
|
||||
<th className={styles.field}>Sheet Column Headers</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<ImportFileMappingFields />
|
||||
</tbody>
|
||||
</table>
|
||||
</ImportFileContainer>
|
||||
|
||||
<ImportFileMappingFloatingActions />
|
||||
</ImportFileMappingForm>
|
||||
<ImportFileMappingFloatingActions />
|
||||
</ImportFileMappingForm>
|
||||
</ImportFileMapBootProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -67,6 +72,7 @@ function ImportFileMappingFields() {
|
||||
</tr>
|
||||
);
|
||||
const columns = entityColumns.map(columnMapper);
|
||||
|
||||
return <>{columns}</>;
|
||||
}
|
||||
|
||||
@@ -81,7 +87,7 @@ function ImportFileMappingFloatingActions() {
|
||||
return (
|
||||
<div className={clsx(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
||||
<Group spacing={10}>
|
||||
<Button onClick={handleCancelBtnClick}>Cancel</Button>
|
||||
<Button onClick={handleCancelBtnClick}>Back</Button>
|
||||
<Button type="submit" intent={Intent.PRIMARY} loading={isSubmitting}>
|
||||
Next
|
||||
</Button>
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { Spinner } from '@blueprintjs/core';
|
||||
import React, { createContext, useContext } from 'react';
|
||||
import { Box } from '@/components';
|
||||
import { useImportFileMeta } from '@/hooks/query/import';
|
||||
|
||||
interface ImportFileMapBootContextValue {}
|
||||
|
||||
const ImportFileMapBootContext = createContext<ImportFileMapBootContextValue>(
|
||||
{} as ImportFileMapBootContextValue,
|
||||
);
|
||||
|
||||
export const useImportFileMapBootContext = () => {
|
||||
const context = useContext<ImportFileMapBootContextValue>(
|
||||
ImportFileMapBootContext,
|
||||
);
|
||||
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'useImportFileMapBootContext must be used within an ImportFileMapBootProvider',
|
||||
);
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
||||
interface ImportFileMapBootProps {
|
||||
importId: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const ImportFileMapBootProvider = ({
|
||||
importId,
|
||||
children,
|
||||
}: ImportFileMapBootProps) => {
|
||||
const {
|
||||
data: importFile,
|
||||
isLoading: isImportFileLoading,
|
||||
isFetching: isImportFileFetching,
|
||||
} = useImportFileMeta(importId, {
|
||||
enabled: Boolean(importId),
|
||||
});
|
||||
|
||||
const value = {
|
||||
importFile,
|
||||
isImportFileLoading,
|
||||
isImportFileFetching,
|
||||
};
|
||||
return (
|
||||
<ImportFileMapBootContext.Provider value={value}>
|
||||
{isImportFileLoading ? (
|
||||
<Box style={{ padding: '2rem', textAlign: 'center' }}>
|
||||
<Spinner size={26} />
|
||||
</Box>
|
||||
) : (
|
||||
<>{children}</>
|
||||
)}
|
||||
</ImportFileMapBootContext.Provider>
|
||||
);
|
||||
};
|
||||
@@ -6,6 +6,8 @@ import { useImportFileContext } from './ImportFileProvider';
|
||||
import { useMemo } from 'react';
|
||||
import { isEmpty, lowerCase } from 'lodash';
|
||||
import { AppToaster } from '@/components';
|
||||
import { useImportFileMapBootContext } from './ImportFileMappingBoot';
|
||||
import { transformToForm } from '@/utils';
|
||||
|
||||
interface ImportFileMappingFormProps {
|
||||
children: React.ReactNode;
|
||||
@@ -58,10 +60,23 @@ const transformValueToReq = (value: ImportFileMappingFormValues) => {
|
||||
return { mapping };
|
||||
};
|
||||
|
||||
const transformResToFormValues = (value: { from: string; to: string }[]) => {
|
||||
return value?.reduce((acc, map) => {
|
||||
acc[map.to] = map.from;
|
||||
return acc;
|
||||
}, {});
|
||||
};
|
||||
|
||||
const useImportFileMappingInitialValues = () => {
|
||||
const { importFile } = useImportFileMapBootContext();
|
||||
const { entityColumns, sheetColumns } = useImportFileContext();
|
||||
|
||||
return useMemo(
|
||||
const initialResValues = useMemo(
|
||||
() => transformResToFormValues(importFile?.map || []),
|
||||
[importFile?.map],
|
||||
);
|
||||
|
||||
const initialValues = useMemo(
|
||||
() =>
|
||||
entityColumns.reduce((acc, { key, name }) => {
|
||||
const _name = lowerCase(name);
|
||||
@@ -75,4 +90,12 @@ const useImportFileMappingInitialValues = () => {
|
||||
}, {}),
|
||||
[entityColumns, sheetColumns],
|
||||
);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
...transformToForm(initialResValues, initialValues),
|
||||
...initialValues,
|
||||
}),
|
||||
[initialValues, initialResValues],
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// @ts-nocheck
|
||||
import { Button, Callout, Intent, Text } from '@blueprintjs/core';
|
||||
import clsx from 'classnames';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import {
|
||||
ImportFilePreviewBootProvider,
|
||||
useImportFilePreviewBootContext,
|
||||
@@ -144,12 +143,12 @@ function ImportFilePreviewUnmapped() {
|
||||
}
|
||||
|
||||
function ImportFilePreviewFloatingActions() {
|
||||
const { importId, setStep } = useImportFileContext();
|
||||
const { importId, setStep, onImportSuccess, onImportFailed } =
|
||||
useImportFileContext();
|
||||
const { importPreview } = useImportFilePreviewBootContext();
|
||||
const { mutateAsync: importFile, isLoading: isImportFileLoading } =
|
||||
useImportFileProcess();
|
||||
|
||||
const history = useHistory();
|
||||
const isValidToImport = importPreview?.createdCount > 0;
|
||||
|
||||
const handleSubmitBtn = () => {
|
||||
@@ -161,9 +160,11 @@ function ImportFilePreviewFloatingActions() {
|
||||
importPreview.createdCount
|
||||
} of ${10} has imported successfully.`,
|
||||
});
|
||||
history.push('/accounts');
|
||||
onImportSuccess && onImportSuccess();
|
||||
})
|
||||
.catch((error) => {});
|
||||
.catch((error) => {
|
||||
onImportFailed && onImportFailed();
|
||||
});
|
||||
};
|
||||
const handleCancelBtnClick = () => {
|
||||
setStep(ImportStepperStep.Mapping);
|
||||
|
||||
@@ -33,12 +33,36 @@ interface ImportFileContextValue {
|
||||
setImportId: Dispatch<SetStateAction<string>>;
|
||||
|
||||
resource: string;
|
||||
description?: string;
|
||||
params: Record<string, any>;
|
||||
onImportSuccess?: () => void;
|
||||
onImportFailed?: () => void;
|
||||
onCancelClick?: () => void;
|
||||
sampleFileName?: string;
|
||||
|
||||
exampleDownload?: boolean;
|
||||
exampleTitle?: string;
|
||||
exampleDescription?: string;
|
||||
}
|
||||
interface ImportFileProviderProps {
|
||||
resource: string;
|
||||
description?: string;
|
||||
params: Record<string, any>;
|
||||
onImportSuccess?: () => void;
|
||||
onImportFailed?: () => void;
|
||||
onCancelClick?: () => void;
|
||||
children: React.ReactNode;
|
||||
sampleFileName?: string;
|
||||
|
||||
exampleDownload?: boolean;
|
||||
exampleTitle?: string;
|
||||
exampleDescription?: string;
|
||||
}
|
||||
|
||||
const ExampleDescription =
|
||||
'You can download the sample file to obtain detailed information about the data fields used during the import.';
|
||||
const ExampleTitle = 'Table Example';
|
||||
|
||||
const ImportFileContext = createContext<ImportFileContextValue>(
|
||||
{} as ImportFileContextValue,
|
||||
);
|
||||
@@ -57,6 +81,16 @@ export const useImportFileContext = () => {
|
||||
export const ImportFileProvider = ({
|
||||
resource,
|
||||
children,
|
||||
description,
|
||||
params,
|
||||
onImportFailed,
|
||||
onImportSuccess,
|
||||
onCancelClick,
|
||||
sampleFileName,
|
||||
|
||||
exampleDownload = true,
|
||||
exampleTitle = ExampleTitle,
|
||||
exampleDescription = ExampleDescription,
|
||||
}: ImportFileProviderProps) => {
|
||||
const [sheetColumns, setSheetColumns] = useState<SheetColumn[]>([]);
|
||||
const [entityColumns, setEntityColumns] = useState<SheetColumn[]>([]);
|
||||
@@ -82,6 +116,18 @@ export const ImportFileProvider = ({
|
||||
setImportId,
|
||||
|
||||
resource,
|
||||
description,
|
||||
params,
|
||||
|
||||
onImportSuccess,
|
||||
onImportFailed,
|
||||
onCancelClick,
|
||||
|
||||
sampleFileName,
|
||||
|
||||
exampleDownload,
|
||||
exampleTitle,
|
||||
exampleDescription,
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -29,7 +29,7 @@ export function ImportFileUploadForm({
|
||||
formProps,
|
||||
}: ImportFileUploadFormProps) {
|
||||
const { mutateAsync: uploadImportFile } = useImportFileUpload();
|
||||
const { setStep, setSheetColumns, setEntityColumns, setImportId } =
|
||||
const { resource, params, setStep, setSheetColumns, setEntityColumns, setImportId } =
|
||||
useImportFileContext();
|
||||
|
||||
const handleSubmit = (
|
||||
@@ -41,7 +41,8 @@ export function ImportFileUploadForm({
|
||||
setSubmitting(true);
|
||||
const formData = new FormData();
|
||||
formData.append('file', values.file);
|
||||
formData.append('resource', 'Account');
|
||||
formData.append('resource', resource);
|
||||
formData.append('params', JSON.stringify(params));
|
||||
|
||||
uploadImportFile(formData)
|
||||
.then(({ data }) => {
|
||||
|
||||
@@ -1,22 +1,31 @@
|
||||
// @ts-nocheck
|
||||
import { Classes } from '@blueprintjs/core';
|
||||
import { Stack } from '@/components';
|
||||
import { ImportDropzone } from './ImportDropzone';
|
||||
import { ImportSampleDownload } from './ImportSampleDownload';
|
||||
import { ImportFileUploadForm } from './ImportFileUploadForm';
|
||||
import { ImportFileUploadFooterActions } from './ImportFileFooterActions';
|
||||
import { ImportFileContainer } from './ImportFileContainer';
|
||||
import { useImportFileContext } from './ImportFileProvider';
|
||||
|
||||
export function ImportFileUploadStep() {
|
||||
const { exampleDownload } = useImportFileContext();
|
||||
|
||||
return (
|
||||
<ImportFileUploadForm>
|
||||
<ImportFileContainer>
|
||||
<p style={{ marginBottom: 18 }}>
|
||||
Download a sample file and compare it to your import file to ensure
|
||||
you have the file perfect for the import.
|
||||
<p
|
||||
className={Classes.TEXT_MUTED}
|
||||
style={{ marginBottom: 18, lineHeight: 1.6 }}
|
||||
>
|
||||
Download a sample file and compare it with your import file to ensure
|
||||
it is properly formatted. It's not necessary for the columns to be in
|
||||
the same order, you can map them later.
|
||||
</p>
|
||||
|
||||
<Stack spacing={40}>
|
||||
<ImportDropzone />
|
||||
<ImportSampleDownload />
|
||||
{exampleDownload && <ImportSampleDownload />}
|
||||
</Stack>
|
||||
</ImportFileContainer>
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import { ImportStepper } from './ImportStepper';
|
||||
import { Box, DashboardInsider } from '@/components';
|
||||
import { ImportFileProvider } from './ImportFileProvider';
|
||||
import styles from './ImportPage.module.scss';
|
||||
|
||||
|
||||
export default function ImportPage() {
|
||||
return (
|
||||
<DashboardInsider>
|
||||
<Box className={styles.root}>
|
||||
<ImportFileProvider resource="account">
|
||||
<ImportStepper />
|
||||
</ImportFileProvider>
|
||||
</Box>
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
@@ -1,23 +1,64 @@
|
||||
// @ts-nocheck
|
||||
import { Box, Group } from '@/components';
|
||||
import { Button } from '@blueprintjs/core';
|
||||
import { AppToaster, Box, Group } from '@/components';
|
||||
import {
|
||||
Button,
|
||||
Intent,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Popover,
|
||||
PopoverInteractionKind,
|
||||
} from '@blueprintjs/core';
|
||||
import styles from './ImportSampleDownload.module.scss';
|
||||
import { useSampleSheetImport } from '@/hooks/query/import';
|
||||
import { useImportFileContext } from './ImportFileProvider';
|
||||
|
||||
export function ImportSampleDownload() {
|
||||
const { resource, sampleFileName, exampleTitle, exampleDescription } =
|
||||
useImportFileContext();
|
||||
const { mutateAsync: downloadSample } = useSampleSheetImport();
|
||||
|
||||
// Handle download button click.
|
||||
const handleDownloadBtnClick = (format) => () => {
|
||||
downloadSample({
|
||||
filename: sampleFileName || `sample-${resource}`,
|
||||
resource,
|
||||
format: format,
|
||||
})
|
||||
.then(() => {
|
||||
AppToaster.show({
|
||||
intent: Intent.SUCCESS,
|
||||
message: 'The sample sheet has been downloaded successfully.',
|
||||
});
|
||||
})
|
||||
.catch((error) => {});
|
||||
};
|
||||
|
||||
return (
|
||||
<Group className={styles.root} noWrap>
|
||||
<Box>
|
||||
<h3 className={styles.title}>Table Example</h3>
|
||||
<p className={styles.description}>
|
||||
Download a sample file and compare it to your import file to ensure
|
||||
you have the file perfect for the import.
|
||||
</p>
|
||||
<h3 className={styles.title}>{exampleTitle}</h3>
|
||||
<p className={styles.description}>{exampleDescription}</p>
|
||||
</Box>
|
||||
|
||||
<Box className={styles.buttonWrap}>
|
||||
<Button minimal outlined>
|
||||
Download File
|
||||
</Button>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem onClick={handleDownloadBtnClick('csv')} text={'CSV'} />
|
||||
<MenuItem
|
||||
onClick={handleDownloadBtnClick('xlsx')}
|
||||
text={'XLSX'}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
placement="bottom-start"
|
||||
minimal
|
||||
>
|
||||
<Button minimal outlined>
|
||||
Download File
|
||||
</Button>
|
||||
</Popover>
|
||||
</Box>
|
||||
</Group>
|
||||
);
|
||||
|
||||
28
packages/webapp/src/containers/Import/ImportView.tsx
Normal file
28
packages/webapp/src/containers/Import/ImportView.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
// @ts-nocheck
|
||||
import { ImportStepper } from './ImportStepper';
|
||||
import { Box } from '@/components';
|
||||
import { ImportFileProvider } from './ImportFileProvider';
|
||||
import styles from './ImportView.module.scss';
|
||||
|
||||
interface ImportViewProps {
|
||||
resource: string;
|
||||
description?: string;
|
||||
params: Record<string, any>;
|
||||
onImportSuccess?: () => void;
|
||||
onImportFailed?: () => void;
|
||||
onCancelClick?: () => void;
|
||||
sampleFileName?: string;
|
||||
exampleDownload?: boolean;
|
||||
exampleTitle?: string;
|
||||
exampleDescription?: string;
|
||||
}
|
||||
|
||||
export function ImportView({ ...props }: ImportViewProps) {
|
||||
return (
|
||||
<Box className={styles.root}>
|
||||
<ImportFileProvider {...props}>
|
||||
<ImportStepper />
|
||||
</ImportFileProvider>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
1
packages/webapp/src/containers/Import/index.ts
Normal file
1
packages/webapp/src/containers/Import/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './ImportView';
|
||||
11
packages/webapp/src/containers/Items/ItemsImportable.tsx
Normal file
11
packages/webapp/src/containers/Items/ItemsImportable.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
// @ts-nocheck
|
||||
import { DashboardInsider } from '@/components';
|
||||
import { ImportView } from '../Import/ImportView';
|
||||
|
||||
export default function ItemsImport() {
|
||||
return (
|
||||
<DashboardInsider name={'import-items'}>
|
||||
<ImportView resource={'items'} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
26
packages/webapp/src/containers/Vendors/VendorsImport.tsx
Normal file
26
packages/webapp/src/containers/Vendors/VendorsImport.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
// @ts-nocheck
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { DashboardInsider } from '@/components';
|
||||
import { ImportView } from '../Import/ImportView';
|
||||
|
||||
export default function VendorsImport() {
|
||||
const history = useHistory();
|
||||
|
||||
const handleImportSuccess = () => {
|
||||
history.push('/vendors');
|
||||
};
|
||||
const handleImportBtnClick = () => {
|
||||
history.push('/vendors');
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardInsider name={'import-vendors'}>
|
||||
<ImportView
|
||||
resource={'vendors'}
|
||||
onImportSuccess={handleImportSuccess}
|
||||
onCancelClick={handleImportBtnClick}
|
||||
exampleTitle='Vendors Example'
|
||||
/>
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
@@ -83,6 +83,10 @@ function VendorActionsBar({
|
||||
const handleTableRowSizeChange = (size) => {
|
||||
addSetting('vendors', 'tableSize', size);
|
||||
};
|
||||
// Handle import button success.
|
||||
const handleImportBtnSuccess = () => {
|
||||
history.push('/vendors/import');
|
||||
};
|
||||
return (
|
||||
<DashboardActionsBar>
|
||||
<NavbarGroup>
|
||||
@@ -128,6 +132,7 @@ function VendorActionsBar({
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon="file-import-16" iconSize={16} />}
|
||||
text={<T id={'import'} />}
|
||||
onClick={handleImportBtnSuccess}
|
||||
/>
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
|
||||
Reference in New Issue
Block a user