From e593472c84c862201aff9efde51d3bca4b756c90 Mon Sep 17 00:00:00 2001 From: Mitchell Date: Sun, 19 Aug 2018 18:17:40 -0500 Subject: [PATCH] UI Overhaul --- .gitignore | 13 +- .vscode/settings.json | 5 +- client/app/Wrapper.tsx | 20 --- client/app/app.tsx | 38 ++--- client/app/components/Navbar/Navbar.tsx | 90 ---------- client/app/components/Navbar/index.ts | 1 - client/app/components/SoundList/index.ts | 1 - client/app/components/header/header.scss | 37 ++++ client/app/components/header/header.tsx | 26 +++ client/app/components/index.ts | 4 + .../Navbar.scss => navbar/navbar.scss} | 32 ++-- client/app/components/navbar/navbar.tsx | 86 ++++++++++ .../sound-list.scss} | 4 +- .../sound-list.tsx} | 7 +- .../uploader/uploader.scss} | 28 +-- client/app/components/uploader/uploader.tsx | 86 ++++++++++ client/app/model/claims.ts | 12 ++ client/app/model/index.ts | 2 + client/app/model/permissions.ts | 5 + client/app/pages/Clips/index.ts | 1 - client/app/pages/Home/Home.tsx | 48 ------ client/app/pages/NotFound/NotFound.tsx | 12 -- client/app/pages/Pubg/Pubg.scss | 33 ---- client/app/pages/Pubg/Pubg.tsx | 159 ------------------ client/app/pages/Soundboard/Soundboard.tsx | 130 -------------- .../{Clips/Clips.tsx => clips/clips.tsx} | 5 +- .../downloader.scss} | 8 +- .../downloader.tsx} | 7 +- client/app/pages/index.ts | 6 + .../not-found.scss} | 3 +- client/app/pages/not-found/not-found.tsx | 4 + client/app/pages/oauth/oauth.tsx | 4 +- .../Home.scss => soundboard/soundboard.scss} | 0 client/app/pages/soundboard/soundboard.tsx | 66 ++++++++ client/app/pages/stats/stats.scss | 3 - client/app/scss/button.scss | 20 +++ client/app/scss/card.scss | 20 +++ client/app/scss/index.scss | 3 +- client/app/scss/mixins.scss | 5 + client/app/scss/style.scss | 61 ++----- client/app/services/axios.service.ts | 5 - client/app/stores/app.store.ts | 43 +++++ client/app/stores/index.ts | 2 + client/app/stores/root.store.ts | 7 + client/app/util.ts | 17 ++ client/app/wrapper.scss | 16 ++ client/app/wrapper.tsx | 29 ++++ client/index.html | 1 + client/package-lock.json | 21 ++- client/package.json | 4 +- client/tsconfig.json | 23 +-- docker-build.sh | 4 +- docker-compose.yml | 1 + fresh.conf | 1 + readme.md | 47 +++--- run_client.sh | 1 + run_server.sh | 1 + screenshots/sound-bot.png | Bin 0 -> 32136 bytes 58 files changed, 633 insertions(+), 685 deletions(-) delete mode 100644 client/app/Wrapper.tsx delete mode 100644 client/app/components/Navbar/Navbar.tsx delete mode 100644 client/app/components/Navbar/index.ts delete mode 100644 client/app/components/SoundList/index.ts create mode 100644 client/app/components/header/header.scss create mode 100644 client/app/components/header/header.tsx create mode 100644 client/app/components/index.ts rename client/app/components/{Navbar/Navbar.scss => navbar/navbar.scss} (70%) create mode 100644 client/app/components/navbar/navbar.tsx rename client/app/components/{SoundList/SoundList.scss => sound-list/sound-list.scss} (78%) rename client/app/components/{SoundList/SoundList.tsx => sound-list/sound-list.tsx} (91%) rename client/app/{pages/Soundboard/Soundboard.scss => components/uploader/uploader.scss} (55%) create mode 100644 client/app/components/uploader/uploader.tsx create mode 100644 client/app/model/claims.ts create mode 100644 client/app/model/index.ts create mode 100644 client/app/model/permissions.ts delete mode 100644 client/app/pages/Clips/index.ts delete mode 100644 client/app/pages/Home/Home.tsx delete mode 100644 client/app/pages/NotFound/NotFound.tsx delete mode 100644 client/app/pages/Pubg/Pubg.scss delete mode 100644 client/app/pages/Pubg/Pubg.tsx delete mode 100644 client/app/pages/Soundboard/Soundboard.tsx rename client/app/pages/{Clips/Clips.tsx => clips/clips.tsx} (88%) rename client/app/pages/{Downloader/Downloader.scss => downloader/downloader.scss} (56%) rename client/app/pages/{Downloader/Downloader.tsx => downloader/downloader.tsx} (95%) create mode 100644 client/app/pages/index.ts rename client/app/pages/{NotFound/NotFound.scss => not-found/not-found.scss} (88%) create mode 100644 client/app/pages/not-found/not-found.tsx rename client/app/pages/{Home/Home.scss => soundboard/soundboard.scss} (100%) create mode 100644 client/app/pages/soundboard/soundboard.tsx create mode 100644 client/app/scss/button.scss create mode 100644 client/app/scss/card.scss create mode 100644 client/app/scss/mixins.scss create mode 100644 client/app/stores/app.store.ts create mode 100644 client/app/stores/index.ts create mode 100644 client/app/stores/root.store.ts create mode 100644 client/app/util.ts create mode 100644 client/app/wrapper.scss create mode 100644 client/app/wrapper.tsx create mode 100644 fresh.conf create mode 100755 run_client.sh create mode 100755 run_server.sh create mode 100644 screenshots/sound-bot.png diff --git a/.gitignore b/.gitignore index 0e2d0f8..e927834 100644 --- a/.gitignore +++ b/.gitignore @@ -4,11 +4,14 @@ node_modules yarn-error* vendor bot -sounds -clips debug -youtube go-discord-bot -data.db .wwp-cache -data +tmp + +/sounds +/clips +/youtube + +/data +/data.db diff --git a/.vscode/settings.json b/.vscode/settings.json index ad92582..1589eb1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,6 @@ { - "editor.formatOnSave": true + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.organizeImports": true + } } diff --git a/client/app/Wrapper.tsx b/client/app/Wrapper.tsx deleted file mode 100644 index 9863fc9..0000000 --- a/client/app/Wrapper.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; -import { Navbar } from './components/Navbar'; - -//styling -import './scss/index.scss'; - -export class Wrapper extends React.Component { - constructor(props: any) { - super(props); - } - - render() { - return ( -
- -
{this.props.children}
-
- ); - } -} diff --git a/client/app/app.tsx b/client/app/app.tsx index d044ac4..eb1f83f 100644 --- a/client/app/app.tsx +++ b/client/app/app.tsx @@ -1,31 +1,27 @@ +import 'babel-polyfill'; +import { Provider } from 'mobx-react'; import React from 'react'; import ReactDOM from 'react-dom'; import { BrowserRouter, Route, Switch } from 'react-router-dom'; - -import { Wrapper } from './Wrapper'; -import { Home } from './pages/Home/Home'; -import { Soundboard } from './pages/Soundboard/Soundboard'; -import { NotFound } from './pages/NotFound/NotFound'; -import { Downloader } from './pages/Downloader/Downloader'; -import { Clips } from './pages/Clips'; -import { Oauth } from './pages/oauth/oauth'; -import { Stats } from './pages/stats/stats'; -import 'babel-polyfill'; +import { Clips, Downloader, NotFound, Oauth, Soundboard, Stats } from './pages'; +import { rootStoreInstance } from './stores'; +import { Wrapper } from './wrapper'; const App: any = (): any => { return ( - - - - - - - - - - - + + + + + + + + + + + + ); }; diff --git a/client/app/components/Navbar/Navbar.tsx b/client/app/components/Navbar/Navbar.tsx deleted file mode 100644 index 581267f..0000000 --- a/client/app/components/Navbar/Navbar.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React from 'react'; -import { NavLink } from 'react-router-dom'; -import jwt_decode from 'jwt-decode'; -import { OauthService, StorageService } from '../../services'; -import './Navbar.scss'; - -interface Props {} - -interface State { - token: string | null; - email?: string; - oauthUrl?: string; -} - -export class Navbar extends React.Component { - constructor(props: Props) { - super(props); - this.state = { - token: null, - }; - } - - componentDidMount() { - this.loadOauthUrl(); - const token = StorageService.getJWT(); - - if (token) { - const claims: any = jwt_decode(token); - const email = claims['email']; - this.setState({ token, email }); - } - } - - async loadOauthUrl() { - try { - const oauthUrl = await OauthService.getOauthUrl(); - this.setState({ oauthUrl }); - } catch (e) { - console.error(e); - } - } - - private logout = () => { - StorageService.clear(); - window.location.href = '/'; - }; - - renderLoginButton() { - if (!this.state.oauthUrl) { - return null; - } - - return !this.state.token ? ( - - Login - - ) : ( - - Logout - - ); - } - - render() { - return ( -
-
Sound Bot
- - Home - - - Soundboard - - - Youtube Downloader - - - Clips - - - Stats - - - {this.renderLoginButton()} - - {this.state.email &&
{this.state.email}
} -
- ); - } -} diff --git a/client/app/components/Navbar/index.ts b/client/app/components/Navbar/index.ts deleted file mode 100644 index e8a6562..0000000 --- a/client/app/components/Navbar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './Navbar'; diff --git a/client/app/components/SoundList/index.ts b/client/app/components/SoundList/index.ts deleted file mode 100644 index 81dc08b..0000000 --- a/client/app/components/SoundList/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './SoundList'; diff --git a/client/app/components/header/header.scss b/client/app/components/header/header.scss new file mode 100644 index 0000000..d57bf01 --- /dev/null +++ b/client/app/components/header/header.scss @@ -0,0 +1,37 @@ +@import '../../scss/variables'; + +.header { + position: fixed; + top: 0; + left: 0; + background: linear-gradient(to right, $primaryBlue, darken($primaryBlue, 20%)); + height: 50px; + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + padding-right: 20px; + + &__title-container { + display: flex; + align-items: center; + } + + &__nav-button { + display: flex; + justify-content: center; + align-items: center; + width: 50px; + height: 50px; + margin-right: 10px; + background: $primaryBlue; + border: none; + color: $white; + border-right: 1px solid darken($primaryBlue, 2%); + cursor: pointer; + outline: none; + &:hover { + background: darken($primaryBlue, 5%); + } + } +} diff --git a/client/app/components/header/header.tsx b/client/app/components/header/header.tsx new file mode 100644 index 0000000..443ddaa --- /dev/null +++ b/client/app/components/header/header.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import './header.scss'; + +interface IProps { + onButtonClick: () => void; +} + +export class Header extends React.Component { + constructor(props: IProps) { + super(props); + } + + render() { + return ( +
+
+ +

Sound Bot

+
+ +
+ ); + } +} diff --git a/client/app/components/index.ts b/client/app/components/index.ts new file mode 100644 index 0000000..42edd04 --- /dev/null +++ b/client/app/components/index.ts @@ -0,0 +1,4 @@ +export * from './header/header'; +export * from './navbar/navbar'; +export * from './sound-list/sound-list'; +export * from './uploader/uploader'; diff --git a/client/app/components/Navbar/Navbar.scss b/client/app/components/navbar/navbar.scss similarity index 70% rename from client/app/components/Navbar/Navbar.scss rename to client/app/components/navbar/navbar.scss index 4d9350d..f6cf9b1 100644 --- a/client/app/components/Navbar/Navbar.scss +++ b/client/app/components/navbar/navbar.scss @@ -1,31 +1,25 @@ @import '../../scss/variables'; -.Navbar { +.navbar { position: fixed; display: flex; flex-direction: column; - top: 0; - left: 0; - height: 100%; + left: -$navbarWidth; + top: 50px; + height: calc(100% - 50px); width: $navbarWidth; background-color: $gray2; border-right: 1px solid darken($gray2, 2%); overflow-y: auto; padding-bottom: 10px; + transition: 0.2s left ease-in-out; + + &--open { + left: 0; + } } -.Navbar__header { - font-size: 25px; - min-height: 100px; - display: flex; - align-items: center; - justify-content: center; - text-align: center; - background-color: $primaryBlue; - border-bottom: 1px solid $gray3; -} - -.Navbar__item { +.navbar__item { min-height: 50px; text-decoration: none; display: flex; @@ -39,18 +33,18 @@ background-color: $gray1; } - & + .Navbar__item { + & + & { border-top: 1px solid $gray3; } } -.Navbar__item--active { +.navbar__item--active { padding-left: 4px; border-right: 4px solid $primaryBlue; color: $primaryBlue !important; } -.Navbar__email { +.navbar__email { padding-top: 10px; flex: 1; display: flex; diff --git a/client/app/components/navbar/navbar.tsx b/client/app/components/navbar/navbar.tsx new file mode 100644 index 0000000..1dcea14 --- /dev/null +++ b/client/app/components/navbar/navbar.tsx @@ -0,0 +1,86 @@ +import React from 'react'; +import { NavLink } from 'react-router-dom'; +import { IClaims } from '../../model'; +import { OauthService, StorageService } from '../../services'; +import './navbar.scss'; + +interface Props { + claims?: IClaims; + open: boolean; + onNavClick: () => void; +} + +interface State { + oauthUrl?: string; +} + +export class Navbar extends React.Component { + constructor(props: Props) { + super(props); + this.state = {}; + } + + componentDidMount() { + this.loadOauthUrl(); + } + + async loadOauthUrl() { + const oauthUrl = await OauthService.getOauthUrl(); + if (oauthUrl) { + this.setState({ oauthUrl }); + } + } + + private logout = () => { + StorageService.clear(); + window.location.href = '/'; + }; + + renderLoginButton() { + const { claims } = this.props; + + if (!this.state.oauthUrl) { + return null; + } + + return !claims ? ( + + Login + + ) : ( + + Logout + + ); + } + + renderNavLink = (title: string, to: string, params?: any) => { + return ( + + {title} + + ); + }; + + render() { + const { claims, open } = this.props; + const openClass = open ? 'navbar--open' : ''; + return ( +
+ {this.renderNavLink('Soundboard', '/', { exact: true })} + {this.renderNavLink('Youtube Downloader', '/downloader')} + {this.renderNavLink('Clips', '/clips')} + {this.renderNavLink('Stats', '/stats')} + {this.renderLoginButton()} + + {claims && claims.email &&
{claims.email}
} +
+ ); + } +} diff --git a/client/app/components/SoundList/SoundList.scss b/client/app/components/sound-list/sound-list.scss similarity index 78% rename from client/app/components/SoundList/SoundList.scss rename to client/app/components/sound-list/sound-list.scss index 23cf2e1..66035d8 100644 --- a/client/app/components/SoundList/SoundList.scss +++ b/client/app/components/sound-list/sound-list.scss @@ -1,12 +1,12 @@ @import '../../scss/variables'; -.SoundList__item { +.sound-list__item { display: flex; justify-content: space-between; align-items: center; height: 50px; - & + .SoundList__item { + & + .sound-list__item { border-top: 1px solid $gray3; } } diff --git a/client/app/components/SoundList/SoundList.tsx b/client/app/components/sound-list/sound-list.tsx similarity index 91% rename from client/app/components/SoundList/SoundList.tsx rename to client/app/components/sound-list/sound-list.tsx index ea9a922..9cc9dd0 100644 --- a/client/app/components/SoundList/SoundList.tsx +++ b/client/app/components/sound-list/sound-list.tsx @@ -1,6 +1,5 @@ import React from 'react'; - -import './SoundList.scss'; +import './sound-list.scss'; interface Props { soundList: SoundType[]; @@ -64,8 +63,8 @@ export class SoundList extends React.Component { {soundList.length > 0 ? soundList.map((sound: SoundType, index: number) => { return ( -
-
{(sound.prefix || '') + sound.name}
+
+
{(sound.prefix || '') + sound.name}
{this.checkExtension(sound.extension) && this.state.showAudioControls[index] ? (