diff --git a/UI/config-overrides.js b/UI/config-overrides.js index 760dc75..9e93b5a 100644 --- a/UI/config-overrides.js +++ b/UI/config-overrides.js @@ -1,4 +1,2 @@ -const { override, addDecoratorsLegacy } = require('customize-cra') -module.exports = override( - addDecoratorsLegacy() -) \ No newline at end of file +const { override, addDecoratorsLegacy } = require("customize-cra"); +module.exports = override(addDecoratorsLegacy()); diff --git a/UI/package.json b/UI/package.json index 2ac5324..27b3d92 100644 --- a/UI/package.json +++ b/UI/package.json @@ -31,7 +31,8 @@ "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test", - "eject": "react-app-rewired eject" + "eject": "react-app-rewired eject", + "lint:prettier": "prettier -c '**/*.{ts,tsx,css,yml,yaml,md,json,js,jsx}'" }, "eslintConfig": { "extends": "react-app" @@ -53,6 +54,7 @@ "eslint-plugin-react": "^7.11.1", "eslint-plugin-standard": "^4.0.0", "node-sass-chokidar": "^1.3.4", + "prettier": "^1.19.1", "react-app-rewire-scss": "^1.0.2", "react-app-rewired": "^2.1.1", "redux-devtools": "^3.4.1", diff --git a/UI/src/.prettierrc.js b/UI/src/.prettierrc.js new file mode 100644 index 0000000..d58c0ce --- /dev/null +++ b/UI/src/.prettierrc.js @@ -0,0 +1,9 @@ +module.exports = { + printWidth: 90, + useTabs: false, + tabWidth: 2, + singleQuote: true, + trailingComma: 'es5', + bracketSpacing: true, + semi: true, +}; diff --git a/UI/src/App.css b/UI/src/App.css index c5c6e8a..31be39d 100644 --- a/UI/src/App.css +++ b/UI/src/App.css @@ -23,6 +23,10 @@ } @keyframes App-logo-spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } } diff --git a/UI/src/App.js b/UI/src/App.js index f3d83ec..cbaabca 100644 --- a/UI/src/App.js +++ b/UI/src/App.js @@ -1,29 +1,29 @@ -import React, { Component } from 'react' -import { Provider } from 'react-redux' -import { ConnectedRouter } from 'react-router-redux' -import { DragDropContext } from 'react-dnd' -import HTML5Backend from 'react-dnd-html5-backend' -import createHistory from 'history/createBrowserHistory' -import configureStore from './store/configureStore' -import './App.css' -import './generic.sass' +import React, { Component } from 'react'; +import { Provider } from 'react-redux'; +import { ConnectedRouter } from 'react-router-redux'; +import { DragDropContext } from 'react-dnd'; +import HTML5Backend from 'react-dnd-html5-backend'; +import createHistory from 'history/createBrowserHistory'; +import configureStore from './store/configureStore'; +import './App.css'; +import './generic.sass'; -import Wrapper from './components/wrapper' -import AppRouter from './router' -import { userInit } from './actions' +import Wrapper from './components/wrapper'; +import AppRouter from './router'; +import { userInit } from './actions'; -const history = createHistory() -const store = configureStore(undefined, history) +const history = createHistory(); +const store = configureStore(undefined, history); -window.__APP_STORE__ = store +window.__APP_STORE__ = store; @DragDropContext(HTML5Backend) class App extends Component { - componentWillMount () { - store.dispatch(userInit) + componentWillMount() { + store.dispatch(userInit); } - render () { + render() { return ( @@ -32,8 +32,8 @@ class App extends Component { - ) + ); } } -export default App +export default App; diff --git a/UI/src/actions/index.js b/UI/src/actions/index.js index 47dbe67..0fae6fb 100644 --- a/UI/src/actions/index.js +++ b/UI/src/actions/index.js @@ -1,87 +1,88 @@ -import superagent from 'superagent' -import { push } from 'react-router-redux' +import superagent from 'superagent'; +import { push } from 'react-router-redux'; export const fetchServers = async dispatch => { - const rsp = await superagent.get('/api/servers') + const rsp = await superagent.get('/api/servers'); dispatch({ type: Symbol.for('update servers'), - data: rsp.body - }) + data: rsp.body, + }); dispatch({ - type: Symbol.for('app ready') - }) -} + type: Symbol.for('app ready'), + }); +}; export const userInit = async dispatch => { if (!window.location.pathname.startsWith('/oauth')) { try { - const rsp = await superagent.get('/api/auth/user') + const rsp = await superagent.get('/api/auth/user'); dispatch({ type: Symbol.for('set user'), - data: rsp.body - }) - - dispatch(fetchServers) + data: rsp.body, + }); + + dispatch(fetchServers); } catch (e) { dispatch({ - type: Symbol.for('app ready') - }) + type: Symbol.for('app ready'), + }); // window.location.href = '/oauth/flow' } } else { dispatch({ - type: Symbol.for('app ready') - }) + type: Symbol.for('app ready'), + }); } -} +}; export const userLogout = async dispatch => { try { - await superagent.post('/api/auth/logout') - } catch (e) { - } + await superagent.post('/api/auth/logout'); + } catch (e) {} dispatch({ - type: Symbol.for('reset user') - }) + type: Symbol.for('reset user'), + }); - window.location.href = '/' -} + window.location.href = '/'; +}; export const startServerPolling = dispatch => { - return poll(window.__APP_STORE__.dispatch, window.__APP_STORE__.getState) // let's not cheat... :c -} + return poll(window.__APP_STORE__.dispatch, window.__APP_STORE__.getState); // let's not cheat... :c +}; const poll = (dispatch, getState) => { - const { servers } = getState() - let stop = false - const stopPolling = () => { stop = true } + const { servers } = getState(); + let stop = false; + const stopPolling = () => { + stop = true; + }; const pollFunc = async () => { if (stop) { - return + return; } try { - await fetchServers(dispatch) + await fetchServers(dispatch); } catch (e) { - console.error(e) - setTimeout(pollFunc, 5000) + console.error(e); + setTimeout(pollFunc, 5000); } - const newServers = getState().servers + const newServers = getState().servers; if (servers.size >= newServers.size) { - setTimeout(pollFunc, 5000) + setTimeout(pollFunc, 5000); } else { - const old = servers.keySeq().toSet() - const upd = newServers.keySeq().toSet() - const newSrv = upd.subtract(old) - stopPolling() - dispatch(push(`/s/${newSrv.toJS()[0]}/edit`)) + const old = servers.keySeq().toSet(); + const upd = newServers.keySeq().toSet(); + const newSrv = upd.subtract(old); + stopPolling(); + dispatch(push(`/s/${newSrv.toJS()[0]}/edit`)); } - } + }; - pollFunc() - return stopPolling -} + pollFunc(); + return stopPolling; +}; diff --git a/UI/src/actions/ui.js b/UI/src/actions/ui.js index 2182bea..7076c2f 100644 --- a/UI/src/actions/ui.js +++ b/UI/src/actions/ui.js @@ -1,13 +1,13 @@ export const fadeOut = cb => dispatch => { dispatch({ type: Symbol.for('app fade'), - data: true - }) + data: true, + }); - setTimeout(cb, 300) -} + setTimeout(cb, 300); +}; export const fadeIn = { type: Symbol.for('app fade'), - data: false -} + data: false, +}; diff --git a/UI/src/components/add-server/index.js b/UI/src/components/add-server/index.js index 7e4bd74..a74165b 100644 --- a/UI/src/components/add-server/index.js +++ b/UI/src/components/add-server/index.js @@ -1,41 +1,64 @@ -import React, { Component } from 'react' -import { Link } from 'react-router-dom' -import TypingDemo from '../demos/typing' -import RoleypolyDemo from '../demos/roleypoly' -import * as Actions from '../../actions' -import './styles.sass' -import discordLogo from '../../pages/images/discord-logo.svg' +import React, { Component } from 'react'; +import { Link } from 'react-router-dom'; +import TypingDemo from '../demos/typing'; +import RoleypolyDemo from '../demos/roleypoly'; +import * as Actions from '../../actions'; +import './styles.sass'; +import discordLogo from '../../pages/images/discord-logo.svg'; export default class AddServer extends Component { - polling = null - - componentDidMount () { + polling = null; + + componentDidMount() { if (this.props.match.params.server !== undefined) { - this.pollingStop = Actions.startServerPolling(this.props.dispatch) + this.pollingStop = Actions.startServerPolling(this.props.dispatch); } } - componentWillUnmount () { + componentWillUnmount() { if (this.pollingStop != null) { - this.pollingStop() + this.pollingStop(); } } - - render () { - return
-

What is Roleypoly?

-

- Roleypoly is a helper bot to help server members assign themselves roles on Discord. -

-
-
-
Could you easily remember 250 role names? You'd use images or bot commands to tell everyone what they can assign. This kinda limits how many roles you can reasonably have. And don't even start with emojis. 💢
-
Just click. 🌈 💖
-
+ + render() { + return ( +
+

What is Roleypoly?

+

+ Roleypoly is a helper bot to help server members assign themselves roles on + Discord. +

+
+
+ +
+
+ Could you easily remember 250 role names? You'd use images or bot commands to + tell everyone what they can assign. This kinda limits how many roles + you can reasonably have. And don't even start with emojis.{' '} + + 💢 + +
+
+ Just click. 🌈 💖 +
+
+ +
+
+
+ + Authorize via + Discord + +
-
- Authorize via Discord -
-
+ ); } } diff --git a/UI/src/components/demos/roleypoly.js b/UI/src/components/demos/roleypoly.js index a58f58a..5646fd2 100644 --- a/UI/src/components/demos/roleypoly.js +++ b/UI/src/components/demos/roleypoly.js @@ -1,12 +1,14 @@ -import React from 'react' -import RoleDemo from '../role/demo' +import React from 'react'; +import RoleDemo from '../role/demo'; -const RoleypolyDemo = () =>
- - - - - -
+const RoleypolyDemo = () => ( +
+ + + + + +
+); -export default RoleypolyDemo +export default RoleypolyDemo; diff --git a/UI/src/components/demos/typing.js b/UI/src/components/demos/typing.js index d8778ab..11e1373 100644 --- a/UI/src/components/demos/typing.js +++ b/UI/src/components/demos/typing.js @@ -1,29 +1,31 @@ -import React from 'react' -import moment from 'moment' -import Typist from 'react-typist' -import './typing.sass' +import React from 'react'; +import moment from 'moment'; +import Typist from 'react-typist'; +import './typing.sass'; -const Typing = () =>
-
- {moment().format('LT')} - Kata カタ - Hey, I want some roles! +const Typing = () => ( +
+
+ {moment().format('LT')} + Kata カタ + Hey, I want some roles! +
+
+ + .iam a cute role ♡ + + .iam a vanity role ♡ + + .iam a brave role ♡ + + .iam a proud role ♡ + + .iam a wonderful role ♡ + + i have too many roles. + +
-
- - .iam a cute role ♡ - - .iam a vanity role ♡ - - .iam a brave role ♡ - - .iam a proud role ♡ - - .iam a wonderful role ♡ - - i have too many roles. - -
-
+); -export default Typing +export default Typing; diff --git a/UI/src/components/dev-tools/index.js b/UI/src/components/dev-tools/index.js index a7d540a..f437a20 100644 --- a/UI/src/components/dev-tools/index.js +++ b/UI/src/components/dev-tools/index.js @@ -1,11 +1,10 @@ -import React from 'react' -import { createDevTools } from 'redux-devtools' -import LogMonitor from 'redux-devtools-log-monitor' -import DockMonitor from 'redux-devtools-dock-monitor' +import React from 'react'; +import { createDevTools } from 'redux-devtools'; +import LogMonitor from 'redux-devtools-log-monitor'; +import DockMonitor from 'redux-devtools-dock-monitor'; export default createDevTools( - + -) \ No newline at end of file +); diff --git a/UI/src/components/logotype/index.js b/UI/src/components/logotype/index.js index 9cecf84..5be9230 100644 --- a/UI/src/components/logotype/index.js +++ b/UI/src/components/logotype/index.js @@ -1,18 +1,44 @@ -import React from 'react' +import React from 'react'; -const Logotype = ({fill = 'var(--c-7)', width, height, circleFill, typeFill, style, className}) => ( - +const Logotype = ({ + fill = 'var(--c-7)', + width, + height, + circleFill, + typeFill, + style, + className, +}) => ( + - + - + - + -) +); -export default Logotype +export default Logotype; diff --git a/UI/src/components/oauth-bot-flow/index.js b/UI/src/components/oauth-bot-flow/index.js index 7786b01..a166610 100644 --- a/UI/src/components/oauth-bot-flow/index.js +++ b/UI/src/components/oauth-bot-flow/index.js @@ -1,27 +1,35 @@ -import React, { Component } from 'react' -import { Redirect } from 'react-router-dom' -import superagent from 'superagent' -import { connect } from 'react-redux' -import { push } from 'react-router-redux' -import { fetchServers } from '../../actions' +import React, { Component } from 'react'; +import { Redirect } from 'react-router-dom'; +import superagent from 'superagent'; +import { connect } from 'react-redux'; +import { push } from 'react-router-redux'; +import { fetchServers } from '../../actions'; @connect() class OauthCallback extends Component { state = { notReady: true, message: 'chotto matte kudasai...', - url: null + url: null, + }; + + async componentDidMount() { + const { + body: { url }, + } = await superagent.get('/api/oauth/bot?url=✔️'); + this.setState({ url, notReady: false }); + window.location.href = url; } - async componentDidMount () { - const { body: { url } } = await superagent.get('/api/oauth/bot?url=✔️') - this.setState({ url, notReady: false }) - window.location.href = url - } - - render () { - return (this.state.notReady) ? this.state.message : Something oopsed, click me to get to where you meant. + render() { + return this.state.notReady ? ( + this.state.message + ) : ( + + Something oopsed, click me to get to where you meant. + + ); } } -export default OauthCallback +export default OauthCallback; diff --git a/UI/src/components/oauth-callback/index.js b/UI/src/components/oauth-callback/index.js index e895f5f..4da3423 100644 --- a/UI/src/components/oauth-callback/index.js +++ b/UI/src/components/oauth-callback/index.js @@ -1,83 +1,87 @@ -import React, { Component } from 'react' -import { Redirect } from 'react-router-dom' -import superagent from 'superagent' -import { connect } from 'react-redux' -import { fetchServers } from '../../actions' +import React, { Component } from 'react'; +import { Redirect } from 'react-router-dom'; +import superagent from 'superagent'; +import { connect } from 'react-redux'; +import { fetchServers } from '../../actions'; @connect() class OauthCallback extends Component { state = { notReady: true, message: 'chotto matte kudasai...', - redirect: '/s' + redirect: '/s', + }; + + stopped = false; + + componentDidUnmount() { + this.stopped = true; } - stopped = false - - componentDidUnmount () { - this.stopped = true - } - - async componentDidMount () { + async componentDidMount() { // handle stuff in the url - const sp = new URLSearchParams(this.props.location.search) - const token = sp.get('code') - + const sp = new URLSearchParams(this.props.location.search); + const token = sp.get('code'); + if (token === '' || token == null) { - this.setState({ message: 'token missing, what are you trying to do?!' }) - return - } - - const stateToken = sp.get('state') - const state = JSON.parse(window.sessionStorage.getItem('state') || 'null') + this.setState({ message: 'token missing, what are you trying to do?!' }); + return; + } + + const stateToken = sp.get('state'); + const state = JSON.parse(window.sessionStorage.getItem('state') || 'null'); if (state !== null && state.state === stateToken && state.redirect != null) { - this.setState({ redirect: state.redirect }) + this.setState({ redirect: state.redirect }); } - this.props.history.replace(this.props.location.pathname) - - let counter = 0 + this.props.history.replace(this.props.location.pathname); + + let counter = 0; const retry = async () => { - if (this.stopped) return + if (this.stopped) return; try { - const rsp = await superagent.get('/api/auth/user') + const rsp = await superagent.get('/api/auth/user'); this.props.dispatch({ type: Symbol.for('set user'), - data: rsp.body - }) - this.props.dispatch(fetchServers) - this.setState({ notReady: false }) + data: rsp.body, + }); + this.props.dispatch(fetchServers); + this.setState({ notReady: false }); } catch (e) { - counter++ + counter++; if (counter > 10) { - this.setState({ message: "i couldn't log you in. :c" }) + this.setState({ message: "i couldn't log you in. :c" }); } else { - setTimeout(() => { retry() }, 250) + setTimeout(() => { + retry(); + }, 250); } } - } + }; // pass token to backend, await it to finish it's business. try { - await superagent.post('/api/auth/token').send({ token }) + await superagent.post('/api/auth/token').send({ token }); // this.props.onLogin(rsp.body) - - retry() + retry(); } catch (e) { - console.error('token pass error', e) - this.setState({ message: 'g-gomen nasai... i broke it...' }) - return - } - + console.error('token pass error', e); + this.setState({ message: 'g-gomen nasai... i broke it...' }); + return; + } // update user stuff here } - render () { - return (this.state.notReady) ? this.state.message : + render() { + return this.state.notReady ? ( + this.state.message + ) : ( + + ); } } -export default OauthCallback +export default OauthCallback; diff --git a/UI/src/components/oauth-flow/index.js b/UI/src/components/oauth-flow/index.js index 60a9fd6..ea0dd57 100644 --- a/UI/src/components/oauth-flow/index.js +++ b/UI/src/components/oauth-flow/index.js @@ -1,10 +1,9 @@ -import React, { Component } from 'react' -import { Redirect } from 'react-router-dom' -import superagent from 'superagent' -import { connect } from 'react-redux' -import uuidv4 from 'uuid/v4' -import { fetchServers } from '../../actions' - +import React, { Component } from 'react'; +import { Redirect } from 'react-router-dom'; +import superagent from 'superagent'; +import { connect } from 'react-redux'; +import uuidv4 from 'uuid/v4'; +import { fetchServers } from '../../actions'; @connect() class OauthCallback extends Component { @@ -12,62 +11,76 @@ class OauthCallback extends Component { notReady: true, message: 'chotto matte kudasai...', redirect: '/s', - url: null - } + url: null, + }; - async fetchUser () { - const rsp = await superagent.get('/api/auth/user') - sessionStorage.setItem('user', JSON.stringify(rsp.body)) - sessionStorage.setItem('user.update', JSON.stringify(Date.now())) + async fetchUser() { + const rsp = await superagent.get('/api/auth/user'); + sessionStorage.setItem('user', JSON.stringify(rsp.body)); + sessionStorage.setItem('user.update', JSON.stringify(Date.now())); this.props.dispatch({ type: Symbol.for('set user'), - data: rsp.body - }) + data: rsp.body, + }); } - setupUser () { - const userUpdateTime = sessionStorage.getItem('user.update') || 0 - if (+userUpdateTime + (1000 * 60 * 10) > Date.now()) { - const user = sessionStorage.getItem('user') + setupUser() { + const userUpdateTime = sessionStorage.getItem('user.update') || 0; + if (+userUpdateTime + 1000 * 60 * 10 > Date.now()) { + const user = sessionStorage.getItem('user'); if (user != null && user !== '') { this.props.dispatch({ type: Symbol.for('set user'), - data: JSON.parse(user) - }) + data: JSON.parse(user), + }); } } - return this.fetchUser() + return this.fetchUser(); } - async componentDidMount () { - const state = uuidv4() + async componentDidMount() { + const state = uuidv4(); - const oUrl = new URL(window.location.href) + const oUrl = new URL(window.location.href); if (oUrl.searchParams.has('r')) { - this.setState({ redirect: oUrl.searchParams.get('r') }) + this.setState({ redirect: oUrl.searchParams.get('r') }); } - window.sessionStorage.setItem('state', JSON.stringify({ state, redirect: oUrl.searchParams.get('r') })) + window.sessionStorage.setItem( + 'state', + JSON.stringify({ state, redirect: oUrl.searchParams.get('r') }) + ); try { - await this.setupUser() + await this.setupUser(); - this.props.dispatch(fetchServers) - this.setState({ notReady: false }) + this.props.dispatch(fetchServers); + this.setState({ notReady: false }); } catch (e) { - const { body: { url } } = await superagent.get('/api/auth/redirect?url=✔️') - const nUrl = new URL(url) + const { + body: { url }, + } = await superagent.get('/api/auth/redirect?url=✔️'); + const nUrl = new URL(url); - nUrl.searchParams.set('state', state) - this.setState({ url: nUrl.toString() }) - window.location.href = nUrl.toString() + nUrl.searchParams.set('state', state); + this.setState({ url: nUrl.toString() }); + window.location.href = nUrl.toString(); } } - render () { - return (this.state.notReady) ? this.state.message : <>Something oopsed, click me to get to where you meant. + render() { + return this.state.notReady ? ( + this.state.message + ) : ( + <> + + + Something oopsed, click me to get to where you meant. + + + ); } } -export default OauthCallback +export default OauthCallback; diff --git a/UI/src/components/role-editor/Category.js b/UI/src/components/role-editor/Category.js index c615685..2e8172d 100644 --- a/UI/src/components/role-editor/Category.js +++ b/UI/src/components/role-editor/Category.js @@ -1,43 +1,69 @@ -import React, { Component } from 'react' -import { DropTarget } from 'react-dnd' +import React, { Component } from 'react'; +import { DropTarget } from 'react-dnd'; -import Role from '../role/draggable' -import CategoryEditor from './CategoryEditor' +import Role from '../role/draggable'; +import CategoryEditor from './CategoryEditor'; -@DropTarget(Symbol.for('dnd: role'), { - drop (props, monitor, element) { - props.onDrop(monitor.getItem()) +@DropTarget( + Symbol.for('dnd: role'), + { + drop(props, monitor, element) { + props.onDrop(monitor.getItem()); + }, + canDrop(props, monitor) { + return ( + props.mode !== Symbol.for('edit') && monitor.getItem().category !== props.name + ); + }, }, - canDrop (props, monitor) { - return (props.mode !== Symbol.for('edit') && monitor.getItem().category !== props.name) - } -}, (connect, monitor) => ({ - connectDropTarget: connect.dropTarget(), - isOver: monitor.isOver(), - isOverCurrent: monitor.isOver({ shallow: true }), - canDrop: monitor.canDrop(), - itemType: monitor.getItemType() -})) + (connect, monitor) => ({ + connectDropTarget: connect.dropTarget(), + isOver: monitor.isOver(), + isOverCurrent: monitor.isOver({ shallow: true }), + canDrop: monitor.canDrop(), + itemType: monitor.getItemType(), + }) +) class Category extends Component { - render () { - const { category, name, isOver, canDrop, connectDropTarget, mode, onEditOpen, ...rest } = this.props + render() { + const { + category, + name, + isOver, + canDrop, + connectDropTarget, + mode, + onEditOpen, + ...rest + } = this.props; if (mode === Symbol.for('edit')) { - return + return ; } - return connectDropTarget(
-
-

{ category.get('name') }

-
-
- { - category.get('roles_map') + return connectDropTarget( +
+
+

{category.get('name')}

+
+
+ {category + .get('roles_map') .reverse() .map((r, k) => ) - .toArray() - } -
) + .toArray()} +
+ ); } } -export default Category +export default Category; diff --git a/UI/src/components/role-editor/CategoryEditor.js b/UI/src/components/role-editor/CategoryEditor.js index 40e292f..1926cd9 100644 --- a/UI/src/components/role-editor/CategoryEditor.js +++ b/UI/src/components/role-editor/CategoryEditor.js @@ -1,86 +1,109 @@ -import React, { Component } from 'react' +import React, { Component } from 'react'; export default class CategoryEditor extends Component { - - onKeyPress = (e) => { - const { onSave } = this.props + onKeyPress = e => { + const { onSave } = this.props; switch (e.key) { case 'Enter': case 'Escape': - return onSave() + return onSave(); } - } + }; - render () { - const { - category - } = this.props + render() { + const { category } = this.props; - return
-
-
- -
- -
-
-
- -
-
- -
-
-
-
-
-
-
+ ); } } diff --git a/UI/src/components/role-editor/actions.js b/UI/src/components/role-editor/actions.js index 3be1789..1a1f414 100644 --- a/UI/src/components/role-editor/actions.js +++ b/UI/src/components/role-editor/actions.js @@ -1,55 +1,55 @@ -import { Set } from 'immutable' -import * as UIActions from '../../actions/ui' -import { getViewMap, setup } from '../role-picker/actions' -import uuidv4 from 'uuid/v4' -import superagent from 'superagent' +import { Set } from 'immutable'; +import * as UIActions from '../../actions/ui'; +import { getViewMap, setup } from '../role-picker/actions'; +import uuidv4 from 'uuid/v4'; +import superagent from 'superagent'; export const constructView = id => async (dispatch, getState) => { - await setup(id)(dispatch) - const server = getState().servers.get(id) + await setup(id)(dispatch); + const server = getState().servers.get(id); - let { viewMap, hasSafeRoles } = getViewMap(server) - viewMap = viewMap.map((c, idx) => c.set('mode', Symbol.for('drop'))) + let { viewMap, hasSafeRoles } = getViewMap(server); + viewMap = viewMap.map((c, idx) => c.set('mode', Symbol.for('drop'))); dispatch({ type: Symbol.for('re: setup'), data: { hasSafeRoles, viewMap, - originalSnapshot: viewMap - } - }) + originalSnapshot: viewMap, + }, + }); - dispatch(UIActions.fadeIn) -} + dispatch(UIActions.fadeIn); +}; -export const addRoleToCategory = (id, oldId, role, flip = true) => (dispatch) => { +export const addRoleToCategory = (id, oldId, role, flip = true) => dispatch => { dispatch({ type: Symbol.for('re: add role to category'), data: { id, - role - } - }) + role, + }, + }); if (flip) { - dispatch(removeRoleFromCategory(oldId, id, role, false)) + dispatch(removeRoleFromCategory(oldId, id, role, false)); } -} +}; -export const removeRoleFromCategory = (id, oldId, role, flip = true) => (dispatch) => { +export const removeRoleFromCategory = (id, oldId, role, flip = true) => dispatch => { dispatch({ type: Symbol.for('re: remove role from category'), data: { id, - role - } - }) + role, + }, + }); if (flip) { - dispatch(addRoleToCategory(oldId, id, role, false)) + dispatch(addRoleToCategory(oldId, id, role, false)); } -} +}; export const editCategory = ({ id, key, value }) => dispatch => { dispatch({ @@ -57,38 +57,38 @@ export const editCategory = ({ id, key, value }) => dispatch => { data: { id, key, - value - } - }) -} + value, + }, + }); +}; -export const saveCategory = (id, category) => (dispatch) => { +export const saveCategory = (id, category) => dispatch => { if (category.get('name') === '') { - return + return; } dispatch({ type: Symbol.for('re: switch category mode'), data: { id, - mode: Symbol.for('drop') - } - }) -} + mode: Symbol.for('drop'), + }, + }); +}; -export const openEditor = (id) => ({ +export const openEditor = id => ({ type: Symbol.for('re: switch category mode'), data: { id, - mode: Symbol.for('edit') - } -}) + mode: Symbol.for('edit'), + }, +}); export const deleteCategory = (id, category) => (dispatch, getState) => { - const roles = category.get('roles') - const rolesMap = category.get('roles_map') + const roles = category.get('roles'); + const rolesMap = category.get('roles_map'); - let uncategorized = getState().roleEditor.getIn(['viewMap', 'Uncategorized']) + let uncategorized = getState().roleEditor.getIn(['viewMap', 'Uncategorized']); dispatch({ type: Symbol.for('re: set category'), @@ -99,29 +99,29 @@ export const deleteCategory = (id, category) => (dispatch, getState) => { roles_map: uncategorized.get('roles_map').union(rolesMap), hidden: true, type: 'multi', - mode: null - } - }) + mode: null, + }, + }); dispatch({ type: Symbol.for('re: delete category'), - data: id - }) -} + data: id, + }); +}; export const createCategory = (dispatch, getState) => { - const { roleEditor } = getState() - const vm = roleEditor.get('viewMap') + const { roleEditor } = getState(); + const vm = roleEditor.get('viewMap'); - let name = 'New Category' - let idx = 1 - const pred = c => c.get('name') === name + let name = 'New Category'; + let idx = 1; + const pred = c => c.get('name') === name; while (vm.find(pred) !== undefined) { - idx++ - name = `New Category ${idx}` + idx++; + name = `New Category ${idx}`; } - const id = uuidv4() + const id = uuidv4(); dispatch({ type: Symbol.for('re: set category'), @@ -133,28 +133,28 @@ export const createCategory = (dispatch, getState) => { hidden: true, type: 'multi', position: idx, - mode: Symbol.for('edit') - } - }) -} + mode: Symbol.for('edit'), + }, + }); +}; export const bumpCategory = (category, name) => move => async (dispatch, getState) => { - const { roleEditor } = getState() - const vm = roleEditor.get('viewMap') + const { roleEditor } = getState(); + const vm = roleEditor.get('viewMap'); - const position = category.get('position') - const nextPos = position + move + const position = category.get('position'); + const nextPos = position + move; - const replaceThisOne = vm.findKey(category => category.get('position') === nextPos) + const replaceThisOne = vm.findKey(category => category.get('position') === nextPos); dispatch({ type: Symbol.for('re: edit category'), data: { id: name, key: 'position', - value: nextPos - } - }) + value: nextPos, + }, + }); if (!!replaceThisOne) { dispatch({ @@ -162,27 +162,36 @@ export const bumpCategory = (category, name) => move => async (dispatch, getStat data: { id: replaceThisOne, key: 'position', - value: position - } - }) + value: position, + }, + }); } - -} +}; export const saveServer = id => async (dispatch, getState) => { - const viewMap = getState().roleEditor.get('viewMap') + const viewMap = getState() + .roleEditor.get('viewMap') .filterNot((_, k) => k === 'Uncategorized') - .map(v => v.delete('roles_map').delete('mode').delete('id')) + .map(v => + v + .delete('roles_map') + .delete('mode') + .delete('id') + ); viewMap.map((v, idx) => { if (v.has('position')) { - return v + return v; } - console.warn('category position wasnt set, so fake ones are being made', {cat: v.toJS(), idx, position: viewMap.count()+idx}) - return v.set('position', viewMap.count()+idx) - }) + console.warn('category position wasnt set, so fake ones are being made', { + cat: v.toJS(), + idx, + position: viewMap.count() + idx, + }); + return v.set('position', viewMap.count() + idx); + }); - await superagent.patch(`/api/server/${id}`).send({ categories: viewMap.toJS() }) - dispatch({ type: Symbol.for('re: swap original state') }) -} + await superagent.patch(`/api/server/${id}`).send({ categories: viewMap.toJS() }); + dispatch({ type: Symbol.for('re: swap original state') }); +}; diff --git a/UI/src/components/role-editor/index.js b/UI/src/components/role-editor/index.js index d6d0e0d..6c8d640 100644 --- a/UI/src/components/role-editor/index.js +++ b/UI/src/components/role-editor/index.js @@ -1,197 +1,238 @@ -import React, { Component } from 'react' -import { Set } from 'immutable' -import { connect } from 'react-redux' -import { DropTarget } from 'react-dnd' -import { Link, Prompt, Redirect } from 'react-router-dom' -import { Scrollbars } from 'react-custom-scrollbars' -import * as Actions from './actions' -import * as PickerActions from '../role-picker/actions' -import * as UIActions from '../../actions/ui' -import './RoleEditor.sass' +import React, { Component } from 'react'; +import { Set } from 'immutable'; +import { connect } from 'react-redux'; +import { DropTarget } from 'react-dnd'; +import { Link, Prompt, Redirect } from 'react-router-dom'; +import { Scrollbars } from 'react-custom-scrollbars'; +import * as Actions from './actions'; +import * as PickerActions from '../role-picker/actions'; +import * as UIActions from '../../actions/ui'; +import './RoleEditor.sass'; -import Category from './Category' -import CategoryEditor from './CategoryEditor' -import Role from '../role/draggable' +import Category from './Category'; +import CategoryEditor from './CategoryEditor'; +import Role from '../role/draggable'; const mapState = ({ rolePicker, roleEditor, servers }, ownProps) => ({ rp: rolePicker, editor: roleEditor, - server: servers.get(ownProps.match.params.server) -}) + server: servers.get(ownProps.match.params.server), +}); @connect(mapState) -@DropTarget(Symbol.for('dnd: role'), { - drop (props, monitor, element) { - element.dropRole({}, 'Uncategorized')(monitor.getItem()) +@DropTarget( + Symbol.for('dnd: role'), + { + drop(props, monitor, element) { + element.dropRole({}, 'Uncategorized')(monitor.getItem()); + }, + canDrop(props, monitor) { + return monitor.getItem().category !== 'Uncategorized'; + }, }, - canDrop (props, monitor) { - return (monitor.getItem().category !== 'Uncategorized') - } -}, (connect, monitor) => ({ - connectDropTarget: connect.dropTarget(), - isOver: monitor.isOver(), - isOverCurrent: monitor.isOver({ shallow: true }), - canDrop: monitor.canDrop(), - itemType: monitor.getItemType() -})) + (connect, monitor) => ({ + connectDropTarget: connect.dropTarget(), + isOver: monitor.isOver(), + isOverCurrent: monitor.isOver({ shallow: true }), + canDrop: monitor.canDrop(), + itemType: monitor.getItemType(), + }) +) class RoleEditor extends Component { - componentWillMount () { - const { dispatch, match: { params: { server } } } = this.props - dispatch(Actions.constructView(server)) + componentWillMount() { + const { + dispatch, + match: { + params: { server }, + }, + } = this.props; + dispatch(Actions.constructView(server)); } - componentWillReceiveProps (nextProps) { + componentWillReceiveProps(nextProps) { if (this.props.match.params.server !== nextProps.match.params.server) { - const { dispatch } = this.props - dispatch(UIActions.fadeOut(() => dispatch(Actions.constructView(nextProps.match.params.server)))) + const { dispatch } = this.props; + dispatch( + UIActions.fadeOut(() => + dispatch(Actions.constructView(nextProps.match.params.server)) + ) + ); } } - dropRole = (category, name) => ({role, category}) => { - const { dispatch } = this.props - console.log(role) - dispatch(Actions.addRoleToCategory(name, category, role)) - } + dropRole = (category, name) => ({ role, category }) => { + const { dispatch } = this.props; + console.log(role); + dispatch(Actions.addRoleToCategory(name, category, role)); + }; createCategory = () => { - const { dispatch } = this.props - dispatch(Actions.createCategory) - } + const { dispatch } = this.props; + dispatch(Actions.createCategory); + }; saveCategory = (category, name) => () => { - const { dispatch } = this.props - dispatch(Actions.saveCategory(name, category)) - } + const { dispatch } = this.props; + dispatch(Actions.saveCategory(name, category)); + }; deleteCategory = (category, id) => () => { - const { dispatch } = this.props - dispatch(Actions.deleteCategory(id, category)) - } + const { dispatch } = this.props; + dispatch(Actions.deleteCategory(id, category)); + }; openEditor = (category, name) => () => { - const { dispatch } = this.props - dispatch(Actions.openEditor(name)) - } + const { dispatch } = this.props; + dispatch(Actions.openEditor(name)); + }; editCategory = (category, id) => (key, type) => event => { - const { dispatch } = this.props - let value + const { dispatch } = this.props; + let value; switch (type) { case Symbol.for('edit: text'): - value = event.target.value - break + value = event.target.value; + break; case Symbol.for('edit: bool'): - value = event.target.checked - break - + value = event.target.checked; + break; + case Symbol.for('edit: select'): - value = event.target.value - break - + value = event.target.value; + break; + default: - value = null + value = null; } - dispatch(Actions.editCategory({ category, id, key, type, value })) - } + dispatch(Actions.editCategory({ category, id, key, type, value })); + }; resetServer = () => { - const { dispatch } = this.props - dispatch({ type: Symbol.for('re: reset') }) - } + const { dispatch } = this.props; + dispatch({ type: Symbol.for('re: reset') }); + }; saveServer = () => { - const { dispatch, match: { params: { server } } } = this.props - dispatch(Actions.saveServer(server)) + const { + dispatch, + match: { + params: { server }, + }, + } = this.props; + dispatch(Actions.saveServer(server)); + }; + + onBump = (category, name) => move => () => + this.props.dispatch(Actions.bumpCategory(category, name)(move)); + + get hasChanged() { + return ( + this.props.editor.get('originalSnapshot').hashCode() !== + this.props.editor.get('viewMap').hashCode() + ); } - onBump = (category, name) => (move) => () => this.props.dispatch(Actions.bumpCategory(category, name)(move)) - - get hasChanged () { - return this.props.editor.get('originalSnapshot').hashCode() !== this.props.editor.get('viewMap').hashCode() - } - - render () { - const { server } = this.props + render() { + const { server } = this.props; if (server == null) { - return null + return null; } if (server.getIn(['perms', 'canManageRoles']) !== true) { - return + return ; } - const vm = this.props.editor.get('viewMap') - return
- -
-

{this.props.server.getIn(['server','name'])}

-
-
- - -
-
-
-
- - { - vm - .filter((_, k) => k !== 'Uncategorized') - .sortBy(c => c.get('position')) - .map((c, name, arr) => ) - .toArray() - } -
- + const vm = this.props.editor.get('viewMap'); + return ( +
+ +
+

{this.props.server.getIn(['server', 'name'])}

+
+
+ +
-
- { - this.props.connectDropTarget( -
- -
- { - (vm.getIn(['Uncategorized', 'roles_map']) || Set()) - .sortBy(r => r.get('position')) - .reverse() - .map((r, k) => ) - .toArray() - } - { - (this.props.editor.get('hasSafeRoles') !== true) - ?
- Why are there no roles here? -
- : null - } +
+
+ + {vm + .filter((_, k) => k !== 'Uncategorized') + .sortBy(c => c.get('position')) + .map((c, name, arr) => ( + + )) + .toArray()} +
+
-
) - } +
+ {this.props.connectDropTarget( +
+ +
+ {(vm.getIn(['Uncategorized', 'roles_map']) || Set()) + .sortBy(r => r.get('position')) + .reverse() + .map((r, k) => ) + .toArray()} + {this.props.editor.get('hasSafeRoles') !== true ? ( +
+ + Why are there no roles here? + +
+ ) : null} +
+
+
+ )} +
-
+ ); } } -export default RoleEditor +export default RoleEditor; diff --git a/UI/src/components/role-picker/Category.js b/UI/src/components/role-picker/Category.js index 0bcf855..5e403e4 100644 --- a/UI/src/components/role-picker/Category.js +++ b/UI/src/components/role-picker/Category.js @@ -1,53 +1,68 @@ -import React, { Component } from 'react' -import { Map } from 'immutable' +import React, { Component } from 'react'; +import { Map } from 'immutable'; -import Role from '../role' +import Role from '../role'; class Category extends Component { - - toggleRoleMulti (id, next) { - this.props.onChange(Map({ [id]: next })) + toggleRoleMulti(id, next) { + this.props.onChange(Map({ [id]: next })); } - toggleRoleSingle (id, next) { - this.props.onChange(this.props.category.get('roles').reduce((acc, i) => acc.set(i, false), Map()).set(id, next)) + toggleRoleSingle(id, next) { + this.props.onChange( + this.props.category + .get('roles') + .reduce((acc, i) => acc.set(i, false), Map()) + .set(id, next) + ); } onRoleToggle = id => (next, old) => { - const type = this.props.category.get('type') + const type = this.props.category.get('type'); switch (type) { - case 'single': return this.toggleRoleSingle(id, next) - case 'multi': return this.toggleRoleMulti(id, next) - default: - console.warn('DEFAULTING TO MULTI', id, next, old) - return this.toggleRoleMulti(id, next) + case 'single': + return this.toggleRoleSingle(id, next); + case 'multi': + return this.toggleRoleMulti(id, next); + default: + console.warn('DEFAULTING TO MULTI', id, next, old); + return this.toggleRoleMulti(id, next); } - } + }; - render () { - const { category, name, isSelected } = this.props + render() { + const { category, name, isSelected } = this.props; if (category.get('hidden')) { - return null + return null; } if (category.get('roles').count() === 0) { - return null + return null; } - return
-

{ category.get('name') }

- { - category.get('roles_map') - .sortBy(r => r.get('position')) - .reverse() - .map((r, k) => { - const id = r.get('id') - return - }) - .toArray() - } -
+ return ( +
+

{category.get('name')}

+ {category + .get('roles_map') + .sortBy(r => r.get('position')) + .reverse() + .map((r, k) => { + const id = r.get('id'); + return ( + + ); + }) + .toArray()} +
+ ); } } -export default Category +export default Category; diff --git a/UI/src/components/role-picker/actions.js b/UI/src/components/role-picker/actions.js index 2b59857..24b8653 100644 --- a/UI/src/components/role-picker/actions.js +++ b/UI/src/components/role-picker/actions.js @@ -1,75 +1,89 @@ -import { Map, Set, fromJS } from 'immutable' -import superagent from 'superagent' -import * as UIActions from '../../actions/ui' +import { Map, Set, fromJS } from 'immutable'; +import superagent from 'superagent'; +import * as UIActions from '../../actions/ui'; export const setup = id => async dispatch => { - const rsp = await superagent.get(`/api/server/${id}`) - const data = rsp.body + const rsp = await superagent.get(`/api/server/${id}`); + const data = rsp.body; dispatch({ type: Symbol.for('server: set'), data: { id, - ...data - } - }) - dispatch(constructView(id)) -} + ...data, + }, + }); + dispatch(constructView(id)); +}; export const getViewMap = server => { - const roles = server.get('roles') - const categories = server.get('categories') - const categoriesIds = server.get('categories').keySeq() + const roles = server.get('roles'); + const categories = server.get('categories'); + const categoriesIds = server.get('categories').keySeq(); - const allRoles = server.get('roles').filter(v => v.get('safe')).map(r => r.get('id')).toSet() - const accountedRoles = categories.map(c => c.get('roles')).toSet().flatten() - const unaccountedRoles = allRoles.subtract(accountedRoles) + const allRoles = server + .get('roles') + .filter(v => v.get('safe')) + .map(r => r.get('id')) + .toSet(); + const accountedRoles = categories + .map(c => c.get('roles')) + .toSet() + .flatten(); + const unaccountedRoles = allRoles.subtract(accountedRoles); // console.log('roles', allRoles.toJS(), accountedRoles.toJS(), unaccountedRoles.toJS()) - const viewMap = categories.set('Uncategorized', fromJS({ - roles: unaccountedRoles, - hidden: true, - type: 'multi', - name: 'Uncategorized' - })) - .map( - (cat, idx) => + const viewMap = categories + .set( + 'Uncategorized', + fromJS({ + roles: unaccountedRoles, + hidden: true, + type: 'multi', + name: 'Uncategorized', + }) + ) + .map((cat, idx) => cat.set( - 'position', - cat.get('position', categoriesIds.findIndex(v => v === idx) + 'position', + cat.get( + 'position', + categoriesIds.findIndex(v => v === idx) + ) ) ) - ) - // .sortBy(cat => cat.get('position')) - .map(c => { - const roles = c.get('roles') - // fill in roles_map - .map(r => - server.get('roles').find(sr => sr.get('id') === r) - ) - .filter(r => r != null) - // sort by server position, backwards. - .sort((a, b) => a.position > b.position) - // force data to sets - return c.set('roles_map', Set(roles)).set('roles', Set(c.get('roles'))) - }) + // .sortBy(cat => cat.get('position')) + .map(c => { + const roles = c + .get('roles') + // fill in roles_map + .map(r => server.get('roles').find(sr => sr.get('id') === r)) + .filter(r => r != null) + // sort by server position, backwards. + .sort((a, b) => a.position > b.position); + // force data to sets + return c.set('roles_map', Set(roles)).set('roles', Set(c.get('roles'))); + }); - const selected = roles.reduce((acc, r) => acc.set(r.get('id'), r.get('selected')), Map()) + const selected = roles.reduce( + (acc, r) => acc.set(r.get('id'), r.get('selected')), + Map() + ); - const hasSafeRoles = allRoles.size > 0 + const hasSafeRoles = allRoles.size > 0; return { viewMap, selected, - hasSafeRoles - } -} + hasSafeRoles, + }; +}; export const constructView = id => (dispatch, getState) => { - const server = getState().servers.get(id) + const server = getState().servers.get(id); - const { viewMap, selected } = getViewMap(server) + const { viewMap, selected } = getViewMap(server); dispatch({ type: Symbol.for('rp: setup role picker'), @@ -79,79 +93,79 @@ export const constructView = id => (dispatch, getState) => { originalRolesSelected: selected, hidden: false, isEditingMessage: false, - messageBuffer: '' - } - }) + messageBuffer: '', + }, + }); - dispatch(UIActions.fadeIn) -} + dispatch(UIActions.fadeIn); +}; -export const resetSelected = (dispatch) => { +export const resetSelected = dispatch => { dispatch({ - type: Symbol.for('rp: reset selected') - }) -} + type: Symbol.for('rp: reset selected'), + }); +}; export const submitSelected = serverId => async (dispatch, getState) => { - const { rolePicker } = getState() - const original = rolePicker.get('originalRolesSelected') - const current = rolePicker.get('rolesSelected') + const { rolePicker } = getState(); + const original = rolePicker.get('originalRolesSelected'); + const current = rolePicker.get('rolesSelected'); const diff = original.reduce((acc, v, k) => { if (current.get(k) !== v) { // if original value is false, then we know we're adding, otherwise removing. if (v !== true) { - return acc.set('added', acc.get('added').add(k)) + return acc.set('added', acc.get('added').add(k)); } else { - return acc.set('removed', acc.get('removed').add(k)) + return acc.set('removed', acc.get('removed').add(k)); } } - return acc - }, Map({ added: Set(), removed: Set() })) + return acc; + }, Map({ added: Set(), removed: Set() })); - await superagent.patch(`/api/servers/${serverId}/roles`).send(diff.toJS()) + await superagent.patch(`/api/servers/${serverId}/roles`).send(diff.toJS()); dispatch({ - type: Symbol.for('rp: sync selected roles') - }) -} + type: Symbol.for('rp: sync selected roles'), + }); +}; export const updateRoles = roles => ({ type: Symbol.for('rp: update selected roles'), - data: roles -}) + data: roles, +}); export const openMessageEditor = id => (dispatch, getState) => { - const message = getState().servers.getIn([id, 'message']) - dispatch(editServerMessage(id, message)) + const message = getState().servers.getIn([id, 'message']); + dispatch(editServerMessage(id, message)); dispatch({ type: Symbol.for('rp: set message editor state'), - data: true - }) -} + data: true, + }); +}; export const saveServerMessage = id => async (dispatch, getState) => { - const message = getState().rolePicker.get('messageBuffer') + const message = getState().rolePicker.get('messageBuffer'); - await superagent.patch(`/api/server/${id}`).send({ message }) + await superagent.patch(`/api/server/${id}`).send({ message }); - dispatch(closeMessageEditor) + dispatch(closeMessageEditor); dispatch({ type: Symbol.for('server: edit message'), data: { id, - message - } - }) -} + message, + }, + }); +}; export const editServerMessage = (id, message) => ({ type: Symbol.for('rp: edit message buffer'), - data: message -}) + data: message, +}); -export const closeMessageEditor = ({ +export const closeMessageEditor = { type: Symbol.for('rp: set message editor state'), - data: false -}) + data: false, +}; diff --git a/UI/src/components/role-picker/index.js b/UI/src/components/role-picker/index.js index 3e105d4..22852ff 100644 --- a/UI/src/components/role-picker/index.js +++ b/UI/src/components/role-picker/index.js @@ -1,145 +1,214 @@ -import React, { Component, Fragment } from 'react' -import { connect } from 'react-redux' -import { Prompt } from 'react-router-dom' -import superagent from 'superagent' -import * as Actions from './actions' -import * as UIActions from '../../actions/ui' -import { msgToReal } from '../../utils' -import './RolePicker.sass' +import React, { Component, Fragment } from 'react'; +import { connect } from 'react-redux'; +import { Prompt } from 'react-router-dom'; +import superagent from 'superagent'; +import * as Actions from './actions'; +import * as UIActions from '../../actions/ui'; +import { msgToReal } from '../../utils'; +import './RolePicker.sass'; -import Category from './Category' +import Category from './Category'; import { Scrollbars } from 'react-custom-scrollbars'; import { Link } from 'react-router-dom'; const mapState = ({ rolePicker, servers }, ownProps) => { return { data: rolePicker, - server: servers.get(ownProps.match.params.server) - } -} + server: servers.get(ownProps.match.params.server), + }; +}; @connect(mapState) class RolePicker extends Component { - componentWillMount () { - const { dispatch, match: { params: { server } } } = this.props - dispatch(Actions.setup(server)) + componentWillMount() { + const { + dispatch, + match: { + params: { server }, + }, + } = this.props; + dispatch(Actions.setup(server)); } - componentWillReceiveProps (nextProps) { + componentWillReceiveProps(nextProps) { if (this.props.match.params.server !== nextProps.match.params.server) { - const { dispatch } = this.props - dispatch(UIActions.fadeOut(() => dispatch(Actions.setup(nextProps.match.params.server)))) + const { dispatch } = this.props; + dispatch( + UIActions.fadeOut(() => dispatch(Actions.setup(nextProps.match.params.server))) + ); } } - get serverId () { - return this.props.server.get('id') + get serverId() { + return this.props.server.get('id'); } isSelected = id => { - return this.props.data.getIn([ 'rolesSelected', id ]) + return this.props.data.getIn(['rolesSelected', id]); + }; + + get rolesHaveChanged() { + const { data } = this.props; + return !data.get('rolesSelected').equals(data.get('originalRolesSelected')); } - get rolesHaveChanged () { - const { data } = this.props - return !data.get('rolesSelected').equals(data.get('originalRolesSelected')) - } + editServerMessage = e => { + const { dispatch } = this.props; + dispatch(Actions.editServerMessage(this.serverId, e.target.value)); + }; - editServerMessage = (e) => { - const { dispatch } = this.props - dispatch(Actions.editServerMessage(this.serverId, e.target.value)) - } - - saveServerMessage = (e) => { - const { dispatch } = this.props - dispatch(Actions.saveServerMessage(this.serverId)) - } + saveServerMessage = e => { + const { dispatch } = this.props; + dispatch(Actions.saveServerMessage(this.serverId)); + }; openMessageEditor = () => { - const { dispatch } = this.props - dispatch(Actions.openMessageEditor(this.serverId)) - } + const { dispatch } = this.props; + dispatch(Actions.openMessageEditor(this.serverId)); + }; closeMessageEditor = () => { - const { dispatch } = this.props - dispatch(Actions.closeMessageEditor) - } + const { dispatch } = this.props; + dispatch(Actions.closeMessageEditor); + }; - renderServerMessage (server) { - const isEditing = this.props.data.get('isEditingMessage') - const roleManager = server.getIn(['perms', 'canManageRoles']) - const msg = server.get('message') - const msgBuffer = this.props.data.get('messageBuffer') + renderServerMessage(server) { + const isEditing = this.props.data.get('isEditingMessage'); + const roleManager = server.getIn(['perms', 'canManageRoles']); + const msg = server.get('message'); + const msgBuffer = this.props.data.get('messageBuffer'); - console.log(msg, roleManager, isEditing, this.props.data.toJS()) + console.log(msg, roleManager, isEditing, this.props.data.toJS()); if (!roleManager && msg !== '') { - return
-

Server Message

-

-
+ return ( +
+

Server Message

+

+
+ ); } if (roleManager && !isEditing) { - return
-
-

Server Message

-
-
-

no server message'}}>

-
+ return ( +
+
+

Server Message

+
+
+

no server message', + }} + >

+
+ ); } if (roleManager && isEditing) { - return
-
-

Server Message

-
-
-
-