diff --git a/package-lock.json b/package-lock.json index bc34116..9231076 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "react-redux": "^7.2.6", "react-router-dom": "^5.2.1", "react-scripts": "^4.0.3", + "react-simplemde-editor": "^5.0.2", "uplot": "^1.6.18", "uplot-react": "^1.1.1" }, @@ -4196,6 +4197,14 @@ "@babel/types": "^7.3.0" } }, + "node_modules/@types/codemirror": { + "version": "0.0.109", + "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.109.tgz", + "integrity": "sha512-cSdiHeeLjvGn649lRTNeYrVCDOgDrtP+bDDSFDd1TF+i0jKGPDRozno2NOJ9lTniso+taiv4kiVS8dgM8Jm5lg==", + "dependencies": { + "@types/tern": "*" + } + }, "node_modules/@types/d3": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.1.0.tgz", @@ -4542,6 +4551,11 @@ "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" }, + "node_modules/@types/marked": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-2.0.5.tgz", + "integrity": "sha512-shRZ7XnYFD/8n8zSjKvFdto1QNSf4tONZIlNEZGrJe8GsOE8DL/hG1Hbl8gZlfLnjS7+f5tZGIaTgfpyW38h4w==" + }, "node_modules/@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", @@ -4662,6 +4676,14 @@ "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==" }, + "node_modules/@types/tern": { + "version": "0.23.4", + "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz", + "integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==", + "dependencies": { + "@types/estree": "*" + } + }, "node_modules/@types/uglify-js": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz", @@ -6997,6 +7019,21 @@ "node": ">= 4.0" } }, + "node_modules/codemirror": { + "version": "5.65.0", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.0.tgz", + "integrity": "sha512-gWEnHKEcz1Hyz7fsQWpK7P0sPI2/kSkRX2tc7DFA6TmZuDN75x/1ejnH/Pn8adYKrLEA1V2ww6L00GudHZbSKw==", + "peer": true + }, + "node_modules/codemirror-spell-checker": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/codemirror-spell-checker/-/codemirror-spell-checker-1.1.2.tgz", + "integrity": "sha1-HGYPkIlIPMtRE7m6nKGcP0mTNx4=", + "peer": true, + "dependencies": { + "typo-js": "*" + } + }, "node_modules/collect-v8-coverage": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", @@ -8460,6 +8497,19 @@ "stream-shift": "^1.0.0" } }, + "node_modules/easymde": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/easymde/-/easymde-2.15.0.tgz", + "integrity": "sha512-9jMRIVvKt1d0UjRN45yotUYECAM4xvw0TTAQw8sYDONP++keWJVnd8Xrn+V+vQEN/v9/X0SWEoo1rFSgCooGpw==", + "peer": true, + "dependencies": { + "@types/codemirror": "0.0.109", + "@types/marked": "^2.0.2", + "codemirror": "^5.61.0", + "codemirror-spell-checker": "1.1.2", + "marked": "^2.0.3" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -14505,6 +14555,18 @@ "node": ">=0.10.0" } }, + "node_modules/marked": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-2.1.3.tgz", + "integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA==", + "peer": true, + "bin": { + "marked": "bin/marked" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -18587,6 +18649,20 @@ "node": ">=10" } }, + "node_modules/react-simplemde-editor": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/react-simplemde-editor/-/react-simplemde-editor-5.0.2.tgz", + "integrity": "sha512-yaqZSaUBf6B0kQY0mH8WP/nHnvJFz48aO8cMYCL1e/AFiuB/H8UDuyZFP9/exOtwVpaG373HYR1YedKMtCh+Kw==", + "dependencies": { + "@types/codemirror": "0.0.109", + "@types/marked": "^2.0.2" + }, + "peerDependencies": { + "easymde": ">= 2.0.0 < 3.0.0", + "react": ">=16.8.2", + "react-dom": ">=16.8.2" + } + }, "node_modules/read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -21767,6 +21843,12 @@ "node": ">=4.2.0" } }, + "node_modules/typo-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/typo-js/-/typo-js-1.2.1.tgz", + "integrity": "sha512-bTGLjbD3WqZDR3CgEFkyi9Q/SS2oM29ipXrWfDb4M74ea69QwKAECVceYpaBu0GfdnASMg9Qfl67ttB23nePHg==", + "peer": true + }, "node_modules/unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", @@ -27236,6 +27318,14 @@ "@babel/types": "^7.3.0" } }, + "@types/codemirror": { + "version": "0.0.109", + "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.109.tgz", + "integrity": "sha512-cSdiHeeLjvGn649lRTNeYrVCDOgDrtP+bDDSFDd1TF+i0jKGPDRozno2NOJ9lTniso+taiv4kiVS8dgM8Jm5lg==", + "requires": { + "@types/tern": "*" + } + }, "@types/d3": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.1.0.tgz", @@ -27582,6 +27672,11 @@ "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" }, + "@types/marked": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-2.0.5.tgz", + "integrity": "sha512-shRZ7XnYFD/8n8zSjKvFdto1QNSf4tONZIlNEZGrJe8GsOE8DL/hG1Hbl8gZlfLnjS7+f5tZGIaTgfpyW38h4w==" + }, "@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", @@ -27702,6 +27797,14 @@ "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==" }, + "@types/tern": { + "version": "0.23.4", + "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz", + "integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==", + "requires": { + "@types/estree": "*" + } + }, "@types/uglify-js": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz", @@ -29568,6 +29671,21 @@ "q": "^1.1.2" } }, + "codemirror": { + "version": "5.65.0", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.0.tgz", + "integrity": "sha512-gWEnHKEcz1Hyz7fsQWpK7P0sPI2/kSkRX2tc7DFA6TmZuDN75x/1ejnH/Pn8adYKrLEA1V2ww6L00GudHZbSKw==", + "peer": true + }, + "codemirror-spell-checker": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/codemirror-spell-checker/-/codemirror-spell-checker-1.1.2.tgz", + "integrity": "sha1-HGYPkIlIPMtRE7m6nKGcP0mTNx4=", + "peer": true, + "requires": { + "typo-js": "*" + } + }, "collect-v8-coverage": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", @@ -30732,6 +30850,19 @@ "stream-shift": "^1.0.0" } }, + "easymde": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/easymde/-/easymde-2.15.0.tgz", + "integrity": "sha512-9jMRIVvKt1d0UjRN45yotUYECAM4xvw0TTAQw8sYDONP++keWJVnd8Xrn+V+vQEN/v9/X0SWEoo1rFSgCooGpw==", + "peer": true, + "requires": { + "@types/codemirror": "0.0.109", + "@types/marked": "^2.0.2", + "codemirror": "^5.61.0", + "codemirror-spell-checker": "1.1.2", + "marked": "^2.0.3" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -35250,6 +35381,12 @@ "object-visit": "^1.0.0" } }, + "marked": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-2.1.3.tgz", + "integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA==", + "peer": true + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -38443,6 +38580,15 @@ } } }, + "react-simplemde-editor": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/react-simplemde-editor/-/react-simplemde-editor-5.0.2.tgz", + "integrity": "sha512-yaqZSaUBf6B0kQY0mH8WP/nHnvJFz48aO8cMYCL1e/AFiuB/H8UDuyZFP9/exOtwVpaG373HYR1YedKMtCh+Kw==", + "requires": { + "@types/codemirror": "0.0.109", + "@types/marked": "^2.0.2" + } + }, "read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -40922,6 +41068,12 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz", "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==" }, + "typo-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/typo-js/-/typo-js-1.2.1.tgz", + "integrity": "sha512-bTGLjbD3WqZDR3CgEFkyi9Q/SS2oM29ipXrWfDb4M74ea69QwKAECVceYpaBu0GfdnASMg9Qfl67ttB23nePHg==", + "peer": true + }, "unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", diff --git a/package.json b/package.json index 89e998c..b9eb952 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "react-redux": "^7.2.6", "react-router-dom": "^5.2.1", "react-scripts": "^4.0.3", + "react-simplemde-editor": "^5.0.2", "uplot": "^1.6.18", "uplot-react": "^1.1.1" }, diff --git a/src/App.less b/src/App.less index 5e94918..fbca29e 100644 --- a/src/App.less +++ b/src/App.less @@ -140,3 +140,17 @@ select:-webkit-autofill:focus { box-shadow: 0 0 0px 1000px @component-background inset; transition: background-color 5000s ease-in-out 0s; } + +.CodeMirror, .editor-preview { + color: @text !important; + background-color: @main !important; + border: none !important; +} + +.cm-s-easymde .CodeMirror-cursor { + border: 1px solid @text !important; +} + +.CodeMirror-wrap { + background-color: @main-light !important; +} diff --git a/src/pages/Upload.tsx b/src/pages/Upload.tsx index 2a08145..7dfb0a2 100644 --- a/src/pages/Upload.tsx +++ b/src/pages/Upload.tsx @@ -1,6 +1,7 @@ import { useCallback, useEffect, + useMemo, useState, } from 'react'; import { @@ -32,6 +33,7 @@ import { customAlphabet, nanoid, } from 'nanoid'; +import SimpleMdeReact from 'react-simplemde-editor'; import { emailNotVerified, restrictedPage, @@ -50,6 +52,8 @@ import { } from '../firebase'; import useStorage from '../hooks/useStorage'; +import 'easymde/dist/easymde.min.css'; + enum MaxFiles { TUNE_FILES = 1, LOG_FILES = 5, @@ -68,6 +72,7 @@ interface TuneDbData { logFiles?: string[]; toothLogFiles?: string[]; customIniFile?: string | null; + description?: string; } type Path = string; @@ -100,7 +105,6 @@ const baseUploadPath = 'public/users'; const UploadPage = () => { const [newTuneId, setNewTuneId] = useState(); const [isUserAuthorized, setIsUserAuthorized] = useState(false); - const hasNavigatorShare = navigator.share !== undefined; const [shareUrl, setShareUrl] = useState(); const [copied, setCopied] = useState(false); const [showOptions, setShowOptions] = useState(false); @@ -108,13 +112,15 @@ const UploadPage = () => { const [isPublished, setIsPublished] = useState(false); const [isPublic, setIsPublic] = useState(true); const [isListed, setIsListed] = useState(true); - const { currentUser, refreshToken } = useAuth(); - const history = useHistory(); - const { storageSet, storageGet, storageDelete } = useStorage(); + const [description, setDescription] = useState('# My Tune \ndescription'); const [tuneFile, setTuneFile] = useState(null); const [logFiles, setLogFiles] = useState({}); const [toothLogFiles, setToothLogFiles] = useState({}); const [customIniFile, setCustomIniFile] = useState(null); + const hasNavigatorShare = navigator.share !== undefined; + const { currentUser, refreshToken } = useAuth(); + const history = useHistory(); + const { storageSet, storageGet, storageDelete } = useStorage(); const copyToClipboard = async () => { if (navigator.clipboard) { @@ -126,6 +132,11 @@ const UploadPage = () => { const genericError = (error: Error) => notification.error({ message: 'Error', description: error.message }); + const editorOptions = useMemo(() => ({ + toolbar: false, + autofocus: true, + }), []); + const updateDbData = (tuneId: string, dbData: TuneDbData) => { try { return setDoc(fireStoreDoc(db, 'tunes', tuneId), dbData, { merge: true }); @@ -163,6 +174,7 @@ const UploadPage = () => { isPublished: true, isPublic, isListed, + description, }); setIsPublished(true); setIsLoading(false); @@ -242,6 +254,7 @@ const UploadPage = () => { logFiles: [], toothLogFiles: [], customIniFile: null, + description: '', }; await updateDbData(newTuneId!, tuneData); } @@ -427,6 +440,17 @@ const UploadPage = () => { > {Object.keys(toothLogFiles).length < MaxFiles.TOOTH_LOG_FILES && uploadButton} + + + Description + (markdown) + + + Show more: