Skip to content

Commit

Permalink
fix: file state (#488)
Browse files Browse the repository at this point in the history
  • Loading branch information
hetao92 authored Feb 23, 2023
1 parent 9a69a4f commit eb4be97
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 83 deletions.
172 changes: 91 additions & 81 deletions app/pages/Import/FileList/UploadConfigModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import Icon from '@app/components/Icon';
import { useI18n } from '@vesoft-inc/i18n';
import { Button, Checkbox, Input, Modal, Table, Popconfirm, Dropdown } from 'antd';
import { v4 as uuidv4 } from 'uuid';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { usePapaParse } from 'react-papaparse';
import cls from 'classnames';
import { StudioFile } from '@app/interfaces/import';
import { CheckboxChangeEvent } from 'antd/lib/checkbox';
import { useBatchState } from '@app/utils';
import { useStore } from '@app/stores';
import { observer } from 'mobx-react-lite';
import { observer, useLocalObservable } from 'mobx-react-lite';
import { ExclamationCircleFilled } from '@ant-design/icons';
import { observable } from 'mobx';
import styles from './index.module.less';
interface IProps {
visible: boolean;
Expand All @@ -35,32 +35,32 @@ const UploadConfigModal = (props: IProps) => {
const { files } = useStore();
const { fileList, uploadFile } = files;
const { intl } = useI18n();
const { state, setState } = useBatchState({
const state = useLocalObservable(() => ({
data: [],
activeItem: null,
previewContent: [],
checkAll: false,
indeterminate: false,
loading: false,
uploading: false,
});
const { uploading, data, activeItem, previewContent, checkAll, indeterminate, loading } = state;
setState: (obj) => Object.assign(state, obj),
}), { data: observable.ref });
const { readRemoteFile } = usePapaParse();
useEffect(() => {
const { setState } = state;
visible && setState({ data: uploadList, activeItem: uploadList[0] });
}, [visible]);
useEffect(() => {
if (activeItem) {
readFile(activeItem);
}
}, [activeItem]);
const readFile = useCallback((file) => {
if(!file) return;
state.activeItem && readFile();
}, [state.activeItem]);
const readFile = useCallback(() => {
const { activeItem, setState } = state;
if(!activeItem) return;
setState({ loading: true });
const url = URL.createObjectURL(file);
const url = URL.createObjectURL(activeItem);
let content = [];
readRemoteFile(url, {
delimiter: file.delimiter,
delimiter: activeItem.delimiter,
download: true,
preview: 5,
worker: true,
Expand All @@ -73,52 +73,115 @@ const UploadConfigModal = (props: IProps) => {
}
});
}, []);

const onCheckAllChange = useCallback((e: CheckboxChangeEvent) => {
const { data, setState } = state;
const { checked } = e.target;
data.forEach(item => item.withHeader = checked);
setState({
checkAll: checked,
indeterminate: false,
data: [...data]
data: data.map(i => (i.withHeader = checked, i))
});
}, [data]);
}, []);

const updateItem = useCallback((e: CheckboxChangeEvent, item: StudioFile) => {
e.stopPropagation();
const { data, setState } = state;
const { checked } = e.target;
item.withHeader = checked;
const nextData = data.map(i => (i === item && (i.withHeader = checked), i));
const checkedNum = data.reduce((n, file) => n + (file.withHeader & 1), 0);
setState({
checkAll: checkedNum === data.length,
indeterminate: !!checkedNum && checkedNum < data.length,
data: nextData
});
}, [data]);
}, []);
const deletePreviewFile = useCallback((e: React.MouseEvent, index: number) => {
const { activeItem, data, setState, previewContent } = state;
e.stopPropagation();
const isActive = activeItem?.uid === data[index].uid;
const newData = data.filter((_, i) => i !== index);
const checkedNum = data.reduce((n, file) => n + (file.withHeader & 1), 0);
setState({
checkAll: checkedNum === newData.length,
checkAll: checkedNum === newData.length && newData.length > 0,
indeterminate: !!checkedNum && checkedNum < newData.length,
data: newData,
activeItem: isActive ? null : activeItem,
previewContent: isActive ? [] : previewContent,
});
}, [activeItem, data]);
}, []);

const updateDelimiter = useCallback((e: React.ChangeEvent<HTMLInputElement>, item: StudioFile) => {
const { activeItem } = state;
e.stopPropagation();
item.delimiter = e.target.value;
item === activeItem && readFile(item);
}, [activeItem]);
item === activeItem && readFile();
}, []);

const updateAllDelimiter = useCallback((value: string) => {
data.forEach(item => item.delimiter = value);
readFile(activeItem);
}, [data, activeItem]);
const { data } = state;
setState({
data: data.map(item => (item.delimiter = value, item))
});
readFile();
}, []);

const handleConfirm = useCallback(() => {
const { data } = state;
const existFileName = fileList.map((file) => file.name);
const repeatFiles = data.filter((file) => existFileName.includes(file.name));
if(!repeatFiles.length) {
startImport();
return;
}
const repeatFileNames = repeatFiles.map((file) => file.name).join(', ');
Modal.confirm({
title: <>
<ExclamationCircleFilled />
{intl.get('import.uploadConfirm')}
</>,
icon: null,
content: <>
<div className={styles.repeatBox}>{repeatFileNames}</div>
<p>{intl.get('import.fileRepeatTip')}</p>
</>,
okText: intl.get('common.continue'),
cancelText: intl.get('common.cancel'),
centered: true,
wrapClassName: styles.repeatConfirmModal,
onOk: () => {
startImport();
},
});
}, [fileList]);
const startImport = useCallback(async () => {
const { data, setState } = state;
setState({ uploading: true });
const res = await uploadFile(data);
if(res.code === 0) {
onConfirm();
}
setState({ uploading: false });
}, []);
const handleCancel = useCallback(() => {
const { uploading } = state;
!uploading && onCancel();
}, []);

if(!visible) {
return null;
}
const { uploading, data, activeItem, previewContent, checkAll, indeterminate, loading, setState } = state;
const parseColumns = previewContent.length
? previewContent[0].map((header, index) => {
const textIndex = index;
const title = activeItem?.withHeader ? header : `Column ${textIndex}`;
return {
title,
dataIndex: index,
render: value => <span className={styles.limitWidth}>{value}</span>,
};
})
: [];
const columns = [
{
title: intl.get('import.fileName'),
Expand Down Expand Up @@ -165,59 +228,6 @@ const UploadConfigModal = (props: IProps) => {
),
},
];
const parseColumns = useMemo(() => previewContent.length
? previewContent[0].map((header, index) => {
const textIndex = index;
const title = activeItem?.withHeader ? header : `Column ${textIndex}`;
return {
title,
dataIndex: index,
render: value => <span className={styles.limitWidth}>{value}</span>,
};
})
: [], [previewContent, activeItem?.withHeader]);
const handleConfirm = useCallback(() => {
const existFileName = fileList.map((file) => file.name);
const repeatFiles = data.filter((file) => existFileName.includes(file.name));
if(!repeatFiles.length) {
startImport();
return;
}
const repeatFileNames = repeatFiles.map((file) => file.name).join(', ');
Modal.confirm({
title: <>
<ExclamationCircleFilled />
{intl.get('import.uploadConfirm')}
</>,
icon: null,
content: <>
<div className={styles.repeatBox}>{repeatFileNames}</div>
<p>{intl.get('import.fileRepeatTip')}</p>
</>,
okText: intl.get('common.continue'),
cancelText: intl.get('common.cancel'),
centered: true,
wrapClassName: styles.repeatConfirmModal,
onOk: () => {
startImport();
},
});
}, [fileList, data]);
const startImport = useCallback(async () => {
setState({ uploading: true });
const res = await uploadFile(data);
if(res.code === 0) {
onConfirm();
}
setState({ uploading: false });
}, [state]);
const handleCancel = useCallback(() => {
!uploading && onCancel();
}, [uploading]);

if(!visible) {
return null;
}

return (
<Modal
Expand Down
8 changes: 6 additions & 2 deletions app/pages/Import/FileList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { observer } from 'mobx-react-lite';
import { useStore } from '@app/stores';
import { trackPageView } from '@app/utils/stat';
Expand Down Expand Up @@ -96,6 +96,10 @@ const FileList = () => {
await getFiles();
setLoading(false);
};
const handleDeleteFiles = useCallback(async () => {
const flag = await deleteFile(selectFiles);
flag && setSelectFiles([]);
}, [selectFiles]);
useEffect(() => {
getFileList();
trackPageView('/import/files');
Expand All @@ -116,7 +120,7 @@ const FileList = () => {
</Button>
</Upload>
<Popconfirm
onConfirm={() => deleteFile(selectFiles)}
onConfirm={handleDeleteFiles}
title={intl.get('common.ask')}
okText={intl.get('common.confirm')}
cancelText={intl.get('common.cancel')}
Expand Down
1 change: 1 addition & 0 deletions app/stores/files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export class FilesStore {
this.fileList = this.fileList.filter((item) => !names.includes(item.name));
});
}
return res.code === 0;
};

updateFileConfig = async (payload: {
Expand Down

0 comments on commit eb4be97

Please sign in to comment.