aboutsummaryrefslogtreecommitdiffstats
path: root/apps/Notes/components/Import.js
blob: 71c08d630e6efbec4692fa8c8b9702c094a11f8e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import React, {useState} from 'react'
import fetchJson from 'lib/fetchJson'
import useNotes from '../hooks/useNotes'
import {faCheck, faTimes} from '@fortawesome/free-solid-svg-icons'
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'

const Import = ({action, setAction}) => {
  const [files, setFiles] = useState()
  const [done, setDone] = useState([])
  const {mutateNotes} = useNotes()

  const state = i => done[i] && <span><FontAwesomeIcon icon={done[i] === 1 ? faCheck : faTimes} /></span>

  const readFileAsText = (file) => new Promise((resolve,reject) => {
    let fr = new FileReader()

    fr.onload = () => resolve(fr.result)
    fr.onerror = () => reject(fr)

    fr.readAsText(file)
  })

  const handleImport = async e => {
    e.preventDefault();

    Array.from(files).forEach(async (file, i) => {
      const title = file.name.replace(/\.[^/.]+$/, "")
      const content = await readFileAsText(file);

      try {
        const notes = await fetchJson('/api/notes', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({title, content}),
        })
        if (i === files.length - 1) await mutateNotes(notes)
        setDone((prev) => ({...prev, [i]: 1}))
      } catch (e) {
        setDone((prev) => ({...prev, [i]: 0}))
      }
    })
  }

  const handleChange = e => {
    setFiles(e.currentTarget.files)
    setDone([])
  }

  return (
    <section>
      <div className='window__submenu'>
        <div onClick={() => { setAction('') }}>Back</div>
      </div>
      <div className='window__scroll'>
        <form onSubmit={handleImport}>
          Import new notes:
          <div>
            <label className="window__button">
              Choose files
              <input
                name="import"
                type="file"
                multiple="multiple"
                accept="text/plain"
                onChange={handleChange}
              />
            </label>
          </div>
          {files && (
            <>
              <p>Notes to import:</p>
              <ul>
                {[...files].map((f, i) => <li key={f.name}>{f.name} {state(i)}</li>)}
              </ul>
              {
                done.length === 0
                  ? <input type="submit" value="Import" className="window__button" />
                  : <p>Import finished.<br/><br/>Go back to notes list or choose other notes to import.</p>
              }
            </>
          )}
        </form>
      </div>
      <style jsx>{`
        section {
          background: white;
          padding: 1rem;
          position: absolute;
          top: 0;
          right: 0;
          bottom: 0;
          left: 0;
          animation: fade-in .3s;
        }

        form {
          padding: 1em;
        }

        input[type=file] {
          display: none;
        }

        label {
          display: inline-block;
          cursor: pointer;
        }

        ul {
           list-style: disc inside none;
        }

        li {
          padding: .25em;
        }

        p {
          padding: 1em 0;
        }
      `}</style>
    </section>
  )
}

export default Import