Preview.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. import { FC, useCallback, useEffect, useMemo, useState } from 'react';
  2. import { makeStyles, Theme, Typography } from '@material-ui/core';
  3. import { useTranslation } from 'react-i18next';
  4. import { InsertPreviewProps } from './Types';
  5. import { Option } from '../customSelector/Types';
  6. import CustomSelector from '../customSelector/CustomSelector';
  7. import MilvusGrid from '../grid/Grid';
  8. import { transferCsvArrayToTableData } from '../../utils/Insert';
  9. import { ColDefinitionsType } from '../grid/Types';
  10. import SimpleMenu from '../menu/SimpleMenu';
  11. import icons from '../icons/Icons';
  12. const getStyles = makeStyles((theme: Theme) => ({
  13. wrapper: {
  14. width: '75vw',
  15. },
  16. selectorTip: {
  17. color: theme.palette.milvusGrey.dark,
  18. fontWeight: 500,
  19. marginBottom: theme.spacing(1),
  20. },
  21. selectorWrapper: {
  22. '& .selector': {
  23. flexBasis: '40%',
  24. minWidth: '256px',
  25. },
  26. '& .isContainSelect': {
  27. paddingTop: theme.spacing(2),
  28. paddingBottom: theme.spacing(2),
  29. },
  30. },
  31. gridWrapper: {
  32. height: '320px',
  33. },
  34. tableTip: {
  35. display: 'flex',
  36. justifyContent: 'space-between',
  37. alignItems: 'center',
  38. marginTop: theme.spacing(3),
  39. marginBottom: theme.spacing(1),
  40. '& .text': {
  41. color: theme.palette.milvusGrey.dark,
  42. fontWeight: 500,
  43. },
  44. },
  45. menuLabel: {
  46. display: 'flex',
  47. justifyContent: 'space-between',
  48. minWidth: '160px',
  49. color: theme.palette.milvusGrey.dark,
  50. backgroundColor: '#fff',
  51. '&:hover': {
  52. backgroundColor: '#fff',
  53. },
  54. },
  55. active: {
  56. color: theme.palette.primary.main,
  57. },
  58. menuIcon: {
  59. color: theme.palette.milvusGrey.dark,
  60. },
  61. menuItem: {
  62. fontWeight: 500,
  63. fontSize: '12px',
  64. lineHeight: '16px',
  65. color: theme.palette.milvusGrey.dark,
  66. },
  67. menuActive: {
  68. color: theme.palette.primary.main,
  69. },
  70. }));
  71. const getTableData = (
  72. data: any[],
  73. isContainFieldNames: number
  74. ): { [key in string]: any }[] => {
  75. const csvData = isContainFieldNames ? data.slice(1) : data;
  76. return transferCsvArrayToTableData(csvData);
  77. };
  78. const getDefaultHeads = (
  79. data: any[],
  80. isContainFieldNames: number
  81. ): string[] => {
  82. return isContainFieldNames ? data[0] : new Array(data[0].length).fill('');
  83. };
  84. const InsertPreview: FC<InsertPreviewProps> = ({
  85. schemaOptions,
  86. data,
  87. isContainFieldNames,
  88. handleIsContainedChange,
  89. }) => {
  90. const classes = getStyles();
  91. const { t: insertTrans } = useTranslation('insert');
  92. const ArrowIcon = icons.dropdown;
  93. const tableData = getTableData(data, isContainFieldNames);
  94. const [tableHeads, setTableHeads] = useState<string[]>(
  95. getDefaultHeads(data, isContainFieldNames)
  96. );
  97. const handleTableHeadChange = useCallback(
  98. (index: number, label: string) => {
  99. const newHeads = [...tableHeads];
  100. newHeads[index] = label;
  101. setTableHeads(newHeads);
  102. },
  103. [tableHeads]
  104. );
  105. useEffect(() => {
  106. const newHeads = getDefaultHeads(data, isContainFieldNames);
  107. setTableHeads(newHeads);
  108. }, [data, isContainFieldNames]);
  109. const editHeads = useMemo(
  110. () =>
  111. tableHeads.map((head: string, index: number) => ({
  112. value: head,
  113. component: (
  114. <SimpleMenu
  115. label={head || insertTrans('requiredFieldName')}
  116. menuItems={schemaOptions.map(schema => ({
  117. label: schema.label,
  118. callback: () => handleTableHeadChange(index, schema.label),
  119. wrapperClass: `${classes.menuItem} ${
  120. head === schema.label ? classes.menuActive : ''
  121. }`,
  122. }))}
  123. buttonProps={{
  124. className: classes.menuLabel,
  125. endIcon: <ArrowIcon classes={{ root: classes.menuIcon }} />,
  126. }}
  127. ></SimpleMenu>
  128. ),
  129. })),
  130. [
  131. tableHeads,
  132. classes.menuLabel,
  133. classes.menuIcon,
  134. classes.menuItem,
  135. classes.menuActive,
  136. ArrowIcon,
  137. schemaOptions,
  138. insertTrans,
  139. handleTableHeadChange,
  140. ]
  141. );
  142. const isContainedOptions: Option[] = [
  143. {
  144. label: 'Yes',
  145. value: 1,
  146. },
  147. { label: 'No', value: 0 },
  148. ];
  149. // use table row first item to get value
  150. const colDefinitions: ColDefinitionsType[] = Object.keys(tableData[0])
  151. // filter id since we don't want to show it in the table
  152. .filter(item => item !== 'id')
  153. .map(key => ({
  154. id: key,
  155. align: 'left',
  156. disablePadding: true,
  157. label: '',
  158. }));
  159. return (
  160. <section className={classes.wrapper}>
  161. <form className={classes.selectorWrapper}>
  162. <label>
  163. <Typography className={classes.selectorTip}>
  164. {insertTrans('isContainFieldNames')}
  165. </Typography>
  166. </label>
  167. <CustomSelector
  168. options={isContainedOptions}
  169. wrapperClass="selector"
  170. classes={{ filled: 'isContainSelect' }}
  171. value={isContainFieldNames}
  172. variant="filled"
  173. onChange={(e: { target: { value: unknown } }) => {
  174. const isContainedValue = e.target.value;
  175. handleIsContainedChange(isContainedValue as number);
  176. }}
  177. />
  178. </form>
  179. <div className={classes.tableTip}>
  180. <Typography className="text">
  181. {insertTrans('previewTipData')}
  182. </Typography>
  183. <Typography className="text">
  184. {insertTrans('previewTipAction')}
  185. </Typography>
  186. </div>
  187. {tableData.length > 0 && (
  188. <div className={classes.gridWrapper}>
  189. <MilvusGrid
  190. toolbarConfigs={[]}
  191. colDefinitions={colDefinitions}
  192. rows={tableData}
  193. rowCount={0}
  194. primaryKey="id"
  195. openCheckBox={false}
  196. showHoverStyle={false}
  197. headEditable={true}
  198. editHeads={editHeads}
  199. tableCellMaxWidth="120px"
  200. />
  201. </div>
  202. )}
  203. </section>
  204. );
  205. };
  206. export default InsertPreview;