Preview.tsx 5.4 KB

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