This repository has been archived by the owner on Mar 6, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(enquete): import individuel #1801
- Loading branch information
Showing
13 changed files
with
350 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { BoxWrapper } from "@emjpm/ui"; | ||
import React, { useContext } from "react"; | ||
|
||
import { EnqueteImportPanel } from "../../../src/components/EnqueteImport"; | ||
import { LayoutMandataire } from "../../../src/components/Layout"; | ||
import { UserContext } from "../../../src/components/UserContext"; | ||
import { withAuthSync } from "../../../src/util/auth"; | ||
|
||
const ImportEnquetePage = () => { | ||
const user = useContext(UserContext); | ||
return ( | ||
<LayoutMandataire> | ||
<BoxWrapper mt={6} px="1"> | ||
<EnqueteImportPanel mandataireUserId={user.id} /> | ||
</BoxWrapper> | ||
</LayoutMandataire> | ||
); | ||
}; | ||
|
||
ImportEnquetePage.getInitialProps = async ({ query }) => { | ||
return { id: Number(query.id) }; | ||
}; | ||
|
||
export default withAuthSync(ImportEnquetePage); |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import React from "react"; | ||
import { Flex } from "rebass"; | ||
|
||
const DocumentLink = ({ children, document }) => ( | ||
<a href={document}> | ||
<Flex | ||
maxWidth="200px" | ||
flexDirection="column" | ||
justifyContent="center" | ||
alignItem="center" | ||
pt={6} | ||
pb={6} | ||
pr={2} | ||
pl={2} | ||
m={2} | ||
sx={{ | ||
border: "1px solid" | ||
}} | ||
> | ||
{children} | ||
</Flex> | ||
</a> | ||
); | ||
|
||
export { DocumentLink }; |
25 changes: 25 additions & 0 deletions
25
packages/app/src/components/EnqueteImport/EnqueteImportErrors.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { Card, Heading3 } from "@emjpm/ui"; | ||
import React from "react"; | ||
import { Flex, Text } from "rebass"; | ||
|
||
import { importErrorsWrapperStyle } from "./style"; | ||
|
||
const EnqueteImportErrors = props => { | ||
const { errors } = props; | ||
|
||
return ( | ||
<Card sx={importErrorsWrapperStyle} overflow="hidden"> | ||
<Heading3 mb={4}>Détail des erreurs par ligne</Heading3> | ||
{errors.map(({ line = 0, message }) => ( | ||
<Flex key={`${line}-${message}`} mb={1}> | ||
<Text color="warning" mr={1}> | ||
LIGNE {line} | ||
</Text> | ||
<Text>{message}</Text> | ||
</Flex> | ||
))} | ||
</Card> | ||
); | ||
}; | ||
|
||
export { EnqueteImportErrors }; |
58 changes: 58 additions & 0 deletions
58
packages/app/src/components/EnqueteImport/EnqueteImportPanel.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { LoaderCircle } from "@styled-icons/boxicons-regular/LoaderCircle"; | ||
import React, { Fragment } from "react"; | ||
import { Box } from "rebass"; | ||
|
||
import { EnqueteImportResult } from "./EnqueteImportResult"; | ||
import { SingleImportFilePicker } from "./SingleImportFilePicker"; | ||
import { useEnqueteImportManager } from "./useEnqueteImportManager.hook"; | ||
|
||
export const EnqueteImportPanel = ({ | ||
// mandataireUserId & serviceId are mutually exclusive | ||
mandataireUserId, | ||
serviceId | ||
}) => { | ||
const { | ||
importEnqueteFile, | ||
importSummary, | ||
importEnqueteFileWithAntennesMap, | ||
reset, | ||
enquetesImportLoading | ||
} = useEnqueteImportManager({ | ||
mandataireUserId, | ||
serviceId | ||
}); | ||
|
||
if (enquetesImportLoading) { | ||
return ( | ||
<Box p={4}> | ||
<LoaderCircle size="16" /> Traitement du fichier en cours, veuillez patienter (cela peut | ||
prendre jusqu'à 2mn pour les gros fichiers)... | ||
</Box> | ||
); | ||
} | ||
|
||
if (importSummary && !importSummary.unexpectedError) { | ||
return ( | ||
<EnqueteImportResult | ||
reset={() => reset()} | ||
importSummary={importSummary} | ||
serviceId={serviceId} | ||
onSubmitAntennesMap={({ antennesMap }) => importEnqueteFileWithAntennesMap(antennesMap)} | ||
/> | ||
); | ||
} | ||
|
||
return ( | ||
<Fragment> | ||
{importSummary && importSummary.unexpectedError && ( | ||
<Box mt={2} mb={2}> | ||
Erreur innatendue. Veuillez ré-essayer. | ||
</Box> | ||
)} | ||
<SingleImportFilePicker | ||
placeholder="Sélectionner votre fichier excel" | ||
onFileChosen={file => importEnqueteFile(file)} | ||
/> | ||
</Fragment> | ||
); | ||
}; |
37 changes: 37 additions & 0 deletions
37
packages/app/src/components/EnqueteImport/EnqueteImportResult.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { Button, Heading2, Text } from "@emjpm/ui"; | ||
import React from "react"; | ||
import { Flex } from "rebass"; | ||
|
||
import { EnqueteImportErrors } from "./EnqueteImportErrors"; | ||
import { ServiceEnqueteImportResultStyle } from "./style"; | ||
|
||
const EnqueteImportResult = ({ | ||
reset, | ||
importSummary: { creationNumber, updateNumber, errors } | ||
}) => { | ||
return ( | ||
<div p={7} sx={ServiceEnqueteImportResultStyle}> | ||
<Flex alignItems="center"> | ||
<Flex flexDirection="column"> | ||
<Heading2>{`Résultat de l'import`}</Heading2> | ||
{errors.length ? ( | ||
<Text m={2} fontSize={2}>{`Erreur lors de l'import des enquetes (${ | ||
errors.length | ||
} erreurs sur ${errors.length + | ||
creationNumber + | ||
updateNumber} enquetes). Aucune enquete n'a été importée.`}</Text> | ||
) : ( | ||
<Text m={2} fontSize={2}>{`${creationNumber + | ||
updateNumber} enquetes ont été importées (${creationNumber} nouvelles et ${updateNumber} mises à jour).`}</Text> | ||
)} | ||
</Flex> | ||
<Button variant="outline" onClick={reset}> | ||
Sélectionner un autre fichier | ||
</Button> | ||
</Flex> | ||
{!!errors.length && <EnqueteImportErrors errors={errors} />} | ||
</div> | ||
); | ||
}; | ||
|
||
export { EnqueteImportResult }; |
34 changes: 34 additions & 0 deletions
34
packages/app/src/components/EnqueteImport/EnqueteImportResults.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { Button, Heading2, Text } from "@emjpm/ui"; | ||
import React, { Fragment } from "react"; | ||
import { Flex } from "rebass"; | ||
|
||
import { EnqueteImportErrors } from "./EnqueteImportErrors"; | ||
import { ServiceEnqueteImportResultStyle } from "./style"; | ||
|
||
const EnqueteImportResults = props => { | ||
const { errors, enquetes, reset } = props; | ||
|
||
return ( | ||
<Fragment> | ||
<Flex alignItems="center" p={7} sx={ServiceEnqueteImportResultStyle}> | ||
<Flex flexDirection="column"> | ||
<Heading2>{`Résultat de l'import`}</Heading2> | ||
<Text | ||
m={2} | ||
fontSize={2} | ||
>{`${enquetes.length} enquetes vont être importées ou mises à jour. Vous allez recevoir un email dans quelques instants.`}</Text> | ||
<Text | ||
m={2} | ||
fontSize={2} | ||
>{`${errors.length} enquetes ne seront pas importées ou mises à jour. Les erreurs sont indiquées ci-dessous.`}</Text> | ||
</Flex> | ||
<Button variant="outline" onClick={reset}> | ||
Sélectionner un autre fichier | ||
</Button> | ||
</Flex> | ||
{errors.length > 0 && <EnqueteImportErrors errors={errors} />} | ||
</Fragment> | ||
); | ||
}; | ||
|
||
export { EnqueteImportResults }; |
23 changes: 23 additions & 0 deletions
23
packages/app/src/components/EnqueteImport/SingleImportFilePicker.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { Input } from "@emjpm/ui"; | ||
import React from "react"; | ||
import { Box } from "rebass"; | ||
|
||
const SingleImportFilePicker = ({ onFileChosen, placeholder }) => { | ||
return ( | ||
<Box mb="2"> | ||
<Input | ||
id="file" | ||
type="file" | ||
name="file" | ||
value="" | ||
onChange={event => { | ||
const file = event.currentTarget.files[0]; | ||
onFileChosen(file); | ||
}} | ||
placeholder={placeholder} | ||
/> | ||
</Box> | ||
); | ||
}; | ||
|
||
export { SingleImportFilePicker }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
function readFileAsBinaryString(file, cb, err) { | ||
if (file) { | ||
const reader = new FileReader(); | ||
|
||
const isExcel = file.name.endsWith(".xls") || file.name.endsWith(".xlsx"); | ||
|
||
if (isExcel) { | ||
reader.readAsBinaryString(file); | ||
} else { | ||
reader.readAsText(file); | ||
} | ||
reader.onload = () => { | ||
const base64str = btoa(reader.result); | ||
if (cb) { | ||
cb({ base64str, file }); | ||
} | ||
}; | ||
reader.onerror = () => { | ||
console.error("unable to parse file"); | ||
if (err) { | ||
err(new Error("Unable to parse file")); | ||
} | ||
}; | ||
} | ||
} | ||
|
||
export const fileReader = { | ||
readFileAsBinaryString | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { EnqueteImportPanel } from "./EnqueteImportPanel"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import gql from "graphql-tag"; | ||
|
||
export const UPLOAD_ENQUETES_EXCEL_FILE = gql` | ||
mutation upload_enquetes_file( | ||
$name: String! | ||
$type: String! | ||
$base64str: String! | ||
$antennesMap: String | ||
$serviceId: Int | ||
$mandataireUserId: Int | ||
) { | ||
upload_enquetes_file( | ||
name: $name | ||
type: $type | ||
base64str: $base64str | ||
antennesMap: $antennesMap | ||
serviceId: $serviceId | ||
mandataireUserId: $mandataireUserId | ||
) { | ||
data | ||
} | ||
} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
const ServiceEnqueteImportStyle = {}; | ||
|
||
const ServiceEnqueteImportResultStyle = { | ||
border: "1px solid", | ||
borderRadius: "3px" | ||
}; | ||
|
||
const importErrorsWrapperStyle = { | ||
bg: "cardSecondary", | ||
borderRadius: "5px 0 0 5px", | ||
m: "2", | ||
p: "5", | ||
maxHeight: "500px", | ||
overflow: "auto" | ||
}; | ||
|
||
export { ServiceEnqueteImportStyle, ServiceEnqueteImportResultStyle, importErrorsWrapperStyle }; |
54 changes: 54 additions & 0 deletions
54
packages/app/src/components/EnqueteImport/useEnqueteImportManager.hook.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { useMutation } from "@apollo/react-hooks"; | ||
import { useState } from "react"; | ||
|
||
import { UPLOAD_ENQUETES_EXCEL_FILE } from "../EnqueteImport/mutations"; | ||
import { fileReader } from "./fileReader"; | ||
|
||
function useEnqueteImportManager({ mandataireUserId, serviceId }) { | ||
const [importSummary, setImportSummary] = useState(); | ||
const [uploadFile, { loading: enquetesImportLoading }] = useMutation(UPLOAD_ENQUETES_EXCEL_FILE); | ||
|
||
function importEnqueteFile({ file, antennesMap }) { | ||
fileReader.readFileAsBinaryString(file, ({ file, base64str }) => { | ||
const { name, type } = file; | ||
uploadFile({ | ||
variables: { | ||
base64str, | ||
name, | ||
serviceId, | ||
antennesMap: antennesMap ? JSON.stringify(antennesMap) : undefined, | ||
type, | ||
mandataireUserId | ||
} | ||
}) | ||
.then( | ||
({ | ||
data: { | ||
upload_enquetes_file: { data } | ||
} | ||
}) => { | ||
const importSummary = JSON.parse(data); | ||
setImportSummary(importSummary); | ||
} | ||
) | ||
.catch(() => { | ||
setImportSummary({ | ||
unexpectedError: true | ||
}); | ||
}); | ||
}); | ||
} | ||
|
||
function reset() { | ||
setImportSummary(undefined); | ||
} | ||
|
||
return { | ||
importEnqueteFile, | ||
importSummary, | ||
enquetesImportLoading, | ||
reset | ||
}; | ||
} | ||
|
||
export { useEnqueteImportManager }; |