diff --git a/Server/services/server.js b/Server/services/server.js index f79db37..d7b3d6f 100644 --- a/Server/services/server.js +++ b/Server/services/server.js @@ -8,7 +8,13 @@ class ServerService extends Service { } async ensure (server) { - const srv = await this.get(server.id) + let srv + try { + srv = await this.get(server.id) + } catch (e) { + + } + if (srv == null) { return this.create({ id: server.id, diff --git a/UI/package.json b/UI/package.json index 3584a3e..a77593c 100644 --- a/UI/package.json +++ b/UI/package.json @@ -10,6 +10,7 @@ "immutable": "^3.8.2", "prop-types": "^15.6.0", "react": "^16.2.0", + "react-custom-scrollbars": "^4.2.1", "react-dom": "^16.2.0", "react-immutable-proptypes": "^2.1.0", "react-redux": "^5.0.6", diff --git a/UI/public/index.html b/UI/public/index.html index 4b88511..562fcbd 100644 --- a/UI/public/index.html +++ b/UI/public/index.html @@ -4,8 +4,8 @@ Roleypoly - - + diff --git a/UI/src/components/role-picker/RolePicker.sass b/UI/src/components/role-picker/RolePicker.sass index b737c68..602fa59 100644 --- a/UI/src/components/role-picker/RolePicker.sass +++ b/UI/src/components/role-picker/RolePicker.sass @@ -11,11 +11,63 @@ flex-wrap: wrap flex-direction: row - &__category // flex: 1 3 33% box-sizing: border-box background-color: var(--c-1) padding: 15px margin: 10px - width: 220px - 30px \ No newline at end of file + width: 220px - 30px + + &__roles-header + display: flex + + &__spacer + flex: 1 + + &__actions + opacity: 1 + transition: opacity 0.3s ease-in-out + + button + margin-left: 5px + + &.hidden + opacity: 0 + // display: none + +.action__button + border: 0 + border-radius: 5px + transition: transform 0.2s ease-out, box-shadow 0.2s ease-out + position: relative + + &::after + content: "" + position: absolute + top: 0 + bottom: 0 + right: 0 + left: 0 + background-color: rgba(0,0,0,0.1) + border-radius: 5px + opacity: 0 + transition: opacity 0.15s ease-in-out + + &:hover + transform: translateY(-1px) + box-shadow: 0 1px 2px rgba(0,0,0,0.3) + &::after + opacity: 0.7 + + &:active + transform: translateY(0px) + box-shadow: none + &::after + opacity: 1 + + &.primary + background-color: var(--c-5) + + &.secondary + background-color: var(--c-3) \ No newline at end of file diff --git a/UI/src/components/role-picker/actions.js b/UI/src/components/role-picker/actions.js index fd3c413..110f544 100644 --- a/UI/src/components/role-picker/actions.js +++ b/UI/src/components/role-picker/actions.js @@ -42,7 +42,11 @@ export const constructView = id => (dispatch, getState) => { hidden: false, type: 'multi' })).map(c => { - const roles = c.get('roles').map(r => server.get('roles').find(sr => sr.get('id') === r)) + const roles = c.get('roles') + .map(r => + server.get('roles').find(sr => sr.get('id') === r) + ) + .sort((a, b) => a.position > b.position) return c.set('roles_map', roles) }) @@ -59,3 +63,30 @@ export const constructView = id => (dispatch, getState) => { } }) } + +export const resetSelected = (dispatch) => { + dispatch({ + type: Symbol.for('reset selected') + }) +} + +export const submitSelected = serverId => async (dispatch, getState) => { + 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)) + } else { + return acc.set('removed', acc.get('removed').add(k)) + } + } + + return acc + }, Map({ added: Set(), removed: Set() })) + + await superagent.patch(`/api/servers/${serverId}/roles`).send(diff.toJS()) +} diff --git a/UI/src/components/role-picker/index.js b/UI/src/components/role-picker/index.js index f8f64ff..e2775a7 100644 --- a/UI/src/components/role-picker/index.js +++ b/UI/src/components/role-picker/index.js @@ -1,10 +1,11 @@ -import React, { Component } from 'react' +import React, { Component, Fragment } from 'react' import { connect } from 'react-redux' import superagent from 'superagent' import * as Actions from './actions' import './RolePicker.sass' import Role from '../role' +import { Scrollbars } from 'react-custom-scrollbars'; const mapState = ({ rolePicker, servers }, ownProps) => { return { @@ -31,15 +32,21 @@ class RolePicker extends Component { return this.props.data.getIn([ 'rolesSelected', id ]) } + get rolesHaveChanged () { + const { data } = this.props + return !data.get('rolesSelected').equals(data.get('originalRolesSelected')) + } + render () { - const { data, server } = this.props + const { data, server, dispatch } = this.props const vm = data.get('viewMap') if (server === undefined) { return null } - return
+ return
+ {/* */} { (server.get('message') !== '') ?

Server Message

@@ -48,7 +55,18 @@ class RolePicker extends Component { : null }
-

Roles

+
+

Roles

+
+
+ + +
+
{ vm.map((c, name) => { @@ -68,6 +86,8 @@ class RolePicker extends Component { }
+ {/* */} +
} } diff --git a/UI/src/components/role/Role.sass b/UI/src/components/role/Role.sass index 2609c88..3f9498b 100644 --- a/UI/src/components/role/Role.sass +++ b/UI/src/components/role/Role.sass @@ -15,7 +15,7 @@ &:hover .role__option - transform: translateY(-1px) + transform: translateY(-1px) translateZ(0px) box-shadow: 0 1px 1px var(--c-dark) border-color: var(--role-color-hover) background-color: transparent @@ -35,11 +35,12 @@ /* display: inline-block */ background-color: transparent overflow: hidden + transform: translateZ(0px) border: 1px solid var(--role-color-hex) - transition: background-color 0.1s ease-in-out, border-left-width 0.3s ease-in-out, border-right-width 0.5s ease-in-out, border-color 0.1s ease-in-out, transform 0.1s ease-in-out, box-shadow 0.1s ease-out + transition: background-color 0.1s ease-in-out, border-left-width 0.3s ease-in-out, border-color 0.1s ease-in-out, transform 0.1s ease-in-out, box-shadow 0.1s ease-out &.selected - background-color: var(--role-color-hex) + // background-color: var(--role-color-hex) // This **must** be width-1, otherwise blink adds width to the boundaries. border-left-width: 21px @@ -57,4 +58,4 @@ user-select: none .role__option:active, .role:active .role__option:not(:active) - transform: translateY(0) !important \ No newline at end of file + transform: translateY(0) translateZ(0px) !important \ No newline at end of file diff --git a/UI/src/components/servers/Navigation.js b/UI/src/components/servers/Navigation.js index c4b9019..962dc4e 100644 --- a/UI/src/components/servers/Navigation.js +++ b/UI/src/components/servers/Navigation.js @@ -3,6 +3,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes' import PropTypes from 'prop-types' import ServerCard from './ServerCard' import UserCard from './UserCard' +import { Scrollbars } from 'react-custom-scrollbars'; class ServersNavigation extends Component { static propTypes = { @@ -16,12 +17,14 @@ class ServersNavigation extends Component { return
- { - this.props.servers.reduce((acc, s, i) => { - acc.push() - return acc - }, []) - } + + { + this.props.servers.reduce((acc, s, i) => { + acc.push() + return acc + }, []) + } +
} diff --git a/UI/src/components/servers/index.js b/UI/src/components/servers/index.js index bde422a..c56bd90 100644 --- a/UI/src/components/servers/index.js +++ b/UI/src/components/servers/index.js @@ -1,5 +1,6 @@ import React, { Component } from 'react' import { Route } from 'react-router-dom' +import { Scrollbars } from 'react-custom-scrollbars' import { connect } from 'react-redux' import './index.sass' @@ -21,10 +22,12 @@ class Servers extends Component { render () { return
-
- - -
+
+ + + + +
} } diff --git a/UI/src/components/servers/index.sass b/UI/src/components/servers/index.sass index 12fe4c8..e8d6dd2 100644 --- a/UI/src/components/servers/index.sass +++ b/UI/src/components/servers/index.sass @@ -10,13 +10,17 @@ &__nav grid-area: listing - overflow-y: scroll - height: $fullH - - + overflow: hidden + // height: $fullH + &__content - grid-area: content background-color: var(--c-3) - padding: 15px - overflow-y: scroll + // padding: 15px + grid-area: content + position: relative + // height: $fullH + overflow: hidden box-sizing: border-box + + .inner + padding: 15px diff --git a/UI/src/reducers/role-picker.js b/UI/src/reducers/role-picker.js index 4f4de60..71a2ab8 100644 --- a/UI/src/reducers/role-picker.js +++ b/UI/src/reducers/role-picker.js @@ -14,20 +14,17 @@ export default (state = initialState, { type, data }) => { return Map(data) case Symbol.for('hide role picker ui'): - return { - ...state, - hidden: data - } + return state.set('hidden', data) case Symbol.for('reset role picker ui'): - return { - ...state, - emptyRoles: data - } + return state.set('emptyRoles', data) case Symbol.for('update selected roles'): return state.setIn(['rolesSelected', data.id], data.state) + case Symbol.for('reset selected'): + return state.set('rolesSelected', state.get('originalRolesSelected')) + // case Symbol.for('zero role picker'): // return initialState diff --git a/UI/src/store.js b/UI/src/store.js deleted file mode 100644 index f453591..0000000 --- a/UI/src/store.js +++ /dev/null @@ -1,50 +0,0 @@ -import { observable, computed } from 'mobx' - -class Store { - @observable servers = [ - { - "id": "203493697696956418", - "gm": { - "nickname": "sexkittenhime", - "color": "#ff5c00" - }, - "server": { - "id": "203493697696956418", - "name": "Genudine Medkit Manufacturing", - "ownerID": "62601275618889728", - "icon": "ff08d36f5aee1ff48f8377b65d031ab0" - }, - "perms": { - "isAdmin": true, - "canManageRoles": true - } - }, - { - "id": "386659935687147521", - "gm": { - "nickname": null, - "color": "#cca1a1" - }, - "server": { - "id": "386659935687147521", - "name": "Roleypoly", - "ownerID": "62601275618889728", - "icon": "4fa0c1063649a739f3fe1a0589aa2c03" - }, - "perms": { - "isAdmin": true, - "canManageRoles": true - } - } - ] - - @observable user = { - username: 'あたし', - discriminator: '0001', - id: '', - avatar: null - } - -} - -export default Store diff --git a/UI/yarn.lock b/UI/yarn.lock index 514b8a0..bded731 100644 --- a/UI/yarn.lock +++ b/UI/yarn.lock @@ -64,6 +64,10 @@ acorn@^5.0.0, acorn@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.2.1.tgz#317ac7821826c22c702d66189ab8359675f135d7" +add-px-to-style@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/add-px-to-style/-/add-px-to-style-1.0.0.tgz#d0c135441fa8014a8137904531096f67f28f263a" + address@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/address/-/address-1.0.2.tgz#480081e82b587ba319459fef512f516fe03d58af" @@ -2304,6 +2308,14 @@ dom-converter@~0.1: dependencies: utila "~0.3" +dom-css@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/dom-css/-/dom-css-2.1.0.tgz#fdbc2d5a015d0a3e1872e11472bbd0e7b9e6a202" + dependencies: + add-px-to-style "1.0.0" + prefix-style "2.0.1" + to-camel-case "1.0.0" + dom-serializer@0: version "0.1.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" @@ -5812,6 +5824,10 @@ postcss@^6.0.1, postcss@^6.0.2, postcss@^6.0.6: source-map "^0.6.1" supports-color "^4.4.0" +prefix-style@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/prefix-style/-/prefix-style-2.0.1.tgz#66bba9a870cfda308a5dc20e85e9120932c95a06" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -5954,6 +5970,12 @@ querystringify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb" +raf@^3.1.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575" + dependencies: + performance-now "^2.1.0" + randomatic@^1.1.3: version "1.1.7" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" @@ -6005,6 +6027,14 @@ react-base16-styling@^0.5.1: lodash.flow "^3.3.0" pure-color "^1.2.0" +react-custom-scrollbars@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/react-custom-scrollbars/-/react-custom-scrollbars-4.2.1.tgz#830fd9502927e97e8a78c2086813899b2a8b66db" + dependencies: + dom-css "^2.0.0" + prop-types "^15.5.10" + raf "^3.1.0" + react-dev-utils@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-3.1.1.tgz#09ae7209a81384248db56547e718e65bd3b20eb5" @@ -7233,6 +7263,12 @@ to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" +to-camel-case@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-camel-case/-/to-camel-case-1.0.0.tgz#1a56054b2f9d696298ce66a60897322b6f423e46" + dependencies: + to-space-case "^1.0.0" + to-descriptor@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/to-descriptor/-/to-descriptor-1.0.1.tgz#a0e678c34ebc7d2dae464d8372bc21479d9c2bcd" @@ -7241,6 +7277,16 @@ to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" +to-no-case@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/to-no-case/-/to-no-case-1.0.2.tgz#c722907164ef6b178132c8e69930212d1b4aa16a" + +to-space-case@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-space-case/-/to-space-case-1.0.0.tgz#b052daafb1b2b29dc770cea0163e5ec0ebc9fc17" + dependencies: + to-no-case "^1.0.0" + toposort@^1.0.0: version "1.0.6" resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.6.tgz#c31748e55d210effc00fdcdc7d6e68d7d7bb9cec"