diff options
| author | 8cy <[email protected]> | 2020-07-23 23:24:17 -0700 |
|---|---|---|
| committer | 8cy <[email protected]> | 2020-07-23 23:24:17 -0700 |
| commit | bb511abc03bb66848947e37a999502b813c77269 (patch) | |
| tree | 612c010fc8317e1cdf11471a18aad0270819d33e /client/src | |
| parent | fix: if clear amount equal or over 100, round down to 99 (diff) | |
| download | dep-core-bb511abc03bb66848947e37a999502b813c77269.tar.xz dep-core-bb511abc03bb66848947e37a999502b813c77269.zip | |
goodbye old uwufier :cry:
Diffstat (limited to 'client/src')
| -rw-r--r-- | client/src/components/App.js | 61 | ||||
| -rw-r--r-- | client/src/components/manageserver/ManageServerSettings.js | 71 | ||||
| -rw-r--r-- | client/src/components/navigation/NavigationBar.js | 50 | ||||
| -rw-r--r-- | client/src/components/selection/ServerCard.js | 37 | ||||
| -rw-r--r-- | client/src/index.js | 20 | ||||
| -rw-r--r-- | client/src/pages/ManageServer.js | 69 | ||||
| -rw-r--r-- | client/src/pages/ServerSelection.js | 33 | ||||
| -rw-r--r-- | client/src/serviceWorker.js | 141 | ||||
| -rw-r--r-- | client/src/styles/styles.css | 8 |
9 files changed, 490 insertions, 0 deletions
diff --git a/client/src/components/App.js b/client/src/components/App.js new file mode 100644 index 0000000..270e199 --- /dev/null +++ b/client/src/components/App.js @@ -0,0 +1,61 @@ +import React, { Component } from 'react'; +import { BrowserRouter as Router, Route } from 'react-router-dom'; +import fetch from 'node-fetch'; + +import NavigationBar from './navigation/NavigationBar'; +import ServerSelection from '../pages/ServerSelection'; +import ManageServer from '../pages/ManageServer'; + +export default class App extends Component { + state = { + loading: true, + user: null + } + + componentDidMount() { + fetch('http://localhost:8088/oauth/details', { + credentials: 'include' + }) + .then(res => res.json()) + .then(res => { + if (!res) return this.setState({ loading: false }); + this.setState({ + loading: false, + user: res + }) + }) + .catch(() => this.setState({ loading: false })); + } + + render() { + if (this.state.loading) { + return( + <React.Fragment> + <div className="container"> + <h1>Loading...</h1> + </div> + </React.Fragment> + ); + } else if (!this.state.user) { + window.location.replace('http://localhost:8088/oauth/login'); // OAuth2... + return (<React.Fragment />); + } else { + return( + <React.Fragment> + <Router> + <div className="container"> + <NavigationBar user={this.state.user} /> + + <br /> + + <Route exact path="/" render={(props) => <ServerSelection {...props} user={this.state.user} /> } /> + <Route exact path="/server/:id" render={(props) => <ManageServer {...props} user={this.state.user} /> } /> + + <br /> + </div> + </Router> + </React.Fragment> + ); + } + } +}
\ No newline at end of file diff --git a/client/src/components/manageserver/ManageServerSettings.js b/client/src/components/manageserver/ManageServerSettings.js new file mode 100644 index 0000000..66a5fe5 --- /dev/null +++ b/client/src/components/manageserver/ManageServerSettings.js @@ -0,0 +1,71 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { MDBCard, MDBCardHeader, MDBCardBody, MDBInput, MDBAlert, MDBBtn } from 'mdbreact'; +import fetch from 'node-fetch'; + +export default class ManageServerSettings extends Component { + state = { + error: null, + success: false, + disabled: false + } + + handleSave() { + this.setState({ + error: null, + success: false, + disabled: true + }); + + fetch(`http://localhost:8088/v1/post/guild-name/${this.props.guild}`, { + method: 'POST', + credentials: 'include', + headers: { + 'Authorization': process.env.REACT_APP_AUTHORIZATION, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + name: this.props.data.name + }) + }) + .then(res => res.json()) + .then(res => { + if (res.message) return this.setState({ error: res.message, disabled: false }); + + this.setState({ success: true }); + }) + .catch(err => { + console.log(err); + this.setState({ error: 'An unknown error occured' }); + }); + } + + render() { + return( + <React.Fragment> + <MDBCard> + <MDBCardHeader> + <h3>Server Settings</h3> + </MDBCardHeader> + <MDBCardBody> + {this.state.error && + <MDBAlert color="danger">{this.state.error}</MDBAlert> + } + {this.state.success && + <MDBAlert color="success">Updated server settings successfully</MDBAlert> + } + + <MDBInput id="name" label="Server name" value={this.props.data.name} onChange={this.props.handleInput} /> + <MDBBtn color="dark" onClick={this.handleSave.bind(this)} disabled={this.state.disabled}>Save</MDBBtn> + </MDBCardBody> + </MDBCard> + </React.Fragment> + ) + } +} + +ManageServerSettings.propTypes = { + data: PropTypes.object, + handleInput: PropTypes.func, + guild: PropTypes.string +}
\ No newline at end of file diff --git a/client/src/components/navigation/NavigationBar.js b/client/src/components/navigation/NavigationBar.js new file mode 100644 index 0000000..3962aae --- /dev/null +++ b/client/src/components/navigation/NavigationBar.js @@ -0,0 +1,50 @@ +import React, { Component } from 'react'; +import { + MDBNavbar, MDBNavbarBrand, MDBNavbarNav, MDBNavItem, MDBNavLink, MDBNavbarToggler, MDBCollapse, MDBIcon, + MDBDropdown, MDBDropdownToggle, MDBDropdownMenu, MDBDropdownItem, MDBCol +} from 'mdbreact' +import PropTypes from 'prop-types'; + +export default class NavigationBar extends Component { + state = { + isOpen: false + }; + + toggleCollapse() { + this.setState({ isOpen: !this.state.isOpen }); + } + + render() { + return( + <MDBNavbar color="black" dark expand="md"> + <MDBNavbarBrand> + <strong className="white-text">Bot Dashboard</strong> + </MDBNavbarBrand> + <MDBNavbarToggler onClick={this.toggleCollapse} /> + <MDBCollapse id="navbarCollapse" isOpen={this.state.isOpen} navbar> + <MDBNavbarNav left> + <MDBNavItem> + <MDBNavLink to="/">Server Selection</MDBNavLink> + </MDBNavItem> + </MDBNavbarNav> + <MDBNavbarNav right> + <MDBNavItem> + <MDBDropdown> + <MDBDropdownToggle nav caret> + <MDBIcon icon='user' /> + </MDBDropdownToggle> + <MDBDropdownMenu className="dropdown-default"> + <MDBDropdownItem href="http://localhost:8088/oauth/logout">{`Logout (${this.props.user.username})`}</MDBDropdownItem> + </MDBDropdownMenu> + </MDBDropdown> + </MDBNavItem> + </MDBNavbarNav> + </MDBCollapse> + </MDBNavbar> + ); + } +} + +NavigationBar.propTypes = { + user: PropTypes.object +}
\ No newline at end of file diff --git a/client/src/components/selection/ServerCard.js b/client/src/components/selection/ServerCard.js new file mode 100644 index 0000000..93c7ad6 --- /dev/null +++ b/client/src/components/selection/ServerCard.js @@ -0,0 +1,37 @@ +import React, { Component } from 'react'; +import { Link } from 'react-router-dom'; +import PropTypes from 'prop-types'; +import { MDBBtn, MDBCard, MDBCardBody, MDBCardTitle, MDBCol } from 'mdbreact'; + +export default class ServerCard extends Component { + render() { + return( + <React.Fragment> + <MDBCol size={6}> + <MDBCard className="server-card"> + <MDBCardBody> + <img + width="200px" + alt={`Icon of ${this.props.guild.name}`} + className="server-card-image" + src={this.props.guild.icon ? + `https://cdn.discordapp.com/icons/${this.props.guild.id}/${this.props.guild.icon}.png?size=4096` : + `https://cdn.discordapp.com/embed/avatars/3.png` + } + /> + + <MDBCardTitle><h6><strong>{this.props.guild.name}</strong></h6></MDBCardTitle> + <Link to={`/server/${this.props.guild.id}`}> + <MDBBtn color="primary">Manage</MDBBtn> + </Link> + </MDBCardBody> + </MDBCard> + </MDBCol> + </React.Fragment> + ) + } +} + +ServerCard.propTypes = { + guild: PropTypes.object +}
\ No newline at end of file diff --git a/client/src/index.js b/client/src/index.js new file mode 100644 index 0000000..88c1be6 --- /dev/null +++ b/client/src/index.js @@ -0,0 +1,20 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import '@fortawesome/fontawesome-free/css/all.min.css'; +import 'bootstrap-css-only/css/bootstrap.min.css'; +import 'mdbreact/dist/css/mdb.css'; +import './styles/styles.css' +import App from './components/App'; +import * as serviceWorker from './serviceWorker'; + +ReactDOM.render( + <React.StrictMode> + <App /> + </React.StrictMode>, + document.getElementById('root') +); + +// If you want your app to work offline and load faster, you can change +// unregister() to register() below. Note this comes with some pitfalls. +// Learn more about service workers: https://bit.ly/CRA-PWA +serviceWorker.unregister(); diff --git a/client/src/pages/ManageServer.js b/client/src/pages/ManageServer.js new file mode 100644 index 0000000..990884e --- /dev/null +++ b/client/src/pages/ManageServer.js @@ -0,0 +1,69 @@ +import React, { Component } from 'react'; +import fetch from 'node-fetch'; +import PropTypes from 'prop-types'; +import { MDBBadge, MDBAlert } from 'mdbreact'; + +import ManageServerSettings from '../components/manageserver/ManageServerSettings'; + +export default class ManageServer extends Component { + constructor(props) { + super(props) + + this.state = { + loading: true, + data: null + } + + this.handleInput = this.handleInput.bind(this); + } + + componentDidMount() { + fetch(`http://localhost:8088/v1/get/guild/${this.props.match.params.id}`) + .then(res => res.json()) + .then(res => this.setState({ + loading: false, + data: res.message ? null : res + })) + .catch(() => this.setState({ loading: false })); + } + + handleInput(event) { + const eventId = event.target.id; + const value = event.target.value; + + this.setState(prevState => ({ + data: { + ...prevState.data, + [eventId]: value + } + })); + } + + render() { + if (this.state.loading) { + return( + <h1>Loading...</h1> + ); + } else if(!this.state.data) { + return( + <MDBAlert color="warning">This bot is not in this server</MDBAlert> + ); + } else { + return( + <React.Fragment> + <h1><strong>{this.state.data.name}</strong></h1> + <MDBBadge color="info">{`${this.state.data.members} Members`}</MDBBadge> + <MDBBadge color="success">{`Owner: ${this.state.data.owner}`}</MDBBadge> + + <hr /> + + <ManageServerSettings data={this.state.data} handleInput={this.handleInput} guild={this.props.match.params.id} /> + </React.Fragment> + ) + } + } +} + +ManageServer.propTypes = { + user: PropTypes.object +}
\ No newline at end of file diff --git a/client/src/pages/ServerSelection.js b/client/src/pages/ServerSelection.js new file mode 100644 index 0000000..f1e3a39 --- /dev/null +++ b/client/src/pages/ServerSelection.js @@ -0,0 +1,33 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { MDBAlert, MDBRow } from 'mdbreact'; + +import ServerCard from '../components/selection/ServerCard'; + +export default class ServerSelection extends Component { + render() { + const guilds = this.props.user.guilds.filter(g => g.admin); + + if (!guilds.length) { + return( + <MDBAlert color="warning"> + <strong>You cannot manage any servers</strong> + </MDBAlert> + ); + } else { + return( + <React.Fragment> + <MDBRow> + {guilds.map(guild => { + return(<ServerCard guild={guild} />); + })} + </MDBRow> + </React.Fragment> + ); + } + } +} + +ServerSelection.propTypes = { + user: PropTypes.object +}
\ No newline at end of file diff --git a/client/src/serviceWorker.js b/client/src/serviceWorker.js new file mode 100644 index 0000000..b04b771 --- /dev/null +++ b/client/src/serviceWorker.js @@ -0,0 +1,141 @@ +// This optional code is used to register a service worker. +// register() is not called by default. + +// This lets the app load faster on subsequent visits in production, and gives +// it offline capabilities. However, it also means that developers (and users) +// will only see deployed updates on subsequent visits to a page, after all the +// existing tabs open on the page have been closed, since previously cached +// resources are updated in the background. + +// To learn more about the benefits of this model and instructions on how to +// opt-in, read https://bit.ly/CRA-PWA + +const isLocalhost = Boolean( + window.location.hostname === 'localhost' || + // [::1] is the IPv6 localhost address. + window.location.hostname === '[::1]' || + // 127.0.0.0/8 are considered localhost for IPv4. + window.location.hostname.match( + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ + ) +); + +export function register(config) { + if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { + // The URL constructor is available in all browsers that support SW. + const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); + if (publicUrl.origin !== window.location.origin) { + // Our service worker won't work if PUBLIC_URL is on a different origin + // from what our page is served on. This might happen if a CDN is used to + // serve assets; see https://github.com/facebook/create-react-app/issues/2374 + return; + } + + window.addEventListener('load', () => { + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; + + if (isLocalhost) { + // This is running on localhost. Let's check if a service worker still exists or not. + checkValidServiceWorker(swUrl, config); + + // Add some additional logging to localhost, pointing developers to the + // service worker/PWA documentation. + navigator.serviceWorker.ready.then(() => { + console.log( + 'This web app is being served cache-first by a service ' + + 'worker. To learn more, visit https://bit.ly/CRA-PWA' + ); + }); + } else { + // Is not localhost. Just register service worker + registerValidSW(swUrl, config); + } + }); + } +} + +function registerValidSW(swUrl, config) { + navigator.serviceWorker + .register(swUrl) + .then(registration => { + registration.onupdatefound = () => { + const installingWorker = registration.installing; + if (installingWorker == null) { + return; + } + installingWorker.onstatechange = () => { + if (installingWorker.state === 'installed') { + if (navigator.serviceWorker.controller) { + // At this point, the updated precached content has been fetched, + // but the previous service worker will still serve the older + // content until all client tabs are closed. + console.log( + 'New content is available and will be used when all ' + + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' + ); + + // Execute callback + if (config && config.onUpdate) { + config.onUpdate(registration); + } + } else { + // At this point, everything has been precached. + // It's the perfect time to display a + // "Content is cached for offline use." message. + console.log('Content is cached for offline use.'); + + // Execute callback + if (config && config.onSuccess) { + config.onSuccess(registration); + } + } + } + }; + }; + }) + .catch(error => { + console.error('Error during service worker registration:', error); + }); +} + +function checkValidServiceWorker(swUrl, config) { + // Check if the service worker can be found. If it can't reload the page. + fetch(swUrl, { + headers: { 'Service-Worker': 'script' }, + }) + .then(response => { + // Ensure service worker exists, and that we really are getting a JS file. + const contentType = response.headers.get('content-type'); + if ( + response.status === 404 || + (contentType != null && contentType.indexOf('javascript') === -1) + ) { + // No service worker found. Probably a different app. Reload the page. + navigator.serviceWorker.ready.then(registration => { + registration.unregister().then(() => { + window.location.reload(); + }); + }); + } else { + // Service worker found. Proceed as normal. + registerValidSW(swUrl, config); + } + }) + .catch(() => { + console.log( + 'No internet connection found. App is running in offline mode.' + ); + }); +} + +export function unregister() { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.ready + .then(registration => { + registration.unregister(); + }) + .catch(error => { + console.error(error.message); + }); + } +} diff --git a/client/src/styles/styles.css b/client/src/styles/styles.css new file mode 100644 index 0000000..b988e04 --- /dev/null +++ b/client/src/styles/styles.css @@ -0,0 +1,8 @@ +.server-card { + text-align: center; + margin-bottom: 20px; +} + +.server-card-image { + border-radius: 50%; +}
\ No newline at end of file |