diff --git a/web-app/src/containers/SelectTutorial/LoadTutorialSummary.tsx b/web-app/src/containers/SelectTutorial/LoadTutorialSummary.tsx index 898deceb..87cf0118 100644 --- a/web-app/src/containers/SelectTutorial/LoadTutorialSummary.tsx +++ b/web-app/src/containers/SelectTutorial/LoadTutorialSummary.tsx @@ -1,13 +1,11 @@ import * as React from 'react' import useFetch from '../../services/hooks/useFetch' import * as TT from 'typings/tutorial' -import TutorialOverview from '../../components/TutorialOverview' import Loading from '../Loading' interface Props { url: string - send: any - onClear(): void + onLoadSummary(data: TT.Tutorial): void } const LoadTutorialSummary = (props: Props) => { @@ -22,15 +20,8 @@ const LoadTutorialSummary = (props: Props) => { if (!data) { return
No data returned for tutorial
} - const onNext = () => { - props.send({ - type: 'TUTORIAL_START', - payload: { - tutorial: data, - }, - }) - } - return + props.onLoadSummary(data) + return null } export default LoadTutorialSummary diff --git a/web-app/src/containers/SelectTutorial/SelectTutorialForm.tsx b/web-app/src/containers/SelectTutorial/SelectTutorialForm.tsx index 4e4b568e..b65972f2 100644 --- a/web-app/src/containers/SelectTutorial/SelectTutorialForm.tsx +++ b/web-app/src/containers/SelectTutorial/SelectTutorialForm.tsx @@ -1,7 +1,9 @@ +import * as TT from 'typings/tutorial' import * as React from 'react' import { Radio } from '@alifd/next' import TutorialSelect from './forms/TutorialSelect' import TutorialUrl from './forms/TutorialUrl' +import TutorialFile from './forms/TutorialFile' const styles = { formWrapper: { @@ -15,7 +17,8 @@ interface Props { tab: string setTab(tab: 'list' | 'url'): void url: string | null - onTutorialLoad(url: string): void + onTutorialLoadFromUrl(url: string): void + onLoadSummary(data: TT.Tutorial | null): void } const SelectTutorialForm = (props: Props) => { @@ -30,12 +33,13 @@ const SelectTutorialForm = (props: Props) => { > List URL - {/* File */} + File

- {props.tab === 'list' && } - {props.tab === 'url' && } + {props.tab === 'list' && } + {props.tab === 'url' && } + {props.tab === 'file' && } ) } diff --git a/web-app/src/containers/SelectTutorial/forms/TutorialFile.tsx b/web-app/src/containers/SelectTutorial/forms/TutorialFile.tsx new file mode 100644 index 00000000..da257446 --- /dev/null +++ b/web-app/src/containers/SelectTutorial/forms/TutorialFile.tsx @@ -0,0 +1,56 @@ +import * as React from 'react' +import * as TT from 'typings/tutorial' +import { Form } from '@alifd/next' + +const FormItem = Form.Item + +interface Props { + onLoadSummary(data: TT.Tutorial): void +} + +const styles = { + uploadFileButton: { + padding: '0.3rem 0.5rem', + outline: '1px dotted rgb(51, 51, 51)', + borderRadius: '0.2rem', + fontWeight: 400, + fontFamily: + '-apple-system, system-ui, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;', + }, +} + +const TutorialFile = (props: Props) => { + const onChange = (evt: any) => { + evt.preventDefault() + const files = evt.target.files + + if (!files.length) { + alert('No file select') + return + } + const uploadedFile = files[0] + const reader = new FileReader() + reader.onload = (e: any) => { + // TODO: handle errors from invalid JSON + const fileJson: TT.Tutorial = JSON.parse(e.target.result) + props.onLoadSummary(fileJson) + } + reader.readAsText(uploadedFile) + } + + return ( +
+ +
+ +
+
+
+
+ ) +} + +export default TutorialFile diff --git a/web-app/src/containers/SelectTutorial/forms/TutorialUrl.tsx b/web-app/src/containers/SelectTutorial/forms/TutorialUrl.tsx index f9727261..9693f3bc 100644 --- a/web-app/src/containers/SelectTutorial/forms/TutorialUrl.tsx +++ b/web-app/src/containers/SelectTutorial/forms/TutorialUrl.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import { Button, Form, Radio, Input } from '@alifd/next' +import { Button, Form, Input } from '@alifd/next' const FormItem = Form.Item diff --git a/web-app/src/containers/SelectTutorial/index.tsx b/web-app/src/containers/SelectTutorial/index.tsx index 34e1155c..ee4bafae 100644 --- a/web-app/src/containers/SelectTutorial/index.tsx +++ b/web-app/src/containers/SelectTutorial/index.tsx @@ -1,5 +1,7 @@ +import * as TT from 'typings/tutorial' import * as React from 'react' import SelectTutorialForm from './SelectTutorialForm' +import TutorialOverview from '../../components/TutorialOverview' import LoadTutorialSummary from './LoadTutorialSummary' const styles = { @@ -19,17 +21,44 @@ interface Props { } const SelectTutorialPage = (props: Props) => { - const [page, setPage] = React.useState<'form' | 'summary'>('form') + const [data, setData] = React.useState() + const [page, setPage] = React.useState<'form' | 'loading' | 'summary'>('form') const [tab, setTab] = React.useState<'list' | 'url'>('list') const [url, setUrl] = React.useState(null) - const onTutorialLoad = (url: string) => { + + const onNext = () => { + props.send({ + type: 'TUTORIAL_START', + payload: { + tutorial: data, + }, + }) + } + const onTutorialLoadFromUrl = (url: string) => { setUrl(url) + setPage('loading') + } + const onLoadSummary = (d: TT.Tutorial) => { + setData(d) setPage('summary') } + const onClear = () => { + setData(null) + setPage('form') + } return (
- {page === 'form' && } - {page === 'summary' && url && setPage('form')} />} + {page === 'form' && ( + + )} + {page === 'loading' && url && } + {page === 'summary' && data && }
) }