#
luxiaotao1123
2024-09-19 baf8c53a9d798861451a68620cdb946083d5c8a1
#
3个文件已修改
3个文件已添加
2 文件已重命名
164 ■■■■ 已修改文件
zy-acs-flow/package-lock.json 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/package.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/code/CodeList.jsx 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/code/importTemp.csv 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/code/useCodeImport.jsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/components/ImportButton.jsx 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/components/ImportModal.jsx 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/components/usePapaParse.jsx 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/package-lock.json
@@ -12,6 +12,7 @@
        "@mui/x-tree-view": "^7.16.0",
        "axios": "^1.7.4",
        "date-fns": "^3.6.0",
        "papaparse": "^5.4.1",
        "pixi.js": "^7.4.0",
        "react": "^18.3.0",
        "react-admin": "^5.1.0",
@@ -4818,6 +4819,11 @@
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/papaparse": {
      "version": "5.4.1",
      "resolved": "https://registry.npmmirror.com/papaparse/-/papaparse-5.4.1.tgz",
      "integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw=="
    },
    "node_modules/parent-module": {
      "version": "1.0.1",
      "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz",
zy-acs-flow/package.json
@@ -17,6 +17,7 @@
    "axios": "^1.7.4",
    "date-fns": "^3.6.0",
    "pixi.js": "^7.4.0",
    "papaparse": "^5.4.1",
    "react": "^18.3.0",
    "react-admin": "^5.1.0",
    "react-dom": "^18.3.0",
zy-acs-flow/src/page/code/CodeList.jsx
@@ -42,7 +42,10 @@
import MyField from "../components/MyField";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE } from '@/config/setting';
import * as Common from '@/utils/common';
import { ImportButton } from './ImportButton'
import { ImportButton } from '../components/ImportButton'
import { useCodeImport } from './useCodeImport';
import * as sampleCsv from './importTemp.csv?raw';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
@@ -112,7 +115,7 @@
                        <FilterButton />
                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
                        <SelectColumnsButton preferenceKey='code' />
                        <ImportButton />
                        <ImportButton sampleCsv={sampleCsv} useCodeImport={useCodeImport} />
                        <MyExportButton />
                    </TopToolbar>
                )}
zy-acs-flow/src/page/code/importTemp.csv
New file
@@ -0,0 +1,4 @@
first_name,last_name,gender,title,company,email,phone_1_number,phone_1_type,phone_2_number,phone_2_type,background,first_seen,last_seen,has_newsletter,status,tags,linkedin_url
John,Doe,male,Sales Executive,Acme,john@doe.example,659-980-2015,work,740.645.3807,home,,2024-07-01,2024-07-01T11:54:49.950Z,FALSE,in-contract,"influencer, developer",https://www.linkedin.com/in/johndoe
Jane,Doe,female,Designer,Acme,jane@doe.example,659-980-2020,work,740.647.3802,home,,2024-07-01,2024-07-01T11:54:49.950Z,FALSE,in-contract,"UI, design",https://www.linkedin.com/in/janedoe
Camille,Brown,nonbinary,Accountant,Atomic Corp,person@doe.example,659-910-3010,work,740.698.3752,home,,2024-07-01,2024-07-01T11:54:49.950Z,FALSE,in-contract,"payroll, accountant",,
zy-acs-flow/src/page/code/useCodeImport.jsx
New file
@@ -0,0 +1,14 @@
import { useCallback, useMemo } from 'react';
import { useDataProvider, useGetIdentity } from 'react-admin';
export function useCodeImport() {
    const processBatch = useCallback(async (batch) => {
        console.log(batch);
    }, []);
    return {
        processBatch,
    };
}
zy-acs-flow/src/page/components/ImportButton.jsx
File was renamed from zy-acs-flow/src/page/code/ImportButton.jsx
@@ -1,9 +1,9 @@
import UploadIcon from '@mui/icons-material/Upload';
import { useState } from 'react';
import { Button } from 'react-admin';
// import { ImportModal } from './ImportModal';
import { ImportModal } from './ImportModal';
export const ImportButton = () => {
export const ImportButton = (props) => {
    const [modalOpen, setModalOpen] = useState(false);
    const handleOpenModal = () => {
@@ -13,7 +13,7 @@
    const handleCloseModal = () => {
        setModalOpen(false);
    };
    return (
        <>
            <Button
@@ -22,7 +22,7 @@
                onClick={handleOpenModal}
            />
            {/* <ImportModal open={modalOpen} onClose={handleCloseModal} /> */}
            <ImportModal open={modalOpen} onClose={handleCloseModal} {...props} />
        </>
    );
};
zy-acs-flow/src/page/components/ImportModal.jsx
File was renamed from zy-acs-flow/src/page/code/ImportModal.jsx
@@ -1,3 +1,4 @@
import { useEffect, useState } from 'react';
import { Box, CircularProgress, Stack, Typography } from '@mui/material';
import Alert from '@mui/material/Alert';
import Dialog from '@mui/material/Dialog';
@@ -14,20 +15,16 @@
    useRefresh,
} from 'react-admin';
import { Link } from 'react-router-dom';
import { DialogCloseButton } from '../misc/DialogCloseButton';
import { usePapaParse } from '../misc/usePapaParse';
import { ContactImportSchema, useContactImport } from './useContactImport';
import DialogCloseButton from './DialogCloseButton';
import { usePapaParse } from './usePapaParse';
import { MouseEvent, useEffect, useState } from 'react';
import * as sampleCsv from './contacts_export.csv?raw';
const SAMPLE_URL = `data:text/csv;name=crm_contacts_sample.csv;charset=utf-8,${encodeURIComponent(sampleCsv.default)}`;
export function ImportModal({ open, onClose }) {
export function ImportModal({ open, onClose, sampleCsv, useCodeImport }) {
    const refresh = useRefresh();
    const { processBatch } = useContactImport();
    const { importer, parseCsv, reset } = usePapaParse<ContactImportSchema>({
    const SAMPLE_URL = `data:text/csv;name=crm_contacts_sample.csv;charset=utf-8,${encodeURIComponent(sampleCsv.default)}`;
    const { processBatch } = useCodeImport();
    const { importer, parseCsv, reset } = usePapaParse({
        batchSize: 10,
        processBatch,
    });
zy-acs-flow/src/page/components/usePapaParse.jsx
New file
@@ -0,0 +1,103 @@
import * as Papa from 'papaparse';
import { useCallback, useMemo, useRef, useState } from 'react';
export function usePapaParse({ batchSize = 10, processBatch }) {
    const importIdRef = useRef(0);
    const [importer, setImporter] = useState({
        state: 'idle',
    });
    const reset = useCallback(() => {
        setImporter({
            state: 'idle',
        });
        importIdRef.current += 1;
    }, []);
    const parseCsv = useCallback((file) => {
        setImporter({
            state: 'parsing',
        });
        const importId = importIdRef.current;
        Papa.parse(file, {
            header: true,
            skipEmptyLines: true,
            async complete(results) {
                if (importIdRef.current !== importId) {
                    return;
                }
                setImporter({
                    state: 'running',
                    rowCount: results.data.length,
                    errorCount: results.errors.length,
                    importCount: 0,
                    remainingTime: null,
                });
                let totalTime = 0;
                for (let i = 0; i < results.data.length; i += batchSize) {
                    if (importIdRef.current !== importId) {
                        return;
                    }
                    const batch = results.data.slice(i, i + batchSize);
                    try {
                        const start = Date.now();
                        await processBatch(batch);
                        totalTime += Date.now() - start;
                        const meanTime = totalTime / (i + batch.length);
                        setImporter(previous => {
                            if (previous.state === 'running') {
                                const importCount =
                                    previous.importCount + batch.length;
                                return {
                                    ...previous,
                                    importCount,
                                    remainingTime:
                                        meanTime *
                                        (results.data.length - importCount),
                                };
                            }
                            return previous;
                        });
                    } catch (error) {
                        console.error('Failed to import batch', error);
                        setImporter(previous =>
                            previous.state === 'running'
                                ? {
                                    ...previous,
                                    errorCount:
                                        previous.errorCount +
                                        batch.length,
                                }
                                : previous
                        );
                    }
                }
                setImporter(previous =>
                    previous.state === 'running'
                        ? {
                            ...previous,
                            state: 'complete',
                            remainingTime: null,
                        }
                        : previous
                );
            },
            error(error) {
                setImporter({
                    state: 'error',
                    error,
                });
            },
            dynamicTyping: true,
        });
    }, [batchSize, processBatch]);
    return useMemo(() => ({ importer, parseCsv, reset, }), [importer, parseCsv, reset]);
}