Add markdown description editor (#361)

This commit is contained in:
Piotr Rogowski 2022-01-05 00:22:31 +01:00 committed by GitHub
parent da10d29b42
commit 0aaa10307b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 195 additions and 4 deletions

152
package-lock.json generated
View File

@ -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",

View File

@ -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"
},

View File

@ -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;
}

View File

@ -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<string>();
const [isUserAuthorized, setIsUserAuthorized] = useState(false);
const hasNavigatorShare = navigator.share !== undefined;
const [shareUrl, setShareUrl] = useState<string>();
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<UploadedFile | null>(null);
const [logFiles, setLogFiles] = useState<UploadedFile>({});
const [toothLogFiles, setToothLogFiles] = useState<UploadedFile>({});
const [customIniFile, setCustomIniFile] = useState<UploadedFile | null>(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}
</Upload>
<Divider>
<Space>
Description
<Typography.Text type="secondary">(markdown)</Typography.Text>
</Space>
</Divider>
<SimpleMdeReact
onChange={setDescription}
value={description}
options={editorOptions}
/>
<Space style={{ marginTop: 30 }}>
Show more:
<Switch checked={showOptions} onChange={setShowOptions} />