Compare commits
3 Commits
bd271021f1
...
9e7b456400
| Author | SHA1 | Date | |
|---|---|---|---|
| 9e7b456400 | |||
| 7cc9fd7722 | |||
| c036d7d5ca |
@@ -9,6 +9,7 @@
|
|||||||
"@types/react": "^17.0.0",
|
"@types/react": "^17.0.0",
|
||||||
"@types/react-dom": "^17.0.0",
|
"@types/react-dom": "^17.0.0",
|
||||||
"autoprefixer": "^9",
|
"autoprefixer": "^9",
|
||||||
|
"copy-to-clipboard": "^3.3.1",
|
||||||
"postcss": "^7",
|
"postcss": "^7",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
|
|||||||
@@ -1,26 +1,61 @@
|
|||||||
import React, { useState } from "react"
|
import React, { useEffect, useState } from "react"
|
||||||
|
import copy from "copy-to-clipboard"
|
||||||
import RetakesConfig from "../types/RetakesConfig"
|
import RetakesConfig from "../types/RetakesConfig"
|
||||||
import AllDecks from "./AllDecks"
|
import AllDecks from "./AllDecks"
|
||||||
import MenuBar from "./MenuBar"
|
import MenuBar from "./MenuBar"
|
||||||
|
import Modal from "./Modal"
|
||||||
|
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
const [retakesConfig,setRetakesConfig] = useState(new RetakesConfig())
|
const [retakesConfig,setRetakesConfig] = useState(new RetakesConfig())
|
||||||
|
const [showExport,setShowExport] = useState(false)
|
||||||
|
const [exportText,setExportText] = useState("")
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
// Load saved config
|
||||||
|
const retakesJSON = window.localStorage.getItem("retakesJSON")
|
||||||
|
if (retakesJSON){
|
||||||
|
try{
|
||||||
|
const parsedConfig: RetakesConfig = JSON.parse(retakesJSON)
|
||||||
|
setRetakesConfig(parsedConfig)
|
||||||
|
}catch(err){
|
||||||
|
window.localStorage.removeItem("retakesJSON")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},[])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-white">
|
<div className="text-white">
|
||||||
<MenuBar
|
<MenuBar
|
||||||
onExport={()=>{
|
onExport={()=>{
|
||||||
const exportString = retakesConfig.toCvar()
|
setExportText(retakesConfig.toCvar())
|
||||||
console.log(exportString)
|
setShowExport(true)
|
||||||
}}
|
}}
|
||||||
onExportJson={()=>{
|
onExportJson={()=>{
|
||||||
|
setExportText(JSON.stringify(retakesConfig))
|
||||||
|
setShowExport(true)
|
||||||
|
}}
|
||||||
|
onSave={()=>{
|
||||||
const jsonString = JSON.stringify(retakesConfig)
|
const jsonString = JSON.stringify(retakesConfig)
|
||||||
console.log(jsonString)
|
window.localStorage.setItem("retakesJSON",jsonString)
|
||||||
}}
|
// TODO: user feedback that config was saved
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<AllDecks retakesConfig={retakesConfig} onChange={(newConfig)=>setRetakesConfig(newConfig)} />
|
<AllDecks retakesConfig={retakesConfig} onChange={(newConfig)=>setRetakesConfig(newConfig)} />
|
||||||
|
|
||||||
|
<Modal show={showExport} onCloseClick={()=>setShowExport(false)}>
|
||||||
|
<div className="flex justify-center mb-2">
|
||||||
|
<textarea
|
||||||
|
cols={50} rows={10}
|
||||||
|
value={exportText}
|
||||||
|
readOnly
|
||||||
|
className="bg-transparent border-2 border-gray-900"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="bg-gray-700 button flex justify-center"
|
||||||
|
onClick={()=>copy(exportText)}
|
||||||
|
>Copy to clipboard</div>
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,10 @@ import React from "react"
|
|||||||
interface Props {
|
interface Props {
|
||||||
onExport?: ()=>void
|
onExport?: ()=>void
|
||||||
onExportJson?: ()=>void
|
onExportJson?: ()=>void
|
||||||
|
onSave?:()=>void
|
||||||
}
|
}
|
||||||
|
|
||||||
const MenuBar: React.FC<Props> = ({onExport,onExportJson}) => {
|
const MenuBar: React.FC<Props> = ({onExport,onExportJson,onSave}) => {
|
||||||
return (
|
return (
|
||||||
<div className="bg-gray-800 h-10 m-1 p-1 flex">
|
<div className="bg-gray-800 h-10 m-1 p-1 flex">
|
||||||
<div className="bg-gray-700 button" onClick={onExport}>
|
<div className="bg-gray-700 button" onClick={onExport}>
|
||||||
@@ -13,6 +14,9 @@ const MenuBar: React.FC<Props> = ({onExport,onExportJson}) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="bg-gray-700 button" onClick={onExportJson}>
|
<div className="bg-gray-700 button" onClick={onExportJson}>
|
||||||
Export to JSON
|
Export to JSON
|
||||||
|
</div>
|
||||||
|
<div className="bg-gray-700 button" onClick={onSave}>
|
||||||
|
Save
|
||||||
</div>
|
</div>
|
||||||
<a href="https://developer.valvesoftware.com/wiki/CS:GO_Game_Mode_-_Retakes" target="_blank" rel='noreferrer'>
|
<a href="https://developer.valvesoftware.com/wiki/CS:GO_Game_Mode_-_Retakes" target="_blank" rel='noreferrer'>
|
||||||
<div className="bg-gray-700 button">
|
<div className="bg-gray-700 button">
|
||||||
|
|||||||
26
src/components/Modal.tsx
Normal file
26
src/components/Modal.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import React from "react"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
show: boolean
|
||||||
|
onCloseClick?: ()=>void
|
||||||
|
}
|
||||||
|
|
||||||
|
const Modal: React.FC<Props> = ({children,show,onCloseClick}) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`${!show?"hidden":"" }
|
||||||
|
fixed z-10 left-0 top-0 w-full h-full
|
||||||
|
flex justify-center items-center bg-gray-900 bg-opacity-80`}
|
||||||
|
onClick={()=>{
|
||||||
|
onCloseClick?.()
|
||||||
|
}}>
|
||||||
|
<div className="bg-gray-800 mx-auto p-5 border-2 border-gray-800 w-10/12 overflow-hidden max-h-full" onClick={(e)=>{
|
||||||
|
e.stopPropagation()
|
||||||
|
}}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Modal
|
||||||
12
yarn.lock
12
yarn.lock
@@ -3649,6 +3649,13 @@ copy-descriptor@^0.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
|
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
|
||||||
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
|
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
|
||||||
|
|
||||||
|
copy-to-clipboard@^3.3.1:
|
||||||
|
version "3.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae"
|
||||||
|
integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==
|
||||||
|
dependencies:
|
||||||
|
toggle-selection "^1.0.6"
|
||||||
|
|
||||||
core-js-compat@^3.18.0, core-js-compat@^3.19.0, core-js-compat@^3.6.2:
|
core-js-compat@^3.18.0, core-js-compat@^3.19.0, core-js-compat@^3.6.2:
|
||||||
version "3.19.1"
|
version "3.19.1"
|
||||||
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.19.1.tgz#fe598f1a9bf37310d77c3813968e9f7c7bb99476"
|
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.19.1.tgz#fe598f1a9bf37310d77c3813968e9f7c7bb99476"
|
||||||
@@ -10836,6 +10843,11 @@ to-regex@^3.0.1, to-regex@^3.0.2:
|
|||||||
regex-not "^1.0.2"
|
regex-not "^1.0.2"
|
||||||
safe-regex "^1.1.0"
|
safe-regex "^1.1.0"
|
||||||
|
|
||||||
|
toggle-selection@^1.0.6:
|
||||||
|
version "1.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
|
||||||
|
integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI=
|
||||||
|
|
||||||
toidentifier@1.0.0:
|
toidentifier@1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
||||||
|
|||||||
Reference in New Issue
Block a user