From f5220aa6dc86e4a487f247a63a9914ace14d8528 Mon Sep 17 00:00:00 2001 From: Kata Date: Mon, 11 Dec 2017 18:06:25 -0600 Subject: [PATCH] sync: full redux retrofit done --- Server/api/servers.js | 8 ++- Server/services/discord.js | 24 +++++--- UI/package.json | 1 - UI/src/actions/index.js | 4 ++ UI/src/components/role-picker/actions.js | 47 +++++++++++++++ UI/src/components/role-picker/index.js | 77 ++++++++++-------------- UI/src/components/servers/Navigation.js | 9 ++- UI/src/components/servers/ServerCard.js | 15 ++--- UI/src/components/servers/UserCard.js | 2 +- UI/src/reducers/index.js | 23 ++++++- UI/src/reducers/role-picker.js | 37 ++++++++++++ UI/src/reducers/servers.js | 43 +++++++------ UI/src/router/index.js | 6 ++ UI/yarn.lock | 32 ---------- 14 files changed, 206 insertions(+), 122 deletions(-) create mode 100644 UI/src/components/role-picker/actions.js create mode 100644 UI/src/reducers/role-picker.js diff --git a/Server/api/servers.js b/Server/api/servers.js index 3f673b5..add8beb 100644 --- a/Server/api/servers.js +++ b/Server/api/servers.js @@ -2,7 +2,9 @@ module.exports = (R, $) => { R.get('/api/servers', async (ctx) => { const { userId } = ctx.session const srv = $.discord.getRelevantServers(userId) - ctx.body = $.discord.presentableServers(srv, userId) + const presentable = $.discord.presentableServers(srv, userId) + + ctx.body = presentable }) R.get('/api/server/:id', async (ctx) => { @@ -18,8 +20,8 @@ module.exports = (R, $) => { } const gm = srv.members.get(userId) - const roles = $.discord.presentableRoles(id, gm) + const server = $.discord.presentableRoles(id, gm) - ctx.body = roles + ctx.body = server }) } diff --git a/Server/services/discord.js b/Server/services/discord.js index 72b556e..ccfa78d 100644 --- a/Server/services/discord.js +++ b/Server/services/discord.js @@ -41,22 +41,26 @@ class DiscordService extends Service { ownerID: server.ownerID, icon: server.icon }, + roles: this.presentableRoles(server.id, gm), + message: 'moe moe kyuuuuuuuuun~', perms: this.getPermissions(gm) } }) } presentableRoles (serverId, gm) { - return this.client.guilds.get(serverId).roles.filter(r => r.id !== serverId).map((role) => { - return { - color: role.hexColor, - position: role.position, - calculatedPosition: role.calculatedPosition, - id: role.id, - name: role.name, - selected: gm.roles.has(role.id) - } - }) + return this.client.guilds + .get(serverId) + .roles + .filter(r => r.id !== serverId) + .map((role) => ({ + color: role.hexColor, + position: role.position, + calculatedPosition: role.calculatedPosition, + id: role.id, + name: role.name, + selected: gm.roles.has(role.id) + })) } getPermissions (gm) { diff --git a/UI/package.json b/UI/package.json index 4eca34f..4102504 100644 --- a/UI/package.json +++ b/UI/package.json @@ -8,7 +8,6 @@ "eslint": "^4.13.0", "immutable": "^3.8.2", "prop-types": "^15.6.0", - "radium": "^0.19.6", "react": "^16.2.0", "react-dom": "^16.2.0", "react-immutable-proptypes": "^2.1.0", diff --git a/UI/src/actions/index.js b/UI/src/actions/index.js index 13e8d5a..1165462 100644 --- a/UI/src/actions/index.js +++ b/UI/src/actions/index.js @@ -7,6 +7,10 @@ export const fetchServers = async dispatch => { type: Symbol.for('update servers'), data: rsp.body }) + + dispatch({ + type: Symbol.for('app ready') + }) } export const userInit = async dispatch => { diff --git a/UI/src/components/role-picker/actions.js b/UI/src/components/role-picker/actions.js new file mode 100644 index 0000000..e53344d --- /dev/null +++ b/UI/src/components/role-picker/actions.js @@ -0,0 +1,47 @@ +import { Map, Set } from 'immutable' +import superagent from 'superagent' + +export const roleUpdate = (id, oldState) => (dispatch, getState) => { + dispatch({ + type: Symbol.for('update selected roles'), + data: { + id, + state: !oldState + } + }) +} + +export const setup = id => async dispatch => { + const rsp = await superagent.get(`/api/server/${id}`) + const data = rsp.body + + dispatch({ + type: Symbol.for('update server roles'), + data: { + id, + roles: data + } + }) + + dispatch(constructView(id)) +} + +export const constructView = id => (dispatch, getState) => { + const server = getState().servers.get(id) + const roles = server.get('roles') + + const categories = roles.groupBy(x => x.get('category')) + const selected = roles.reduce((acc, r) => { + return acc.set(r.id, r.selected) + }, Map()) + + console.log(categories, selected) + dispatch({ + type: Symbol.for('setup role picker'), + data: { + viewMap: categories, + rolesSelected: selected, + originalRolesSelected: selected + } + }) +} diff --git a/UI/src/components/role-picker/index.js b/UI/src/components/role-picker/index.js index 35ad1cb..06570ac 100644 --- a/UI/src/components/role-picker/index.js +++ b/UI/src/components/role-picker/index.js @@ -1,62 +1,47 @@ import React, { Component } from 'react' +import { connect } from 'react-redux' import superagent from 'superagent' +import * as Actions from './actions' import './RolePicker.sass' import Role from '../role' +const mapState = ({ rolePicker, servers }, ownProps) => { + console.log(servers) + return { + data: rolePicker, + server: servers.get(ownProps.match.params.server) + } +} + +@connect(mapState) class RolePicker extends Component { - state = { - roles: [], - categories: {}, - hidden: true, - serverMessage: `Hey there. This is a cool UI you can pick your roles from. If you have any questions, ask the mods on Discord!` - } - - async componentDidUpdate (prevProps) { - if (prevProps.match.params.server !== this.props.match.params.server) { - this.setState({ hidden: true }) - setTimeout(async () => { - this.setState({ roles: [] }) - this.setState({ roles: await this.getRoles(this.props.match.params.server), hidden: false }) - }, 350) - } - } - - async componentWillMount () { - this.setState({ roles: await this.getRoles(this.props.match.params.server), hidden: false }) - } - - async getRoles (id) { - const rsp = await superagent.get(`/api/server/${id}`) - return rsp.body//.map(r => { r.selected = false; return r }) - } - - onChange = k => (newVal, oldVal) => { - this.setState((prevState) => { - return { roles: prevState.roles.map(r => { - if (r.id === k) { - r.selected = newVal - } - - return r - })} - }) + componentWillMount () { + const { dispatch, match: { params: { server } } } = this.props + dispatch(Actions.setup(server)) } render () { - return
-
-

Server Message

-

{this.state.serverMessage}

-
+ console.log(this.props) + if (this.props.server === undefined) { + return null + } + + return
+ { (this.props.server.get('message') !== '') + ?
+

Server Message

+

{this.props.server.get('message')}

+
+ : null + }

Roles

- { - this.state.roles.map((r, k) => { - - return + {/* { + this.props.data.roles.map((r, k) => { + return }) - } + } */}
} diff --git a/UI/src/components/servers/Navigation.js b/UI/src/components/servers/Navigation.js index ec66743..38e1de4 100644 --- a/UI/src/components/servers/Navigation.js +++ b/UI/src/components/servers/Navigation.js @@ -8,7 +8,7 @@ class ServersNavigation extends Component { static propTypes = { user: ImmutablePropTypes.map.isRequired, - servers: ImmutablePropTypes.setOf(ImmutablePropTypes.map).isRequired, + servers: ImmutablePropTypes.setOf(ImmutablePropTypes.orderedMap).isRequired, className: PropTypes.string } @@ -17,7 +17,12 @@ class ServersNavigation extends Component { return
- { this.props.servers.map((s, i) => ) } + { + this.props.servers.reduce((acc, s, i) => { + acc.push() + return acc + }, []) + }
} diff --git a/UI/src/components/servers/ServerCard.js b/UI/src/components/servers/ServerCard.js index d3f0922..d2740f9 100644 --- a/UI/src/components/servers/ServerCard.js +++ b/UI/src/components/servers/ServerCard.js @@ -15,28 +15,29 @@ class ServerCard extends Component { let icon = '' + console.log(__filename, server) const s = server.get('server') const gm = server.get('gm') const perms = server.get('perms') - if (perms.canManageRoles) { + if (perms.get('canManageRoles')) { icon = 🔰 } - if (perms.isAdmin) { + if (perms.get('isAdmin')) { icon = 🔰⭐️ } - return + return
- {s.name} + {s.name}
- {s.name}
- { gm.nickname || user.get('username') } { icon } + {s.get('name')}
+ { gm.get('nickname') || user.get('username') } { icon }
} } -export default Radium(ServerCard) +export default ServerCard diff --git a/UI/src/components/servers/UserCard.js b/UI/src/components/servers/UserCard.js index 20b8937..d9e66c2 100644 --- a/UI/src/components/servers/UserCard.js +++ b/UI/src/components/servers/UserCard.js @@ -16,7 +16,7 @@ class UserCard extends Component { const avatar = user.get('avatar') if (avatar === '' || avatar == null) { - return `https://cdn.discordapp.com/embed/avatars/${Math.ceil(Math.random() * 9999) % 4}.png` + return `https://cdn.discordapp.com/embed/avatars/${Math.ceil(Math.random() * 9999) % 5}.png` } return `https://cdn.discordapp.com/avatars/${user.get('id')}/${avatar}.png` diff --git a/UI/src/reducers/index.js b/UI/src/reducers/index.js index 706ad5f..e09136d 100644 --- a/UI/src/reducers/index.js +++ b/UI/src/reducers/index.js @@ -2,10 +2,31 @@ import { combineReducers } from 'redux' import servers from './servers' import user from './user' +import rolePicker from './role-picker' +// import roles from './roles' + +const initialState = { + ready: false +} + +const appState = (state = initialState, { type }) => { + switch (type) { + case Symbol.for('app ready'): + return { + ready: true + } + + default: + return state + } +} const rootReducer = combineReducers({ + appState, servers, - user + user, + // roles, + rolePicker }) export default rootReducer diff --git a/UI/src/reducers/role-picker.js b/UI/src/reducers/role-picker.js new file mode 100644 index 0000000..73643ce --- /dev/null +++ b/UI/src/reducers/role-picker.js @@ -0,0 +1,37 @@ +import { Map, Set } from 'immutable' + +const initialState = Map({ + hidden: true, // should the view be hidden? + emptyRoles: true, // helps derender roles so there's no visible element state change + viewMap: Set([]), // roles in categories + originalRolesSelected: Map({}), // Map -- original roles for diffing against selected + rolesSelected: Map({}) // Map -- new roles for diffing +}) + +export default (state = initialState, { type, data }) => { + switch (type) { + case Symbol.for('setup role picker'): + return state.merge(data) + + case Symbol.for('hide role picker ui'): + return { + ...state, + hidden: data + } + + case Symbol.for('reset role picker ui'): + return { + ...state, + emptyRoles: data + } + + case Symbol.for('zero role picker'): + return initialState + + case Symbol.for('update selected roles'): + return state.set('rolesSelected', state.get('rolesSelected').set(data.id, data.state)) + + default: + return state + } +} diff --git a/UI/src/reducers/servers.js b/UI/src/reducers/servers.js index c3b35a4..84de745 100644 --- a/UI/src/reducers/servers.js +++ b/UI/src/reducers/servers.js @@ -1,34 +1,39 @@ -import { Set, Map } from 'immutable' +import { Set, OrderedMap, Map, fromJS } from 'immutable' const blankServer = Map({ - 'id': '386659935687147521', - 'gm': { - 'nickname': null, - 'color': '#cca1a1' + id: '386659935687147521', + gm: { + nickname: null, + color: '#cca1a1' }, - 'server': { - 'id': '386659935687147521', - 'name': 'Roleypoly', - 'ownerID': '62601275618889728', - 'icon': '4fa0c1063649a739f3fe1a0589aa2c03' + message: 'Hey hey!', + server: { + id: '386659935687147521', + name: 'Roleypoly', + ownerID: '62601275618889728', + icon: '4fa0c1063649a739f3fe1a0589aa2c03' }, - 'perms': { - 'isAdmin': true, - 'canManageRoles': true + roles: Set([]), + perms: { + isAdmin: true, + canManageRoles: true } }) -const initialState = Set([]) +const initialState = OrderedMap({}) export default (state = initialState, { type, data }) => { - console.log(__filename, type, data) - switch (type) { case Symbol.for('update servers'): - return data.reduce((acc, s) => acc.add(Map(s)), Set()) - + return data.reduce((acc, s) => acc.set(s.id, fromJS(s)), OrderedMap()) + + // case Symbol.for('update server roles'): + // return state.set(data.id, + // state.get(data.id).set('roles', Set(data.roles)) + // ) + case Symbol.for('add debug server'): - return Set([blankServer]) + return state.set('0', blankServer) default: return state diff --git a/UI/src/router/index.js b/UI/src/router/index.js index 0a71896..7850611 100644 --- a/UI/src/router/index.js +++ b/UI/src/router/index.js @@ -1,5 +1,6 @@ import React, { Component, Fragment } from 'react' import { Route } from 'react-router-dom' +import { connect } from 'react-redux' import Servers from '../components/servers' import OauthCallback from '../components/oauth-callback' @@ -7,8 +8,13 @@ import OauthFlow from '../components/oauth-flow' const aaa = (props) => (
{ JSON.stringify(props) }
) +@connect(({ appState }) => ({ ready: appState.ready })) export default class AppRouter extends Component { render () { + if (!this.props.ready) { + return null + } + return diff --git a/UI/yarn.lock b/UI/yarn.lock index 894da22..80add3c 100644 --- a/UI/yarn.lock +++ b/UI/yarn.lock @@ -214,10 +214,6 @@ array-find-index@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" -array-find@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-find/-/array-find-1.0.0.tgz#6c8e286d11ed768327f8e62ecee87353ca3e78b8" - array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -1298,10 +1294,6 @@ boom@5.x.x: dependencies: hoek "4.x.x" -bowser@^1.0.0: - version "1.8.1" - resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.8.1.tgz#49785777e7302febadb1a5b71d9a646520ed310d" - boxen@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-0.6.0.tgz#8364d4248ac34ff0ef1b2f2bf49a6c60ce0d81b6" @@ -2884,10 +2876,6 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -exenv@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" - expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" @@ -3704,10 +3692,6 @@ https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" -hyphenate-style-name@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b" - iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@~0.4.13: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" @@ -3779,13 +3763,6 @@ ini@^1.3.4, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" -inline-style-prefixer@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-2.0.5.tgz#c153c7e88fd84fef5c602e95a8168b2770671fe7" - dependencies: - bowser "^1.0.0" - hyphenate-style-name "^1.0.1" - inquirer@3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.2.1.tgz#06ceb0f540f45ca548c17d6840959878265fa175" @@ -5977,15 +5954,6 @@ querystringify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb" -radium@^0.19.6: - version "0.19.6" - resolved "https://registry.yarnpkg.com/radium/-/radium-0.19.6.tgz#b86721d08dbd303b061a4ae2ebb06cc6e335ae72" - dependencies: - array-find "^1.0.0" - exenv "^1.2.1" - inline-style-prefixer "^2.0.5" - prop-types "^15.5.8" - randomatic@^1.1.3: version "1.1.7" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c"