diff --git a/components/settings/data-management/DataManagement.js b/components/settings/data-management/DataManagement.js
index d36ad70..1e4d2a3 100644
--- a/components/settings/data-management/DataManagement.js
+++ b/components/settings/data-management/DataManagement.js
@@ -6,40 +6,23 @@ import AppText from '../../common/app-text'
import Button from '../../common/button'
import Segment from '../../common/segment'
-import { openImportDialog, getFileContent, importData } from './import-dialog'
import openShareDialogAndExport from './export-dialog'
import DeleteData from './delete-data'
import labels from '../../../i18n/en/settings'
-import { ACTION_DELETE, ACTION_EXPORT, ACTION_IMPORT } from '../../../config'
+import ImportData from './ImportData'
const DataManagement = () => {
const [isLoading, setIsLoading] = useState(false)
- const [currentAction, setCurrentAction] = useState(null)
-
- const startImportFlow = async (shouldDeleteExistingData) => {
- setIsLoading(true)
- const fileContent = await getFileContent()
- if (fileContent) {
- await importData(shouldDeleteExistingData, fileContent)
- }
- setIsLoading(false)
- }
+ const [isDeletingData, setIsDeletingData] = useState(false)
const startExport = () => {
- setCurrentAction(ACTION_EXPORT)
+ setIsDeletingData(false)
openShareDialogAndExport()
}
- const startImport = () => {
- setCurrentAction(ACTION_IMPORT)
- openImportDialog(startImportFlow)
- }
-
if (isLoading) return
- const isDeletingData = currentAction === ACTION_DELETE
-
return (
@@ -48,17 +31,15 @@ const DataManagement = () => {
{labels.export.button}
-
- {labels.import.segmentExplainer}
-
-
+ setIsDeletingData(false)}
+ setIsLoading={setIsLoading}
+ />
{labels.deleteSegment.explainer}
setCurrentAction(ACTION_DELETE)}
+ onStartDeletion={() => setIsDeletingData(true)}
/>
diff --git a/components/settings/data-management/ImportData.js b/components/settings/data-management/ImportData.js
new file mode 100644
index 0000000..d88a21e
--- /dev/null
+++ b/components/settings/data-management/ImportData.js
@@ -0,0 +1,97 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { Alert } from 'react-native'
+import DocumentPicker from 'react-native-document-picker'
+import rnfs from 'react-native-fs'
+import importCsv from '../../../lib/import-export/import-from-csv'
+import alertError from '../common/alert-error'
+import Segment from '../../common/segment'
+import AppText from '../../common/app-text'
+import Button from '../../common/button'
+import { useTranslation } from 'react-i18next'
+
+export default function ImportData({ resetIsDeletingData, setIsLoading }) {
+ const { t } = useTranslation(null, {
+ keyPrefix: 'hamburgerMenu.settings.data.import',
+ })
+
+ async function startImportFlow(shouldDeleteExistingData) {
+ setIsLoading(true)
+ await importData(shouldDeleteExistingData)
+ setIsLoading(false)
+ }
+
+ async function getFileInfo() {
+ try {
+ const fileInfo = await DocumentPicker.pickSingle({
+ type: [DocumentPicker.types.csv, 'text/comma-separated-values'],
+ })
+ return fileInfo
+ } catch (error) {
+ if (DocumentPicker.isCancel(error)) return // User cancelled the picker, exit any dialogs or menus and move on
+ showImportErrorAlert(error)
+ }
+ }
+
+ async function getFileContent() {
+ const fileInfo = await getFileInfo()
+ if (!fileInfo) return null
+
+ try {
+ const fileContent = await rnfs.readFile(fileInfo.uri, 'utf8')
+ return fileContent
+ } catch (err) {
+ return showImportErrorAlert(t('errors.couldNotOpenFile'))
+ }
+ }
+
+ async function importData(shouldDeleteExistingData) {
+ const fileContent = await getFileContent()
+ if (!fileContent) return
+
+ try {
+ await importCsv(fileContent, shouldDeleteExistingData)
+ Alert.alert(t('success.title'), t('success.message'))
+ } catch (err) {
+ showImportErrorAlert(err.message)
+ }
+ }
+
+ function openImportDialog() {
+ resetIsDeletingData()
+ Alert.alert(t('dialog.title'), t('dialog.message'), [
+ {
+ text: t('dialog.cancel'),
+ style: 'cancel',
+ onPress: () => {},
+ },
+ {
+ text: t('dialog.replace'),
+ onPress: () => startImportFlow(false),
+ },
+ {
+ text: t('dialog.delete'),
+ onPress: () => startImportFlow(true),
+ },
+ ])
+ }
+
+ function showImportErrorAlert(message) {
+ const errorMessage = t('errors.noDataImported', { message })
+ alertError(errorMessage)
+ }
+
+ return (
+
+ {t('segmentExplainer')}
+
+
+ )
+}
+
+ImportData.propTypes = {
+ resetIsDeletingData: PropTypes.func.isRequired,
+ setIsLoading: PropTypes.func.isRequired,
+}
diff --git a/i18n/en.json b/i18n/en.json
index 7102896..39a1123 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -80,6 +80,28 @@
}
},
"settings": {
+ "data": {
+ "import": {
+ "button": "Import data",
+ "dialog": {
+ "cancel": "Cancel",
+ "delete": "Import and delete existing",
+ "message": "There are two options for the import:\n\n1. Keep existing cycle days and replace only the ones in the import file.\n\n2. Delete all existing cycle days and import cycle days from file",
+ "replace": "Import and replace",
+ "title": "Keep existing data?"
+ },
+ "errors": {
+ "couldNotOpenFile": "Could not open file",
+ "futureEdit": "Future dates may only contain a note, no other symptoms",
+ "noDataImported": "{{message}}\n\nNo data was imported or changed"
+ },
+ "segmentExplainer": "Import data in CSV format",
+ "success": {
+ "message": "Data successfully imported",
+ "title": "Success"
+ }
+ }
+ },
"menuItem": {
"dataManagement": {
"name": "Data",
diff --git a/i18n/en/settings.js b/i18n/en/settings.js
index bb5117c..4cdffcd 100644
--- a/i18n/en/settings.js
+++ b/i18n/en/settings.js
@@ -31,24 +31,6 @@ export default {
segmentExplainer:
'Export data in CSV format for backup or so you can use it elsewhere',
},
- import: {
- button: 'Import data',
- title: 'Keep existing data?',
- message: `There are two options for the import:
-1. Keep existing cycle days and replace only the ones in the import file.
-2. Delete all existing cycle days and import cycle days from file.`,
- replaceOption: 'Import and replace',
- deleteOption: 'Import and delete existing',
- errors: {
- couldNotOpenFile: 'Could not open file',
- postFix: 'No data was imported or changed',
- futureEdit: 'Future dates may only contain a note, no other symptoms',
- },
- success: {
- message: 'Data successfully imported',
- },
- segmentExplainer: 'Import data in CSV format',
- },
deleteSegment: {
title: 'Delete app data',
explainer: 'Delete app data from this phone',