reset()}
+ importSummary={importSummary}
+ serviceId={serviceId}
+ onSubmitAntennesMap={({ antennesMap }) => importEnqueteFileWithAntennesMap(antennesMap)}
+ />
+ );
+ }
+
+ return (
+
+ {importSummary && importSummary.unexpectedError && (
+
+ Erreur innatendue. Veuillez ré-essayer.
+
+ )}
+ importEnqueteFile(file)}
+ />
+
+ );
+};
diff --git a/packages/app/src/components/EnqueteImport/EnqueteImportResult.js b/packages/app/src/components/EnqueteImport/EnqueteImportResult.js
new file mode 100644
index 0000000000..b6def7de01
--- /dev/null
+++ b/packages/app/src/components/EnqueteImport/EnqueteImportResult.js
@@ -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 (
+
+
+
+ {`Résultat de l'import`}
+ {errors.length ? (
+ {`Erreur lors de l'import des enquetes (${
+ errors.length
+ } erreurs sur ${errors.length +
+ creationNumber +
+ updateNumber} enquetes). Aucune enquete n'a été importée.`}
+ ) : (
+ {`${creationNumber +
+ updateNumber} enquetes ont été importées (${creationNumber} nouvelles et ${updateNumber} mises à jour).`}
+ )}
+
+
+
+ {!!errors.length && }
+
+ );
+};
+
+export { EnqueteImportResult };
diff --git a/packages/app/src/components/EnqueteImport/EnqueteImportResults.js b/packages/app/src/components/EnqueteImport/EnqueteImportResults.js
new file mode 100644
index 0000000000..f66af695f1
--- /dev/null
+++ b/packages/app/src/components/EnqueteImport/EnqueteImportResults.js
@@ -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 (
+
+
+
+ {`Résultat de l'import`}
+ {`${enquetes.length} enquetes vont être importées ou mises à jour. Vous allez recevoir un email dans quelques instants.`}
+ {`${errors.length} enquetes ne seront pas importées ou mises à jour. Les erreurs sont indiquées ci-dessous.`}
+
+
+
+ {errors.length > 0 && }
+
+ );
+};
+
+export { EnqueteImportResults };
diff --git a/packages/app/src/components/EnqueteImport/SingleImportFilePicker.js b/packages/app/src/components/EnqueteImport/SingleImportFilePicker.js
new file mode 100644
index 0000000000..0db4ae6992
--- /dev/null
+++ b/packages/app/src/components/EnqueteImport/SingleImportFilePicker.js
@@ -0,0 +1,23 @@
+import { Input } from "@emjpm/ui";
+import React from "react";
+import { Box } from "rebass";
+
+const SingleImportFilePicker = ({ onFileChosen, placeholder }) => {
+ return (
+
+ {
+ const file = event.currentTarget.files[0];
+ onFileChosen(file);
+ }}
+ placeholder={placeholder}
+ />
+
+ );
+};
+
+export { SingleImportFilePicker };
diff --git a/packages/app/src/components/EnqueteImport/fileReader.js b/packages/app/src/components/EnqueteImport/fileReader.js
new file mode 100644
index 0000000000..a8ac45e89b
--- /dev/null
+++ b/packages/app/src/components/EnqueteImport/fileReader.js
@@ -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
+};
diff --git a/packages/app/src/components/EnqueteImport/index.js b/packages/app/src/components/EnqueteImport/index.js
new file mode 100644
index 0000000000..ce2f9f326a
--- /dev/null
+++ b/packages/app/src/components/EnqueteImport/index.js
@@ -0,0 +1 @@
+export { EnqueteImportPanel } from "./EnqueteImportPanel";
diff --git a/packages/app/src/components/EnqueteImport/mutations.js b/packages/app/src/components/EnqueteImport/mutations.js
new file mode 100644
index 0000000000..2f93c8d266
--- /dev/null
+++ b/packages/app/src/components/EnqueteImport/mutations.js
@@ -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
+ }
+ }
+`;
diff --git a/packages/app/src/components/EnqueteImport/style.js b/packages/app/src/components/EnqueteImport/style.js
new file mode 100644
index 0000000000..bc52290423
--- /dev/null
+++ b/packages/app/src/components/EnqueteImport/style.js
@@ -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 };
diff --git a/packages/app/src/components/EnqueteImport/useEnqueteImportManager.hook.js b/packages/app/src/components/EnqueteImport/useEnqueteImportManager.hook.js
new file mode 100644
index 0000000000..6885cc28db
--- /dev/null
+++ b/packages/app/src/components/EnqueteImport/useEnqueteImportManager.hook.js
@@ -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 };