diff --git a/src/App.less b/src/App.less index 98fa74a..0d3b660 100644 --- a/src/App.less +++ b/src/App.less @@ -141,20 +141,6 @@ select:-webkit-autofill:focus { 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; -} - .markdown-preview { background-color: @main-light; padding: 5px 11px; @@ -162,4 +148,27 @@ select:-webkit-autofill:focus { border-width: 1px; border-radius: @border-radius-base; border-color: @main-dark; + + h1 { + font-size: 2em; + } + + code, pre { + background-color: @main; + border-radius: @border-radius-base; + } + + pre { + padding: 0.5rem; + } + + p code { + padding: 0.3rem; + } +} + +.upload-readme { + textarea { + resize: none; + } } diff --git a/src/pages/Upload.tsx b/src/pages/Upload.tsx index cc2188d..8d57cf0 100644 --- a/src/pages/Upload.tsx +++ b/src/pages/Upload.tsx @@ -5,10 +5,13 @@ import { } from 'react'; import { Button, + Col, Divider, Input, + InputNumber, notification, Row, + Select, Skeleton, Space, Switch, @@ -64,6 +67,22 @@ enum MaxFiles { CUSTOM_INI_FILES = 1, } +interface TuneDataDetails { + readme?: string; + make?: string; + model?: string; + displacement?: string; + year?: number; + hp?: number; + stockHp?: number; + engineCode?: string; + cylinders?: number; + aspiration?: string; + fuel?: string; + injectors?: string; + coils?: string; +} + interface TuneDbData { userUid?: string; createdAt?: Date; @@ -75,7 +94,7 @@ interface TuneDbData { logFiles?: string[]; toothLogFiles?: string[]; customIniFile?: string | null; - description?: string; + details?: TuneDataDetails; } type Path = string; @@ -101,8 +120,10 @@ const containerStyle = { margin: '0 auto', }; -const NEW_TUNE_ID_KEY = 'newTuneId'; -const MAX_FILE_SIZE_MB = 10; +const newTuneIdKey = 'newTuneId'; +const maxFileSizeMB = 10; +const descriptionEditorHeight = 260; +const rowProps = { gutter: 10, style: { marginBottom: 10 } }; const tuneIcon = () => ; const logIcon = () => ; @@ -117,12 +138,11 @@ const UploadPage = () => { const [isUserAuthorized, setIsUserAuthorized] = useState(false); const [shareUrl, setShareUrl] = useState(); const [copied, setCopied] = useState(false); - const [showOptions, setShowOptions] = useState(false); + const [showDetails, setShowDetails] = useState(false); const [isLoading, setIsLoading] = useState(false); const [isPublished, setIsPublished] = useState(false); const [isPublic, setIsPublic] = useState(true); const [isListed, setIsListed] = useState(true); - const [description, setDescription] = useState('# My Tune\n\ndescription'); const [tuneFile, setTuneFile] = useState(null); const [logFiles, setLogFiles] = useState({}); const [toothLogFiles, setToothLogFiles] = useState({}); @@ -132,6 +152,21 @@ const UploadPage = () => { const history = useHistory(); const { storageSet, storageGet, storageDelete } = useStorage(); + // details + const [readme, setReadme] = useState('# My Tune\n\ndescription'); + const [make, setMake] = useState(); + const [model, setModel] = useState(); + const [displacement, setDisplacement] = useState(); + const [year, setYear] = useState(); + const [hp, setHp] = useState(); + const [stockHp, setStockHp] = useState(); + const [engineCode, setEngineCode] = useState(); + const [cylinders, setCylinders] = useState(); + const [aspiration, setAspiration] = useState(); + const [fuel, setFuel] = useState(); + const [injectors, setInjectors] = useState(); + const [coils, setCoils] = useState(); + const noop = () => { }; const copyToClipboard = async () => { @@ -179,16 +214,30 @@ const UploadPage = () => { isPublished: true, isPublic, isListed, - description, + details: { + readme, + make, + model, + displacement, + year, + hp, + stockHp, + engineCode, + cylinders, + aspiration, + fuel, + injectors, + coils, + }, }); setIsPublished(true); setIsLoading(false); - storageDelete(NEW_TUNE_ID_KEY); + storageDelete(newTuneIdKey); }; const validateSize = (file: File) => Promise.resolve({ - result: (file.size / 1024 / 1024) <= MAX_FILE_SIZE_MB, - message: `File should not be larger than ${MAX_FILE_SIZE_MB}MB!`, + result: (file.size / 1024 / 1024) <= maxFileSizeMB, + message: `File should not be larger than ${maxFileSizeMB}MB!`, }); const upload = async (path: string, options: UploadRequestOption, done: Function, validate: ValidateFile) => { @@ -265,7 +314,7 @@ const UploadPage = () => { logFiles: [], toothLogFiles: [], customIniFile: null, - description: '', + details: {}, }; await updateDbData(newTuneId!, tuneData); } @@ -449,15 +498,15 @@ const UploadPage = () => { } setIsUserAuthorized(true); } catch (error) { - storageDelete(NEW_TUNE_ID_KEY); + storageDelete(newTuneIdKey); console.error(error); genericError(error as Error); } - let newTuneIdTemp = await storageGet(NEW_TUNE_ID_KEY); + let newTuneIdTemp = await storageGet(newTuneIdKey); if (!newTuneIdTemp) { newTuneIdTemp = nanoidCustom(); - await storageSet(NEW_TUNE_ID_KEY, newTuneIdTemp); + await storageSet(newTuneIdKey, newTuneIdTemp); } setNewTuneId(newTuneIdTemp); }, [currentUser, history, refreshToken, storageDelete, storageGet, storageSet]); @@ -505,6 +554,116 @@ const UploadPage = () => { ); + const detailsSection = ( + <> + + + Upload Custom INI + (.ini) + + + + {!customIniFile && uploadButton} + + + + README + (markdown) + + + + + setReadme(e.target.value)} + maxLength={3_000} + /> + + +
+ + {readme} + +
+
+
+ + + setMake(e.target.value)} /> + + + setModel(e.target.value)} /> + + + + + + + + setDisplacement(e.target.value)} /> + + + + + + + + + + + + + setEngineCode(e.target.value)} /> + + + + + + + + + + + setFuel(e.target.value)} /> + + + + + setInjectors(e.target.value)} /> + + + setCoils(e.target.value)} /> + + + + Visibility + + + + Public: + + + Listed: + + + + ); + const optionalSection = ( <> @@ -546,65 +705,11 @@ const UploadPage = () => { > {Object.keys(toothLogFiles).length < MaxFiles.TOOTH_LOG_FILES && uploadButton} - - - Description - (markdown) - - - - - setDescription(e.target.value)} - maxLength={3_000} - /> - - -
- - {description} - -
-
-
- Show more: - + Show details: + - {showOptions && <> - - - Upload Custom INI - (.ini) - - - - {!customIniFile && uploadButton} - - - Visibility - - - - Public: - - - Listed: - - - } + {showDetails && detailsSection} {shareUrl && tuneFile && shareSection} );