diff --git a/components/Nav.js b/components/Nav.js index b940e45..2f66d9e 100644 --- a/components/Nav.js +++ b/components/Nav.js @@ -4,9 +4,16 @@ import { useTranslation } from 'next-i18next' import Menu from './icons/Menu' import Close from './icons/Close' import useDeviceDetect from '../hooks/useDeviceDetect' +import { useEffect, useState, useRef } from 'react' +import useLocalStorage from '../hooks/useLocalStorage' export const Nav = ({ + sectionTemplates, selectedSectionSlugs, + setSelectedSectionSlugs, + setSectionSlugs, + templates, + setTemplates, setShowModal, getTemplate, onMenuClick, @@ -15,6 +22,20 @@ export const Nav = ({ setDarkMode, focusedSectionSlug, }) => { + const [files, setFiles] = useState([]) + const { saveBackup } = useLocalStorage() + const fileInput = useRef(null) + + /** + * Enum for handling supported file type exports. + * @readonly + * @enum string + */ + const FileExports = Object.freeze({ + JSON: 'json', + MD: 'md', + }) + const markdown = selectedSectionSlugs.reduce((acc, section) => { const template = getTemplate(section) if (template) { @@ -26,18 +47,67 @@ export const Nav = ({ const { isMobile } = useDeviceDetect() - const downloadMarkdownFile = () => { + const downloadFile = (fileExtension) => { + const selected_slugs = localStorage.getItem('current-slug-list') + const export_template = templates.filter((t) => selected_slugs.includes(t.slug)) + const a = document.createElement('a') - const blob = new Blob([markdown]) + const blob = new Blob( + fileExtension == 'md' + ? [markdown] + : fileExtension == 'json' + ? [JSON.stringify(export_template)] + : [] + ) + a.href = URL.createObjectURL(blob) - a.download = 'README.md' + a.download = `README.${fileExtension}` a.click() + if (isMobile && isDrawerOpen) { onMenuClick() } setShowModal(true) } + const uploadJSON = (e) => { + const fileReader = new FileReader() + fileReader.readAsText(e.target.files[0], 'UTF-8') + fileReader.onload = (e) => { + setFiles(JSON.parse(e.target.result)) + } + } + + const validate_files = () => { + return files.filter((f) => { + const required_keys = ['slug', 'name', 'markdown'] + const keys = Object.keys(f) + + if (keys.length != required_keys.length) { + return false + } + + return keys.every((key) => required_keys.includes(key)) + }) + } + + useEffect(() => { + if (files.length > 0) { + const files = validate_files() + const selected_slugs = files.map((f) => f.slug) + const slugs = sectionTemplates.map((s) => s.slug).filter((s) => !selected_slugs.includes(s)) + + const temp = templates.filter((t) => !selected_slugs.includes(t.slug)) + templates = [...temp, ...files] + + localStorage.setItem('current-slug-list', selected_slugs.join(',')) + setSelectedSectionSlugs(selected_slugs) + setSectionSlugs(slugs) + saveBackup(templates) + setTemplates(templates) + } + }, [files]) + const { t } = useTranslation('editor') return ( @@ -47,7 +117,7 @@ export const Nav = ({ -