Hub - initial commit (#393)
This commit is contained in:
parent
1b1352df47
commit
5e81493569
|
@ -10,11 +10,11 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@reduxjs/toolkit": "^1.7.1",
|
"@reduxjs/toolkit": "^1.7.1",
|
||||||
"@sentry/react": "^6.16.1",
|
"@sentry/react": "^6.17.0",
|
||||||
"@sentry/tracing": "^6.16.1",
|
"@sentry/tracing": "^6.17.0",
|
||||||
"@speedy-tuner/ini": "^0.3.0",
|
"@speedy-tuner/ini": "^0.3.0",
|
||||||
"@speedy-tuner/types": "^0.3.0",
|
"@speedy-tuner/types": "^0.3.0",
|
||||||
"antd": "^4.18.4",
|
"antd": "^4.18.5",
|
||||||
"firebase": "^9.6.4",
|
"firebase": "^9.6.4",
|
||||||
"kbar": "^0.1.0-beta.27",
|
"kbar": "^0.1.0-beta.27",
|
||||||
"mlg-converter": "^0.5.1",
|
"mlg-converter": "^0.5.1",
|
||||||
|
@ -3828,13 +3828,13 @@
|
||||||
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="
|
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/browser": {
|
"node_modules/@sentry/browser": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.17.1.tgz",
|
||||||
"integrity": "sha512-F2I5RL7RTLQF9CccMrqt73GRdK3FdqaChED3RulGQX5lH6U3exHGFxwyZxSrY4x6FedfBFYlfXWWCJXpLnFkow==",
|
"integrity": "sha512-Tj4uXNRA6dAwKzOwLGvTOsD8WNk6tiPaIYXPsIIOdBjDsFBfiu4JY8ygCzQpj7Fwy8qL6UULygU4kBuAx2ieyQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/core": "6.16.1",
|
"@sentry/core": "6.17.1",
|
||||||
"@sentry/types": "6.16.1",
|
"@sentry/types": "6.17.1",
|
||||||
"@sentry/utils": "6.16.1",
|
"@sentry/utils": "6.17.1",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -3842,14 +3842,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/core": {
|
"node_modules/@sentry/core": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.17.1.tgz",
|
||||||
"integrity": "sha512-UFI0264CPUc5cR1zJH+S2UPOANpm6dLJOnsvnIGTjsrwzR0h8Hdl6rC2R/GPq+WNbnipo9hkiIwDlqbqvIU5vw==",
|
"integrity": "sha512-dRcKs3+IKx2w7+xwg3mWRc4ghjnY+36W+qCOJXRbWyRjlzb67Es+TDYY3BxWwN4beNr2dvQkRt5HoPxJnrzGVQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/hub": "6.16.1",
|
"@sentry/hub": "6.17.1",
|
||||||
"@sentry/minimal": "6.16.1",
|
"@sentry/minimal": "6.17.1",
|
||||||
"@sentry/types": "6.16.1",
|
"@sentry/types": "6.17.1",
|
||||||
"@sentry/utils": "6.16.1",
|
"@sentry/utils": "6.17.1",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -3857,12 +3857,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/hub": {
|
"node_modules/@sentry/hub": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.17.1.tgz",
|
||||||
"integrity": "sha512-4PGtg6AfpqMkreTpL7ymDeQ/U1uXv03bKUuFdtsSTn/FRf9TLS4JB0KuTZCxfp1IRgAA+iFg6B784dDkT8R9eg==",
|
"integrity": "sha512-14lNcM4kt2sKhsfZ6WG2gbsPMydxBAY1OSk+WodO/x0Esdr7VbaVngSJSFzCI0iRBPLSQuFVtUWaAZzSF+WdiA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/types": "6.16.1",
|
"@sentry/types": "6.17.1",
|
||||||
"@sentry/utils": "6.16.1",
|
"@sentry/utils": "6.17.1",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -3870,12 +3870,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/minimal": {
|
"node_modules/@sentry/minimal": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.17.1.tgz",
|
||||||
"integrity": "sha512-dq+mI1EQIvUM+zJtGCVgH3/B3Sbx4hKlGf2Usovm9KoqWYA+QpfVBholYDe/H2RXgO7LFEefDLvOdHDkqeJoyA==",
|
"integrity": "sha512-0V5YqVCylMjjDhD98Xod1ZdxzVRUjDSq7ssCJ2PRjfRAEtk7mN5oeznyZUhyx4pZB8hNh2G9PdasIR2WIjYN9w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/hub": "6.16.1",
|
"@sentry/hub": "6.17.1",
|
||||||
"@sentry/types": "6.16.1",
|
"@sentry/types": "6.17.1",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -3883,14 +3883,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/react": {
|
"node_modules/@sentry/react": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-6.17.1.tgz",
|
||||||
"integrity": "sha512-n8fOEKbym4kBi946q3AWXBNy1UKTmABj/hE2nAJbTWhi5IwdM7WBG6QCT2yq7oTHLuTxQrAwgKQc+A6zFTyVHg==",
|
"integrity": "sha512-Woq1QCtpXv4yXetOv68/V61vaUIVrcs7K0SZ3GZxdMJMmu3hpECFZIClFYE4z2fFT/ygueGJoGAL177R7/U3Vw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/browser": "6.16.1",
|
"@sentry/browser": "6.17.1",
|
||||||
"@sentry/minimal": "6.16.1",
|
"@sentry/minimal": "6.17.1",
|
||||||
"@sentry/types": "6.16.1",
|
"@sentry/types": "6.17.1",
|
||||||
"@sentry/utils": "6.16.1",
|
"@sentry/utils": "6.17.1",
|
||||||
"hoist-non-react-statics": "^3.3.2",
|
"hoist-non-react-statics": "^3.3.2",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
|
@ -3902,14 +3902,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/tracing": {
|
"node_modules/@sentry/tracing": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.17.1.tgz",
|
||||||
"integrity": "sha512-MPSbqXX59P+OEeST+U2V/8Hu/8QjpTUxTNeNyTHWIbbchdcMMjDbXTS3etCgajZR6Ro+DHElOz5cdSxH6IBGlA==",
|
"integrity": "sha512-2to3Y3I+kdoJWdbPbK4llALXc+765W0SAAghFWEJ5L3mups59CGf03HtRHPE8p2Hw2Tr6YO6gjtZhvm+I49LPg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/hub": "6.16.1",
|
"@sentry/hub": "6.17.1",
|
||||||
"@sentry/minimal": "6.16.1",
|
"@sentry/minimal": "6.17.1",
|
||||||
"@sentry/types": "6.16.1",
|
"@sentry/types": "6.17.1",
|
||||||
"@sentry/utils": "6.16.1",
|
"@sentry/utils": "6.17.1",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -3917,19 +3917,19 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/types": {
|
"node_modules/@sentry/types": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.17.1.tgz",
|
||||||
"integrity": "sha512-Wh354g30UsJ5kYJbercektGX4ZMc9MHU++1NjeN2bTMnbofEcpUDWIiKeulZEY65IC1iU+1zRQQgtYO+/hgCUQ==",
|
"integrity": "sha512-EBFiN3utd1xoxowy+WFSDQGgS4J+VEZbc7j3uYVZNjn03/w5pe9FfeLsszJ2s1/hCf/K7GAGH4NA7i0r7SWF3g==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/utils": {
|
"node_modules/@sentry/utils": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.17.1.tgz",
|
||||||
"integrity": "sha512-7ngq/i4R8JZitJo9Sl8PDnjSbDehOxgr1vsoMmerIsyRZ651C/8B+jVkMhaAPgSdyJ0AlE3O7DKKTP1FXFw9qw==",
|
"integrity": "sha512-FOjxMZ4yBflYvJYhNDacRfSa0NTKLsjCXQ3u1phxODRUwhQ7wwqmtwy86AL5uzfpiqZKwXAPlWoWihBluw7vqw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/types": "6.16.1",
|
"@sentry/types": "6.17.1",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -5356,22 +5356,21 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/antd": {
|
"node_modules/antd": {
|
||||||
"version": "4.18.4",
|
"version": "4.18.5",
|
||||||
"resolved": "https://registry.npmjs.org/antd/-/antd-4.18.4.tgz",
|
"resolved": "https://registry.npmjs.org/antd/-/antd-4.18.5.tgz",
|
||||||
"integrity": "sha512-7KCEhIyPeQJF/OenkfOTcx+5sHpiI5U6OzYmTUJn9wVPjcl07eFXu2w9teM9pJV9X7mSUWyPeM5aMFmBQo2TNQ==",
|
"integrity": "sha512-5fN3C2lWAzonhOYYlNpzIw2OHl7vxFZ+4cJ7DK/XZrV+75OY61Y+OkanqMJwrFtDDamIez35OM7cAezGko9tew==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/colors": "^6.0.0",
|
"@ant-design/colors": "^6.0.0",
|
||||||
"@ant-design/icons": "^4.7.0",
|
"@ant-design/icons": "^4.7.0",
|
||||||
"@ant-design/react-slick": "~0.28.1",
|
"@ant-design/react-slick": "~0.28.1",
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
"@ctrl/tinycolor": "^3.4.0",
|
"@ctrl/tinycolor": "^3.4.0",
|
||||||
"array-tree-filter": "^2.1.0",
|
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"copy-to-clipboard": "^3.2.0",
|
"copy-to-clipboard": "^3.2.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"memoize-one": "^6.0.0",
|
"memoize-one": "^6.0.0",
|
||||||
"moment": "^2.25.3",
|
"moment": "^2.25.3",
|
||||||
"rc-cascader": "~3.0.0-alpha.8",
|
"rc-cascader": "~3.2.1",
|
||||||
"rc-checkbox": "~2.3.0",
|
"rc-checkbox": "~2.3.0",
|
||||||
"rc-collapse": "~3.1.0",
|
"rc-collapse": "~3.1.0",
|
||||||
"rc-dialog": "~8.6.0",
|
"rc-dialog": "~8.6.0",
|
||||||
|
@ -5398,7 +5397,7 @@
|
||||||
"rc-textarea": "~0.3.0",
|
"rc-textarea": "~0.3.0",
|
||||||
"rc-tooltip": "~5.1.1",
|
"rc-tooltip": "~5.1.1",
|
||||||
"rc-tree": "~5.4.3",
|
"rc-tree": "~5.4.3",
|
||||||
"rc-tree-select": "~5.1.0",
|
"rc-tree-select": "~5.1.1",
|
||||||
"rc-trigger": "^5.2.10",
|
"rc-trigger": "^5.2.10",
|
||||||
"rc-upload": "~4.3.0",
|
"rc-upload": "~4.3.0",
|
||||||
"rc-util": "^5.14.0",
|
"rc-util": "^5.14.0",
|
||||||
|
@ -18329,14 +18328,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rc-cascader": {
|
"node_modules/rc-cascader": {
|
||||||
"version": "3.0.0-alpha.8",
|
"version": "3.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.0.0-alpha.8.tgz",
|
"resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.2.1.tgz",
|
||||||
"integrity": "sha512-zZ6tczHacUy622E7m5aruCcB3ii+J5bhusCPpyb64LP9KbcKcquchdgWeeyVY/7K8BrJXOTOJW1MDZ9nxsWBWw==",
|
"integrity": "sha512-Raxam9tFzBL4TCgHoyVcf7+Q2KSFneUk3FZXi9w1tfxEihLlezSH0oCNMjHJN8hxWwwx9ZbI9UzWTfFImjXc0Q==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
"array-tree-filter": "^2.1.0",
|
"array-tree-filter": "^2.1.0",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
"rc-select": "~14.0.0-alpha.8",
|
"rc-select": "~14.0.0-alpha.23",
|
||||||
"rc-tree": "~5.4.3",
|
"rc-tree": "~5.4.3",
|
||||||
"rc-util": "^5.6.1"
|
"rc-util": "^5.6.1"
|
||||||
},
|
},
|
||||||
|
@ -28086,84 +28085,84 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/browser": {
|
"@sentry/browser": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.17.1.tgz",
|
||||||
"integrity": "sha512-F2I5RL7RTLQF9CccMrqt73GRdK3FdqaChED3RulGQX5lH6U3exHGFxwyZxSrY4x6FedfBFYlfXWWCJXpLnFkow==",
|
"integrity": "sha512-Tj4uXNRA6dAwKzOwLGvTOsD8WNk6tiPaIYXPsIIOdBjDsFBfiu4JY8ygCzQpj7Fwy8qL6UULygU4kBuAx2ieyQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/core": "6.16.1",
|
"@sentry/core": "6.17.1",
|
||||||
"@sentry/types": "6.16.1",
|
"@sentry/types": "6.17.1",
|
||||||
"@sentry/utils": "6.16.1",
|
"@sentry/utils": "6.17.1",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/core": {
|
"@sentry/core": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.17.1.tgz",
|
||||||
"integrity": "sha512-UFI0264CPUc5cR1zJH+S2UPOANpm6dLJOnsvnIGTjsrwzR0h8Hdl6rC2R/GPq+WNbnipo9hkiIwDlqbqvIU5vw==",
|
"integrity": "sha512-dRcKs3+IKx2w7+xwg3mWRc4ghjnY+36W+qCOJXRbWyRjlzb67Es+TDYY3BxWwN4beNr2dvQkRt5HoPxJnrzGVQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/hub": "6.16.1",
|
"@sentry/hub": "6.17.1",
|
||||||
"@sentry/minimal": "6.16.1",
|
"@sentry/minimal": "6.17.1",
|
||||||
"@sentry/types": "6.16.1",
|
"@sentry/types": "6.17.1",
|
||||||
"@sentry/utils": "6.16.1",
|
"@sentry/utils": "6.17.1",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/hub": {
|
"@sentry/hub": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.17.1.tgz",
|
||||||
"integrity": "sha512-4PGtg6AfpqMkreTpL7ymDeQ/U1uXv03bKUuFdtsSTn/FRf9TLS4JB0KuTZCxfp1IRgAA+iFg6B784dDkT8R9eg==",
|
"integrity": "sha512-14lNcM4kt2sKhsfZ6WG2gbsPMydxBAY1OSk+WodO/x0Esdr7VbaVngSJSFzCI0iRBPLSQuFVtUWaAZzSF+WdiA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/types": "6.16.1",
|
"@sentry/types": "6.17.1",
|
||||||
"@sentry/utils": "6.16.1",
|
"@sentry/utils": "6.17.1",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/minimal": {
|
"@sentry/minimal": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.17.1.tgz",
|
||||||
"integrity": "sha512-dq+mI1EQIvUM+zJtGCVgH3/B3Sbx4hKlGf2Usovm9KoqWYA+QpfVBholYDe/H2RXgO7LFEefDLvOdHDkqeJoyA==",
|
"integrity": "sha512-0V5YqVCylMjjDhD98Xod1ZdxzVRUjDSq7ssCJ2PRjfRAEtk7mN5oeznyZUhyx4pZB8hNh2G9PdasIR2WIjYN9w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/hub": "6.16.1",
|
"@sentry/hub": "6.17.1",
|
||||||
"@sentry/types": "6.16.1",
|
"@sentry/types": "6.17.1",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/react": {
|
"@sentry/react": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-6.17.1.tgz",
|
||||||
"integrity": "sha512-n8fOEKbym4kBi946q3AWXBNy1UKTmABj/hE2nAJbTWhi5IwdM7WBG6QCT2yq7oTHLuTxQrAwgKQc+A6zFTyVHg==",
|
"integrity": "sha512-Woq1QCtpXv4yXetOv68/V61vaUIVrcs7K0SZ3GZxdMJMmu3hpECFZIClFYE4z2fFT/ygueGJoGAL177R7/U3Vw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/browser": "6.16.1",
|
"@sentry/browser": "6.17.1",
|
||||||
"@sentry/minimal": "6.16.1",
|
"@sentry/minimal": "6.17.1",
|
||||||
"@sentry/types": "6.16.1",
|
"@sentry/types": "6.17.1",
|
||||||
"@sentry/utils": "6.16.1",
|
"@sentry/utils": "6.17.1",
|
||||||
"hoist-non-react-statics": "^3.3.2",
|
"hoist-non-react-statics": "^3.3.2",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/tracing": {
|
"@sentry/tracing": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.17.1.tgz",
|
||||||
"integrity": "sha512-MPSbqXX59P+OEeST+U2V/8Hu/8QjpTUxTNeNyTHWIbbchdcMMjDbXTS3etCgajZR6Ro+DHElOz5cdSxH6IBGlA==",
|
"integrity": "sha512-2to3Y3I+kdoJWdbPbK4llALXc+765W0SAAghFWEJ5L3mups59CGf03HtRHPE8p2Hw2Tr6YO6gjtZhvm+I49LPg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/hub": "6.16.1",
|
"@sentry/hub": "6.17.1",
|
||||||
"@sentry/minimal": "6.16.1",
|
"@sentry/minimal": "6.17.1",
|
||||||
"@sentry/types": "6.16.1",
|
"@sentry/types": "6.17.1",
|
||||||
"@sentry/utils": "6.16.1",
|
"@sentry/utils": "6.17.1",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/types": {
|
"@sentry/types": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.17.1.tgz",
|
||||||
"integrity": "sha512-Wh354g30UsJ5kYJbercektGX4ZMc9MHU++1NjeN2bTMnbofEcpUDWIiKeulZEY65IC1iU+1zRQQgtYO+/hgCUQ=="
|
"integrity": "sha512-EBFiN3utd1xoxowy+WFSDQGgS4J+VEZbc7j3uYVZNjn03/w5pe9FfeLsszJ2s1/hCf/K7GAGH4NA7i0r7SWF3g=="
|
||||||
},
|
},
|
||||||
"@sentry/utils": {
|
"@sentry/utils": {
|
||||||
"version": "6.16.1",
|
"version": "6.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.17.1.tgz",
|
||||||
"integrity": "sha512-7ngq/i4R8JZitJo9Sl8PDnjSbDehOxgr1vsoMmerIsyRZ651C/8B+jVkMhaAPgSdyJ0AlE3O7DKKTP1FXFw9qw==",
|
"integrity": "sha512-FOjxMZ4yBflYvJYhNDacRfSa0NTKLsjCXQ3u1phxODRUwhQ7wwqmtwy86AL5uzfpiqZKwXAPlWoWihBluw7vqw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/types": "6.16.1",
|
"@sentry/types": "6.17.1",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -29224,22 +29223,21 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"antd": {
|
"antd": {
|
||||||
"version": "4.18.4",
|
"version": "4.18.5",
|
||||||
"resolved": "https://registry.npmjs.org/antd/-/antd-4.18.4.tgz",
|
"resolved": "https://registry.npmjs.org/antd/-/antd-4.18.5.tgz",
|
||||||
"integrity": "sha512-7KCEhIyPeQJF/OenkfOTcx+5sHpiI5U6OzYmTUJn9wVPjcl07eFXu2w9teM9pJV9X7mSUWyPeM5aMFmBQo2TNQ==",
|
"integrity": "sha512-5fN3C2lWAzonhOYYlNpzIw2OHl7vxFZ+4cJ7DK/XZrV+75OY61Y+OkanqMJwrFtDDamIez35OM7cAezGko9tew==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ant-design/colors": "^6.0.0",
|
"@ant-design/colors": "^6.0.0",
|
||||||
"@ant-design/icons": "^4.7.0",
|
"@ant-design/icons": "^4.7.0",
|
||||||
"@ant-design/react-slick": "~0.28.1",
|
"@ant-design/react-slick": "~0.28.1",
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
"@ctrl/tinycolor": "^3.4.0",
|
"@ctrl/tinycolor": "^3.4.0",
|
||||||
"array-tree-filter": "^2.1.0",
|
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"copy-to-clipboard": "^3.2.0",
|
"copy-to-clipboard": "^3.2.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"memoize-one": "^6.0.0",
|
"memoize-one": "^6.0.0",
|
||||||
"moment": "^2.25.3",
|
"moment": "^2.25.3",
|
||||||
"rc-cascader": "~3.0.0-alpha.8",
|
"rc-cascader": "~3.2.1",
|
||||||
"rc-checkbox": "~2.3.0",
|
"rc-checkbox": "~2.3.0",
|
||||||
"rc-collapse": "~3.1.0",
|
"rc-collapse": "~3.1.0",
|
||||||
"rc-dialog": "~8.6.0",
|
"rc-dialog": "~8.6.0",
|
||||||
|
@ -29266,7 +29264,7 @@
|
||||||
"rc-textarea": "~0.3.0",
|
"rc-textarea": "~0.3.0",
|
||||||
"rc-tooltip": "~5.1.1",
|
"rc-tooltip": "~5.1.1",
|
||||||
"rc-tree": "~5.4.3",
|
"rc-tree": "~5.4.3",
|
||||||
"rc-tree-select": "~5.1.0",
|
"rc-tree-select": "~5.1.1",
|
||||||
"rc-trigger": "^5.2.10",
|
"rc-trigger": "^5.2.10",
|
||||||
"rc-upload": "~4.3.0",
|
"rc-upload": "~4.3.0",
|
||||||
"rc-util": "^5.14.0",
|
"rc-util": "^5.14.0",
|
||||||
|
@ -39159,14 +39157,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rc-cascader": {
|
"rc-cascader": {
|
||||||
"version": "3.0.0-alpha.8",
|
"version": "3.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.0.0-alpha.8.tgz",
|
"resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.2.1.tgz",
|
||||||
"integrity": "sha512-zZ6tczHacUy622E7m5aruCcB3ii+J5bhusCPpyb64LP9KbcKcquchdgWeeyVY/7K8BrJXOTOJW1MDZ9nxsWBWw==",
|
"integrity": "sha512-Raxam9tFzBL4TCgHoyVcf7+Q2KSFneUk3FZXi9w1tfxEihLlezSH0oCNMjHJN8hxWwwx9ZbI9UzWTfFImjXc0Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
"array-tree-filter": "^2.1.0",
|
"array-tree-filter": "^2.1.0",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
"rc-select": "~14.0.0-alpha.8",
|
"rc-select": "~14.0.0-alpha.23",
|
||||||
"rc-tree": "~5.4.3",
|
"rc-tree": "~5.4.3",
|
||||||
"rc-util": "^5.6.1"
|
"rc-util": "^5.6.1"
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,11 +32,11 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@reduxjs/toolkit": "^1.7.1",
|
"@reduxjs/toolkit": "^1.7.1",
|
||||||
"@sentry/react": "^6.16.1",
|
"@sentry/react": "^6.17.0",
|
||||||
"@sentry/tracing": "^6.16.1",
|
"@sentry/tracing": "^6.17.0",
|
||||||
"@speedy-tuner/ini": "^0.3.0",
|
"@speedy-tuner/ini": "^0.3.0",
|
||||||
"@speedy-tuner/types": "^0.3.0",
|
"@speedy-tuner/types": "^0.3.0",
|
||||||
"antd": "^4.18.4",
|
"antd": "^4.18.5",
|
||||||
"firebase": "^9.6.4",
|
"firebase": "^9.6.4",
|
||||||
"kbar": "^0.1.0-beta.27",
|
"kbar": "^0.1.0-beta.27",
|
||||||
"mlg-converter": "^0.5.1",
|
"mlg-converter": "^0.5.1",
|
||||||
|
|
|
@ -33,6 +33,7 @@ import {
|
||||||
import useDb from './hooks/useDb';
|
import useDb from './hooks/useDb';
|
||||||
import useServerStorage from './hooks/useServerStorage';
|
import useServerStorage from './hooks/useServerStorage';
|
||||||
import Info from './pages/Info';
|
import Info from './pages/Info';
|
||||||
|
import Hub from './pages/Hub';
|
||||||
|
|
||||||
import 'react-perfect-scrollbar/dist/css/styles.css';
|
import 'react-perfect-scrollbar/dist/css/styles.css';
|
||||||
|
|
||||||
|
@ -127,11 +128,7 @@ const App = ({ ui, navigation }: { ui: UIState, navigation: NavigationState }) =
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path={Routes.ROOT} exact>
|
<Route path={Routes.ROOT} exact>
|
||||||
<ContentFor>
|
<ContentFor>
|
||||||
<Result
|
<Hub />
|
||||||
status="info"
|
|
||||||
title="This page is under construction"
|
|
||||||
style={{ marginTop: 50 }}
|
|
||||||
/>
|
|
||||||
</ContentFor>
|
</ContentFor>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path={Routes.TUNE_ROOT} exact>
|
<Route path={Routes.TUNE_ROOT} exact>
|
||||||
|
|
|
@ -30,6 +30,7 @@ import {
|
||||||
InfoCircleOutlined,
|
InfoCircleOutlined,
|
||||||
FundOutlined,
|
FundOutlined,
|
||||||
SettingOutlined,
|
SettingOutlined,
|
||||||
|
CarOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import {
|
import {
|
||||||
useHistory,
|
useHistory,
|
||||||
|
@ -313,6 +314,14 @@ const CommandPalette = (props: CommandPaletteProps) => {
|
||||||
}, [logout]);
|
}, [logout]);
|
||||||
|
|
||||||
const initialActions = [
|
const initialActions = [
|
||||||
|
{
|
||||||
|
id: 'HubAction',
|
||||||
|
section: Sections.NAVIGATION,
|
||||||
|
name: 'Hub',
|
||||||
|
subtitle: 'Public tunes and logs.',
|
||||||
|
icon: <CarOutlined />,
|
||||||
|
perform: () => history.push(Routes.ROOT),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'ToggleSidebar',
|
id: 'ToggleSidebar',
|
||||||
name: 'Toggle Sidebar',
|
name: 'Toggle Sidebar',
|
||||||
|
|
|
@ -45,6 +45,7 @@ import {
|
||||||
UserAddOutlined,
|
UserAddOutlined,
|
||||||
LogoutOutlined,
|
LogoutOutlined,
|
||||||
InfoCircleOutlined,
|
InfoCircleOutlined,
|
||||||
|
CarOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { useKBar } from 'kbar';
|
import { useKBar } from 'kbar';
|
||||||
import store from '../store';
|
import store from '../store';
|
||||||
|
@ -74,6 +75,9 @@ const TopBar = ({ tuneId }: { tuneId: string | null }) => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { query } = useKBar();
|
const { query } = useKBar();
|
||||||
const buildTuneUrl = (route: string) => tuneId ? generatePath(route, { tuneId }) : null;
|
const buildTuneUrl = (route: string) => tuneId ? generatePath(route, { tuneId }) : null;
|
||||||
|
const matchedRootPath = useMemo(() => matchPath(pathname, {
|
||||||
|
path: Routes.ROOT,
|
||||||
|
}), [pathname]);
|
||||||
const matchedTuneRootPath = useMemo(() => matchPath(pathname, {
|
const matchedTuneRootPath = useMemo(() => matchPath(pathname, {
|
||||||
path: Routes.TUNE_ROOT,
|
path: Routes.TUNE_ROOT,
|
||||||
}), [pathname]);
|
}), [pathname]);
|
||||||
|
@ -114,33 +118,39 @@ const TopBar = ({ tuneId }: { tuneId: string | null }) => {
|
||||||
<Col span={14} md={12} sm={16} style={{ textAlign: 'center' }}>
|
<Col span={14} md={12} sm={16} style={{ textAlign: 'center' }}>
|
||||||
<Radio.Group
|
<Radio.Group
|
||||||
key={pathname}
|
key={pathname}
|
||||||
defaultValue={matchedTabPath?.url || matchedTuneRootPath?.url}
|
defaultValue={matchedTabPath?.url || matchedTuneRootPath?.url || matchedRootPath?.url || ''}
|
||||||
optionType="button"
|
optionType="button"
|
||||||
buttonStyle="solid"
|
buttonStyle="solid"
|
||||||
onChange={(e) => history.push(e.target.value)}
|
onChange={(e) => history.push(e.target.value)}
|
||||||
>
|
>
|
||||||
|
<Radio.Button value={buildTuneUrl(Routes.ROOT)}>
|
||||||
|
<Space>
|
||||||
|
<CarOutlined />
|
||||||
|
{lg && 'Hub'}
|
||||||
|
</Space>
|
||||||
|
</Radio.Button>
|
||||||
<Radio.Button value={buildTuneUrl(Routes.TUNE_ROOT)}>
|
<Radio.Button value={buildTuneUrl(Routes.TUNE_ROOT)}>
|
||||||
<Space>
|
<Space>
|
||||||
<InfoCircleOutlined />
|
<InfoCircleOutlined />
|
||||||
{sm && 'Info'}
|
{lg && 'Info'}
|
||||||
</Space>
|
</Space>
|
||||||
</Radio.Button>
|
</Radio.Button>
|
||||||
<Radio.Button value={buildTuneUrl(Routes.TUNE_TUNE)}>
|
<Radio.Button value={buildTuneUrl(Routes.TUNE_TUNE)}>
|
||||||
<Space>
|
<Space>
|
||||||
<ToolOutlined />
|
<ToolOutlined />
|
||||||
{sm && 'Tune'}
|
{lg && 'Tune'}
|
||||||
</Space>
|
</Space>
|
||||||
</Radio.Button>
|
</Radio.Button>
|
||||||
<Radio.Button value={buildTuneUrl(Routes.TUNE_LOGS)}>
|
<Radio.Button value={buildTuneUrl(Routes.TUNE_LOGS)}>
|
||||||
<Space>
|
<Space>
|
||||||
<FundOutlined />
|
<FundOutlined />
|
||||||
{sm && 'Logs'}
|
{lg && 'Logs'}
|
||||||
</Space>
|
</Space>
|
||||||
</Radio.Button>
|
</Radio.Button>
|
||||||
<Radio.Button value={buildTuneUrl(Routes.TUNE_DIAGNOSE)}>
|
<Radio.Button value={buildTuneUrl(Routes.TUNE_DIAGNOSE)}>
|
||||||
<Space>
|
<Space>
|
||||||
<SettingOutlined />
|
<SettingOutlined />
|
||||||
{sm && 'Diagnose'}
|
{lg && 'Diagnose'}
|
||||||
</Space>
|
</Space>
|
||||||
</Radio.Button>
|
</Radio.Button>
|
||||||
</Radio.Group>
|
</Radio.Group>
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
import {
|
import {
|
||||||
User,
|
User,
|
||||||
UserCredential,
|
UserCredential,
|
||||||
|
createUserWithEmailAndPassword,
|
||||||
|
signInWithEmailAndPassword,
|
||||||
|
sendEmailVerification,
|
||||||
|
signOut,
|
||||||
|
sendPasswordResetEmail,
|
||||||
|
GoogleAuthProvider,
|
||||||
|
GithubAuthProvider,
|
||||||
|
signInWithPopup,
|
||||||
} from 'firebase/auth';
|
} from 'firebase/auth';
|
||||||
import {
|
import {
|
||||||
createContext,
|
createContext,
|
||||||
|
@ -10,17 +18,7 @@ import {
|
||||||
useMemo,
|
useMemo,
|
||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import {
|
import { auth } from '../firebase';
|
||||||
auth,
|
|
||||||
createUserWithEmailAndPassword,
|
|
||||||
signInWithEmailAndPassword,
|
|
||||||
sendEmailVerification,
|
|
||||||
signOut,
|
|
||||||
sendPasswordResetEmail,
|
|
||||||
GoogleAuthProvider,
|
|
||||||
GithubAuthProvider,
|
|
||||||
signInWithPopup,
|
|
||||||
} from '../firebase';
|
|
||||||
|
|
||||||
interface AuthValue {
|
interface AuthValue {
|
||||||
currentUser: User | null,
|
currentUser: User | null,
|
||||||
|
|
|
@ -1,33 +1,9 @@
|
||||||
import { initializeApp } from 'firebase/app';
|
import { initializeApp } from 'firebase/app';
|
||||||
import { getPerformance } from 'firebase/performance';
|
import { getPerformance } from 'firebase/performance';
|
||||||
import {
|
import { getAuth } from 'firebase/auth';
|
||||||
getAuth,
|
|
||||||
createUserWithEmailAndPassword,
|
|
||||||
signInWithEmailAndPassword,
|
|
||||||
signOut,
|
|
||||||
sendEmailVerification,
|
|
||||||
sendPasswordResetEmail,
|
|
||||||
GoogleAuthProvider,
|
|
||||||
GithubAuthProvider,
|
|
||||||
signInWithPopup,
|
|
||||||
} from 'firebase/auth';
|
|
||||||
import { getAnalytics } from 'firebase/analytics';
|
import { getAnalytics } from 'firebase/analytics';
|
||||||
import {
|
import { getStorage } from 'firebase/storage';
|
||||||
getStorage,
|
import { getFirestore } from 'firebase/firestore';
|
||||||
ref,
|
|
||||||
uploadBytes,
|
|
||||||
uploadBytesResumable,
|
|
||||||
deleteObject,
|
|
||||||
getBytes,
|
|
||||||
} from 'firebase/storage';
|
|
||||||
import {
|
|
||||||
getFirestore,
|
|
||||||
doc,
|
|
||||||
setDoc,
|
|
||||||
collection,
|
|
||||||
addDoc,
|
|
||||||
getDoc,
|
|
||||||
} from 'firebase/firestore';
|
|
||||||
|
|
||||||
const firebaseConfig = {
|
const firebaseConfig = {
|
||||||
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
|
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
|
||||||
|
@ -47,27 +23,10 @@ const db = getFirestore();
|
||||||
const storage = getStorage();
|
const storage = getStorage();
|
||||||
|
|
||||||
export {
|
export {
|
||||||
auth,
|
app,
|
||||||
analytics,
|
analytics,
|
||||||
performance,
|
performance,
|
||||||
createUserWithEmailAndPassword,
|
auth,
|
||||||
signInWithEmailAndPassword,
|
|
||||||
sendEmailVerification,
|
|
||||||
signOut,
|
|
||||||
sendPasswordResetEmail,
|
|
||||||
GoogleAuthProvider,
|
|
||||||
GithubAuthProvider,
|
|
||||||
signInWithPopup,
|
|
||||||
ref as storageRef,
|
|
||||||
storage,
|
|
||||||
uploadBytes,
|
|
||||||
uploadBytesResumable,
|
|
||||||
deleteObject,
|
|
||||||
getBytes,
|
|
||||||
doc as fireStoreDoc,
|
|
||||||
collection as fireStoreCollection,
|
|
||||||
setDoc,
|
|
||||||
addDoc,
|
|
||||||
getDoc,
|
|
||||||
db,
|
db,
|
||||||
|
storage,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
import { notification } from 'antd';
|
import { notification } from 'antd';
|
||||||
import * as Sentry from '@sentry/browser';
|
import * as Sentry from '@sentry/browser';
|
||||||
import { Timestamp } from 'firebase/firestore';
|
|
||||||
import {
|
import {
|
||||||
fireStoreDoc,
|
Timestamp,
|
||||||
|
doc,
|
||||||
getDoc,
|
getDoc,
|
||||||
setDoc,
|
setDoc,
|
||||||
db,
|
collection,
|
||||||
} from '../firebase';
|
where,
|
||||||
|
query,
|
||||||
|
getDocs,
|
||||||
|
QuerySnapshot,
|
||||||
|
orderBy,
|
||||||
|
} from 'firebase/firestore';
|
||||||
|
import { db } from '../firebase';
|
||||||
import { TuneDbData } from '../types/dbData';
|
import { TuneDbData } from '../types/dbData';
|
||||||
|
|
||||||
const TUNES_PATH = 'publicTunes';
|
const TUNES_PATH = 'publicTunes';
|
||||||
|
@ -14,9 +20,9 @@ const TUNES_PATH = 'publicTunes';
|
||||||
const genericError = (error: Error) => notification.error({ message: 'Database Error', description: error.message });
|
const genericError = (error: Error) => notification.error({ message: 'Database Error', description: error.message });
|
||||||
|
|
||||||
const useDb = () => {
|
const useDb = () => {
|
||||||
const getData = async (tuneId: string) => {
|
const getTuneData = async (tuneId: string) => {
|
||||||
try {
|
try {
|
||||||
const tune = (await getDoc(fireStoreDoc(db, TUNES_PATH, tuneId))).data() as TuneDbData;
|
const tune = (await getDoc(doc(db, TUNES_PATH, tuneId))).data() as TuneDbData;
|
||||||
const processed = {
|
const processed = {
|
||||||
...tune,
|
...tune,
|
||||||
createdAt: (tune?.createdAt as Timestamp)?.toDate().toISOString(),
|
createdAt: (tune?.createdAt as Timestamp)?.toDate().toISOString(),
|
||||||
|
@ -33,9 +39,29 @@ const useDb = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const listTunesData = async () => {
|
||||||
|
try {
|
||||||
|
const tunesRef = collection(db, TUNES_PATH);
|
||||||
|
const q = query(
|
||||||
|
tunesRef,
|
||||||
|
where('isPublished', '==', true),
|
||||||
|
where('isListed', '==', true),
|
||||||
|
orderBy('createdAt', 'desc'),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Promise.resolve(await getDocs(q));
|
||||||
|
} catch (error) {
|
||||||
|
Sentry.captureException(error);
|
||||||
|
console.error(error);
|
||||||
|
genericError(error as Error);
|
||||||
|
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const updateData = async (tuneId: string, data: TuneDbData) => {
|
const updateData = async (tuneId: string, data: TuneDbData) => {
|
||||||
try {
|
try {
|
||||||
await setDoc(fireStoreDoc(db, TUNES_PATH, tuneId), data, { merge: true });
|
await setDoc(doc(db, TUNES_PATH, tuneId), data, { merge: true });
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -48,8 +74,9 @@ const useDb = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getTune: (tuneId: string): Promise<TuneDbData> => getData(tuneId),
|
|
||||||
updateData: (tuneId: string, data: TuneDbData): Promise<void> => updateData(tuneId, data),
|
updateData: (tuneId: string, data: TuneDbData): Promise<void> => updateData(tuneId, data),
|
||||||
|
getTune: (tuneId: string): Promise<TuneDbData> => getTuneData(tuneId),
|
||||||
|
listTunes: (): Promise<QuerySnapshot<TuneDbData>> => listTunesData(),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { notification } from 'antd';
|
import { notification } from 'antd';
|
||||||
import * as Sentry from '@sentry/browser';
|
import * as Sentry from '@sentry/browser';
|
||||||
import { UploadTask } from 'firebase/storage';
|
|
||||||
import {
|
import {
|
||||||
storage,
|
UploadTask,
|
||||||
storageRef,
|
ref,
|
||||||
getBytes,
|
getBytes,
|
||||||
deleteObject,
|
deleteObject,
|
||||||
uploadBytesResumable,
|
uploadBytesResumable,
|
||||||
} from '../firebase';
|
} from 'firebase/storage';
|
||||||
|
import { storage } from '../firebase';
|
||||||
|
|
||||||
const BASE_PATH = 'public/users';
|
const BASE_PATH = 'public/users';
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ const genericError = (error: Error) => notification.error({ message: 'Database E
|
||||||
const useServerStorage = () => {
|
const useServerStorage = () => {
|
||||||
const getFile = async (path: string) => {
|
const getFile = async (path: string) => {
|
||||||
try {
|
try {
|
||||||
const buffer = await getBytes(storageRef(storage, path));
|
const buffer = await getBytes(ref(storage, path));
|
||||||
|
|
||||||
return Promise.resolve(buffer);
|
return Promise.resolve(buffer);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -30,7 +30,7 @@ const useServerStorage = () => {
|
||||||
|
|
||||||
const removeFile = async (path: string) => {
|
const removeFile = async (path: string) => {
|
||||||
try {
|
try {
|
||||||
await deleteObject(storageRef(storage, path));
|
await deleteObject(ref(storage, path));
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -43,7 +43,7 @@ const useServerStorage = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const uploadFile = (path: string, file: File, data: Uint8Array) =>
|
const uploadFile = (path: string, file: File, data: Uint8Array) =>
|
||||||
uploadBytesResumable(storageRef(storage, path), data, {
|
uploadBytesResumable(ref(storage, path), data, {
|
||||||
customMetadata: {
|
customMetadata: {
|
||||||
name: file.name,
|
name: file.name,
|
||||||
size: `${file.size}`,
|
size: `${file.size}`,
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
import {
|
||||||
|
Badge,
|
||||||
|
Card,
|
||||||
|
Col,
|
||||||
|
Row,
|
||||||
|
Tooltip,
|
||||||
|
Typography,
|
||||||
|
} from 'antd';
|
||||||
|
import {
|
||||||
|
CopyOutlined,
|
||||||
|
StarOutlined,
|
||||||
|
ArrowRightOutlined,
|
||||||
|
} from '@ant-design/icons';
|
||||||
|
import {
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
|
import {
|
||||||
|
generatePath,
|
||||||
|
useHistory,
|
||||||
|
} from 'react-router';
|
||||||
|
import useDb from '../hooks/useDb';
|
||||||
|
import { TuneDbData } from '../types/dbData';
|
||||||
|
import { Routes } from '../routes';
|
||||||
|
import { generateShareUrl } from '../utils/url';
|
||||||
|
|
||||||
|
const containerStyle = {
|
||||||
|
padding: 20,
|
||||||
|
maxWidth: 800,
|
||||||
|
margin: '0 auto',
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadingCards = (
|
||||||
|
<>
|
||||||
|
<Col span={8}>
|
||||||
|
<Card loading />
|
||||||
|
</Col>
|
||||||
|
<Col span={8}>
|
||||||
|
<Card loading />
|
||||||
|
</Col>
|
||||||
|
<Col span={8}>
|
||||||
|
<Card loading />
|
||||||
|
</Col>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
const Hub = () => {
|
||||||
|
const [tunes, setTunes] = useState<TuneDbData[]>([]);
|
||||||
|
const { listTunes } = useDb();
|
||||||
|
const history = useHistory();
|
||||||
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
|
const goToTune = (tuneId: string) => history.push(generatePath(Routes.TUNE_ROOT, { tuneId }));
|
||||||
|
|
||||||
|
const copyToClipboard = async (shareUrl: string) => {
|
||||||
|
if (navigator.clipboard) {
|
||||||
|
await navigator.clipboard.writeText(shareUrl);
|
||||||
|
setCopied(true);
|
||||||
|
setTimeout(() => setCopied(false), 1000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadData = useCallback(() => {
|
||||||
|
listTunes().then((data) => {
|
||||||
|
const temp: TuneDbData[] = [];
|
||||||
|
|
||||||
|
data.forEach((tuneSnapshot) => {
|
||||||
|
temp.push(tuneSnapshot.data());
|
||||||
|
});
|
||||||
|
|
||||||
|
setTunes(temp);
|
||||||
|
});
|
||||||
|
}, [listTunes]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadData();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []); // TODO: fix this
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={containerStyle}>
|
||||||
|
<Typography.Title>Hub</Typography.Title>
|
||||||
|
<Row gutter={[16, 16]}>
|
||||||
|
{tunes.length === 0 ? loadingCards : (
|
||||||
|
tunes.map((tune) => (
|
||||||
|
<Col span={16} sm={8} key={tune.tuneFile}>
|
||||||
|
<Card
|
||||||
|
title={tune.details!.model}
|
||||||
|
actions={[
|
||||||
|
<Badge count={0} showZero size="small" color="gold">
|
||||||
|
<StarOutlined />
|
||||||
|
</Badge>,
|
||||||
|
<Tooltip title={copied ? 'Copied!' : 'Copy URL'}>
|
||||||
|
<CopyOutlined onClick={() => copyToClipboard(generateShareUrl(tune.id!))} />
|
||||||
|
</Tooltip>,
|
||||||
|
<ArrowRightOutlined onClick={() => goToTune(tune.id!)} />,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Typography.Text ellipsis>
|
||||||
|
{tune.details!.make} {tune.details!.model} {tune.details!.year}
|
||||||
|
</Typography.Text>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
)))}
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Hub;
|
|
@ -53,9 +53,9 @@ import { Routes } from '../routes';
|
||||||
import TuneParser from '../utils/tune/TuneParser';
|
import TuneParser from '../utils/tune/TuneParser';
|
||||||
import TriggerLogsParser from '../utils/logs/TriggerLogsParser';
|
import TriggerLogsParser from '../utils/logs/TriggerLogsParser';
|
||||||
import LogParser from '../utils/logs/LogParser';
|
import LogParser from '../utils/logs/LogParser';
|
||||||
import { TuneDbData } from '../types/dbData';
|
|
||||||
import useDb from '../hooks/useDb';
|
import useDb from '../hooks/useDb';
|
||||||
import useServerStorage from '../hooks/useServerStorage';
|
import useServerStorage from '../hooks/useServerStorage';
|
||||||
|
import { generateShareUrl } from '../utils/url';
|
||||||
|
|
||||||
const { Item } = Form;
|
const { Item } = Form;
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ const UploadPage = () => {
|
||||||
const { currentUser, refreshToken } = useAuth();
|
const { currentUser, refreshToken } = useAuth();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { removeFile, uploadFile, basePathForFile } = useServerStorage();
|
const { removeFile, uploadFile, basePathForFile } = useServerStorage();
|
||||||
const { updateData, getTune } = useDb();
|
const { updateData } = useDb();
|
||||||
const requiredRules = [{ required: true, message: 'This field is required!' }];
|
const requiredRules = [{ required: true, message: 'This field is required!' }];
|
||||||
const [readme, setReadme] = useState('# My Tune\n\ndescription');
|
const [readme, setReadme] = useState('# My Tune\n\ndescription');
|
||||||
|
|
||||||
|
@ -139,7 +139,8 @@ const UploadPage = () => {
|
||||||
const publish = async (values: any) => {
|
const publish = async (values: any) => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
await updateData(newTuneId!, {
|
await updateData(newTuneId!, {
|
||||||
createdAt: new Date(),
|
id: newTuneId!,
|
||||||
|
userUid: currentUser!.uid,
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
isPublished: true,
|
isPublished: true,
|
||||||
isListed: values.isListed,
|
isListed: values.isListed,
|
||||||
|
@ -225,29 +226,25 @@ const UploadPage = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const uploadTune = async (options: UploadRequestOption) => {
|
const uploadTune = async (options: UploadRequestOption) => {
|
||||||
const found = await getTune(newTuneId!);
|
setShareUrl(generateShareUrl(newTuneId!));
|
||||||
if (!found) {
|
|
||||||
const tuneData: TuneDbData = {
|
const { path } = (options.data as unknown as UploadFileData);
|
||||||
|
const tune: UploadedFile = {};
|
||||||
|
tune[(options.file as UploadFile).uid] = path;
|
||||||
|
|
||||||
|
upload(path, options, () => {
|
||||||
|
// this is `create` for firebase
|
||||||
|
// initialize data
|
||||||
|
updateData(newTuneId!, {
|
||||||
|
id: newTuneId!,
|
||||||
userUid: currentUser!.uid,
|
userUid: currentUser!.uid,
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
isPublished: false,
|
isPublished: false,
|
||||||
isListed: true,
|
isListed: true,
|
||||||
tuneFile: null,
|
|
||||||
logFiles: [],
|
|
||||||
toothLogFiles: [],
|
|
||||||
customIniFile: null,
|
|
||||||
details: {},
|
details: {},
|
||||||
};
|
tuneFile: path,
|
||||||
await updateData(newTuneId!, tuneData);
|
});
|
||||||
}
|
|
||||||
setShareUrl(`${process.env.REACT_APP_WEB_URL}/#/t/${newTuneId}`);
|
|
||||||
|
|
||||||
const { path } = (options.data as unknown as UploadFileData);
|
|
||||||
const tune: UploadedFile = {};
|
|
||||||
tune[(options.file as UploadFile).uid] = path;
|
|
||||||
upload(path, options, () => {
|
|
||||||
updateData(newTuneId!, { tuneFile: path });
|
|
||||||
}, async (file) => {
|
}, async (file) => {
|
||||||
const { result, message } = await validateSize(file);
|
const { result, message } = await validateSize(file);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
@ -432,7 +429,9 @@ const UploadPage = () => {
|
||||||
genericError(error as Error);
|
genericError(error as Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
setNewTuneId(nanoidCustom());
|
const tuneId = nanoidCustom();
|
||||||
|
setNewTuneId(tuneId);
|
||||||
|
console.log('New tuneId:', tuneId);
|
||||||
}, [currentUser, history, refreshToken]);
|
}, [currentUser, history, refreshToken]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -17,6 +17,7 @@ export interface TuneDataDetails {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TuneDbData {
|
export interface TuneDbData {
|
||||||
|
id?: string,
|
||||||
userUid?: string;
|
userUid?: string;
|
||||||
createdAt?: Date | Timestamp | string;
|
createdAt?: Date | Timestamp | string;
|
||||||
updatedAt?: Date | Timestamp | string;
|
updatedAt?: Date | Timestamp | string;
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
|
export const generateShareUrl = (tuneId: string) => `${process.env.REACT_APP_WEB_URL}/#/t/${tuneId}`;
|
Loading…
Reference in New Issue