From 7806219464aea252f10867da3883414cc17f9cd1 Mon Sep 17 00:00:00 2001 From: Katalina / stardust Date: Wed, 27 Dec 2017 13:16:26 -0600 Subject: [PATCH] finish drag and drop system --- UI/package.json | 6 +- UI/src/App.js | 7 +- UI/src/components/role-editor/Category.js | 30 +++++- .../components/role-editor/CategoryEditor.js | 41 ++++++++ UI/src/components/role-editor/RoleEditor.sass | 44 ++++++++- UI/src/components/role-editor/actions.js | 88 +++++++++++++++++ UI/src/components/role-editor/index.js | 99 ++++++++++++++++--- UI/src/components/role-picker/Category.js | 4 + UI/src/components/role-picker/RolePicker.sass | 38 +------ UI/src/components/role-picker/actions.js | 19 +++- UI/src/components/role-picker/index.js | 4 +- UI/src/components/role/Role.sass | 27 ++++- UI/src/components/role/draggable.js | 19 ++++ UI/src/components/role/index.js | 14 ++- UI/src/generic.sass | 37 +++++++ UI/src/reducers/index.js | 5 +- UI/src/reducers/role-editor.js | 43 ++++++++ UI/src/router/index.js | 2 +- UI/yarn.lock | 28 +++--- 19 files changed, 465 insertions(+), 90 deletions(-) create mode 100644 UI/src/components/role-editor/CategoryEditor.js create mode 100644 UI/src/components/role/draggable.js create mode 100644 UI/src/generic.sass create mode 100644 UI/src/reducers/role-editor.js diff --git a/UI/package.json b/UI/package.json index 9443e7d..80412cc 100644 --- a/UI/package.json +++ b/UI/package.json @@ -5,7 +5,7 @@ "dependencies": { "color": "^2.0.1", "custom-react-scripts": "0.2.1", - "eslint": "^4.13.0", + "eslint": "^4.14.0", "history": "^4.7.2", "immutable": "^3.8.2", "prop-types": "^15.6.0", @@ -22,7 +22,7 @@ "react-transition-group": "^2.2.1", "redux": "^3.7.2", "redux-devtools": "^3.4.1", - "redux-devtools-dock-monitor": "^1.1.2", + "redux-devtools-dock-monitor": "^1.1.3", "redux-devtools-log-monitor": "^1.4.0", "redux-logger": "^3.0.6", "redux-saga": "^0.16.0", @@ -37,7 +37,7 @@ }, "proxy": "http://localhost:6769", "devDependencies": { - "eslint-config-standard": "^10.2.1", + "eslint-config-standard": "^11.0.0-beta.0", "eslint-plugin-import": "^2.8.0", "eslint-plugin-node": "^5.2.1", "eslint-plugin-promise": "^3.6.0", diff --git a/UI/src/App.js b/UI/src/App.js index 369f231..f3d83ec 100644 --- a/UI/src/App.js +++ b/UI/src/App.js @@ -1,10 +1,12 @@ import React, { Component } from 'react' -import { BrowserRouter } from 'react-router-dom' import { Provider } from 'react-redux' -import createHistory from 'history/createBrowserHistory' 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' @@ -15,6 +17,7 @@ const store = configureStore(undefined, history) window.__APP_STORE__ = store +@DragDropContext(HTML5Backend) class App extends Component { componentWillMount () { store.dispatch(userInit) diff --git a/UI/src/components/role-editor/Category.js b/UI/src/components/role-editor/Category.js index 592a565..03cbbe4 100644 --- a/UI/src/components/role-editor/Category.js +++ b/UI/src/components/role-editor/Category.js @@ -1,21 +1,41 @@ import React, { Component } from 'react' +import { DropTarget } from 'react-dnd' -import Role from '../role' +import Role from '../role/draggable' +import CategoryEditor from './CategoryEditor' +@DropTarget(Symbol.for('dnd: role'), { + drop (props, monitor, element) { + props.onDrop(monitor.getItem()) + }, + canDrop (props) { + return props.mode !== Symbol.for('edit') + } +}, (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 } = this.props + const { category, name, isOver, connectDropTarget, mode, ...rest } = this.props - return
+ if (mode === Symbol.for('edit')) { + return + } + + return connectDropTarget(

{ name }

{ category.get('roles_map') .sortBy(r => r.get('position')) .reverse() - .map((r, k) => ) + .map((r, k) => ) .toArray() } -
+
) } } export default Category diff --git a/UI/src/components/role-editor/CategoryEditor.js b/UI/src/components/role-editor/CategoryEditor.js new file mode 100644 index 0000000..ba58882 --- /dev/null +++ b/UI/src/components/role-editor/CategoryEditor.js @@ -0,0 +1,41 @@ +import React, { Component } from 'react' + +export default class CategoryEditor extends Component { + render () { + const { + name, + category + } = this.props + + return
+
e.preventDefault()} className="uk-form-stacked uk-light"> +
+ +
+ +
+
+
+
+ +
+
+
+ + +
+ +
+ } +} diff --git a/UI/src/components/role-editor/RoleEditor.sass b/UI/src/components/role-editor/RoleEditor.sass index 5922999..0b577c8 100644 --- a/UI/src/components/role-editor/RoleEditor.sass +++ b/UI/src/components/role-editor/RoleEditor.sass @@ -2,5 +2,45 @@ &__grid display: grid grid-template-areas: 'left right' - grid-template-columns: 1fr - grid-template-rows: 1fr 1fr \ No newline at end of file + grid-template-columns: 1fr 1fr + grid-template-rows: 1fr + + &__actions + display: flex + margin-top: 10px + + button + padding: 0 + + &_delete + flex: 1 + margin-right: 5px + + &_save + flex: 4 + + .role-editor__category + box-sizing: border-box + background-color: var(--c-1) + padding: 15px + margin: 10px + min-width: 220px - 30px + + &.add-button + height: 100px + display: flex + align-items: center + justify-content: center + text-align: center + color: var(--c-5) + font-size: 2em + + i + transition: transform 0.15s ease-in-out, color 0.15s ease-in-out + + &:hover + i + transform: scale(1.1) + color: var(--c-7) + + \ No newline at end of file diff --git a/UI/src/components/role-editor/actions.js b/UI/src/components/role-editor/actions.js index e69de29..26106fd 100644 --- a/UI/src/components/role-editor/actions.js +++ b/UI/src/components/role-editor/actions.js @@ -0,0 +1,88 @@ +import { Set } from 'immutable' +import * as UIActions from '../../actions/ui' +import { getViewMap } from '../role-picker/actions' + +export const constructView = id => (dispatch, getState) => { + const server = getState().servers.get(id) + + let { viewMap } = getViewMap(server) + viewMap = viewMap.map(c => c.set('mode', Symbol.for('drop'))) + + dispatch({ + type: Symbol.for('re: setup'), + data: { + viewMap: viewMap + } + }) + + dispatch(UIActions.fadeIn) +} + +export const addRoleToCategory = (name, oldName, role, flip = true) => (dispatch) => { + dispatch({ + type: Symbol.for('re: add role to category'), + data: { + name, + role + } + }) + + if (flip) { + dispatch(removeRoleFromCategory(oldName, name, role, false)) + } +} + +export const removeRoleFromCategory = (name, oldName, role, flip = true) => (dispatch) => { + dispatch({ + type: Symbol.for('re: remove role from category'), + data: { + name, + role + } + }) + + if (flip) { + dispatch(addRoleToCategory(oldName, name, role, false)) + } +} + + +export const editCategory = (stuff) => dispatch => { + +} + +export const saveCategory = (name) => ({ + type: Symbol.for('re: switch category mode'), + data: { + name, + mode: Symbol.for('drop') + } +}) + +export const deleteCategory = (name) => ({ + type: Symbol.for('re: delete category'), + data: name +}) + +export const createCategory = (dispatch, getState) => { + const { roleEditor } = getState() + const vm = roleEditor.get('viewMap') + + let name = 'New Category' + let idx = 1 + while (vm.has(name)) { + idx++ + name = `New Category ${idx}` + } + + dispatch({ + type: Symbol.for('re: set category'), + data: { + name, + roles: Set([]), + roles_map: Set([]), + hidden: true, + mode: Symbol.for('edit') + } + }) +} diff --git a/UI/src/components/role-editor/index.js b/UI/src/components/role-editor/index.js index 3bb1f1d..3f98c2f 100644 --- a/UI/src/components/role-editor/index.js +++ b/UI/src/components/role-editor/index.js @@ -1,13 +1,15 @@ import React, { Component } from 'react' import { Set } from 'immutable' import { connect } from 'react-redux' +import { DropTarget } from 'react-dnd' 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 Role from '../role' +import CategoryEditor from './CategoryEditor' +import Role from '../role/draggable' import { Scrollbars } from 'react-custom-scrollbars'; const mapState = ({ rolePicker, roleEditor, servers }, ownProps) => ({ @@ -17,43 +19,110 @@ const mapState = ({ rolePicker, roleEditor, servers }, ownProps) => ({ }) @connect(mapState) +@DropTarget(Symbol.for('dnd: role'), { + drop (props, monitor, element) { + element.dropRole({}, 'Uncategorized')(monitor.getItem()) + } +}, (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(PickerActions.setup(server)) + dispatch(Actions.constructView(server)) } componentWillReceiveProps (nextProps) { if (this.props.match.params.server !== nextProps.match.params.server) { const { dispatch } = this.props - dispatch(UIActions.fadeOut(() => dispatch(PickerActions.setup(nextProps.match.params.server)))) + 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)) + } + + createCategory = () => { + const { dispatch } = this.props + dispatch(Actions.createCategory) + } + + saveCategory = (category, name) => () => { + const { dispatch } = this.props + dispatch(Actions.saveCategory(name)) + } + + deleteCategory = (category, name) => () => { + const { dispatch } = this.props + dispatch(Actions.deleteCategory(name)) + } + + editCategory = (category, name) => (key, type) => event => { + const { dispatch } = this.props + let value + + switch (type) { + case Symbol.for('edit: text'): + value = event.target.value + break + + case Symbol.for('edit: bool'): + value = event.target.checked + break + + default: + value = null + } + + dispatch(Actions.editCategory({ category, name, key, type, value })) + } + render () { - const vm = this.props.rp.get('viewMap') - console.log(vm.toJS()) + const vm = this.props.editor.get('viewMap') return
{ vm - .filter((_, k) => k !== 'Unassigned') - .map((c, name) => ) - .toArray() + .filter((_, k) => k !== 'Uncategorized') + .map((c, name) => ) + .toArray() } +
+ +
-
{ - (vm.getIn(['Uncategorized', 'roles_map']) || Set()) - .sortBy(r => r.get('position')) - .reverse() - .map((r, k) => ) - .toArray() + this.props.connectDropTarget( +
+ { + (vm.getIn(['Uncategorized', 'roles_map']) || Set()) + .sortBy(r => r.get('position')) + .reverse() + .map((r, k) => ) + .toArray() + } +
) } -
} diff --git a/UI/src/components/role-picker/Category.js b/UI/src/components/role-picker/Category.js index bd60b1a..4d04969 100644 --- a/UI/src/components/role-picker/Category.js +++ b/UI/src/components/role-picker/Category.js @@ -29,6 +29,10 @@ class Category extends Component { return null } + if (category.get('roles').count() === 0) { + return null + } + return

{ name }

{ diff --git a/UI/src/components/role-picker/RolePicker.sass b/UI/src/components/role-picker/RolePicker.sass index 578e295..873e93e 100644 --- a/UI/src/components/role-picker/RolePicker.sass +++ b/UI/src/components/role-picker/RolePicker.sass @@ -49,40 +49,4 @@ &.hidden opacity: 0 - // display: none - -.action__button - border: 0 - border-radius: 2px - 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: 2px - 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 + // display: none \ 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 3e92ba6..85ea257 100644 --- a/UI/src/components/role-picker/actions.js +++ b/UI/src/components/role-picker/actions.js @@ -16,8 +16,7 @@ export const setup = id => async dispatch => { dispatch(constructView(id)) } -export const constructView = id => (dispatch, getState) => { - const server = getState().servers.get(id) +export const getViewMap = server => { const roles = server.get('roles') const categories = server.get('categories') @@ -28,7 +27,7 @@ export const constructView = id => (dispatch, getState) => { // console.log('roles', allRoles.toJS(), accountedRoles.toJS(), unaccountedRoles.toJS()) - const vm = categories.set('Uncategorized', fromJS({ + const viewMap = categories.set('Uncategorized', fromJS({ roles: unaccountedRoles, hidden: false, type: 'multi' @@ -43,11 +42,21 @@ export const constructView = id => (dispatch, getState) => { const selected = roles.reduce((acc, r) => acc.set(r.get('id'), r.get('selected')), Map()) - console.log(categories, selected) + return { + viewMap, + selected + } +} + +export const constructView = id => (dispatch, getState) => { + const server = getState().servers.get(id) + + const { viewMap, selected } = getViewMap(server) + dispatch({ type: Symbol.for('setup role picker'), data: { - viewMap: vm, + viewMap: viewMap, rolesSelected: selected, originalRolesSelected: selected, hidden: false diff --git a/UI/src/components/role-picker/index.js b/UI/src/components/role-picker/index.js index ff2e430..e2b556d 100644 --- a/UI/src/components/role-picker/index.js +++ b/UI/src/components/role-picker/index.js @@ -77,10 +77,10 @@ class RolePicker extends Component {

Roles

- -
diff --git a/UI/src/components/role/Role.sass b/UI/src/components/role/Role.sass index 5c29529..46db09d 100644 --- a/UI/src/components/role/Role.sass +++ b/UI/src/components/role/Role.sass @@ -3,7 +3,6 @@ border-radius: 32px box-sizing: border-box height: 32px - margin: 0 6px 6px 0 padding: 4px display: inline-flex font-weight: 600 @@ -13,8 +12,11 @@ vertical-align: baseline transition: background-color 0.15s ease-in-out, transform 0.15s ease-in-out, box-shadow 0.15s ease-in-out transform: translateZ(0) + margin: 0 6px 6px 0 + position: relative &.role__button + .role__option &:hover cursor: inherit @@ -67,13 +69,34 @@ &.role__drag box-shadow: none - &:hover + &:hover, &.is-dragging transform: translateZ(0) translateY(-1px) box-shadow: 0 1px 2px rgba(0,0,0,0.3) background-color: rgba(#ccc,0.03) cursor: grab &:active cursor: grabbing + + &::after + position: absolute + top: -1px + bottom: -1px + left: -1px + right: -1px + border-radius: 32px + background-color: var(--c-3) + border: 2px dashed var(--c-7) + content: "" + opacity: 0 + transition: opacity 0.15s ease-in-out + box-sizing: border-box + + &.is-dragging + transition: border-color 0s ease-out 0.15s + border-color: transparent + &::after + opacity: 1 + .role__option:active, .role:active .role__option:not(:active) transform: translateY(0) translateZ(0px) !important \ No newline at end of file diff --git a/UI/src/components/role/draggable.js b/UI/src/components/role/draggable.js new file mode 100644 index 0000000..d08b418 --- /dev/null +++ b/UI/src/components/role/draggable.js @@ -0,0 +1,19 @@ +import React, { Component } from 'react' +import { DragSource } from 'react-dnd' + +import Role from './index' + +@DragSource(Symbol.for('dnd: role'), { + beginDrag ({ role, categoryId }) { + return { role, category: categoryId } + } +}, +(connect, monitor) => ({ + connectDragSource: connect.dragSource(), + isDragging: monitor.isDragging() +})) +export default class DraggableRole extends Component { + render () { + return + } +} diff --git a/UI/src/components/role/index.js b/UI/src/components/role/index.js index a08055e..f27feaa 100644 --- a/UI/src/components/role/index.js +++ b/UI/src/components/role/index.js @@ -15,9 +15,11 @@ class Role extends Component { } render () { - let { role, selected, disabled, type, provided } = this.props + let { role, selected, disabled, type, isDragging } = this.props type = type || 'button' + // console.log(this.props) + let color = Color(role.get('color')) if (color.rgbNumber() === 0) { @@ -27,14 +29,14 @@ class Role extends Component { const c = color let hc = color.lighten(0.1) - return
{ if (!disabled && this.props.onToggle != null) { this.props.onToggle(!selected, selected) } } } {...((disabled) ? { 'uk-tooltip': '', title: "I don't have permissions to grant this." } : {})} - className={`role font-sans-serif ${(disabled) ? 'disabled' : ''} role__${type}`} + className={`role font-sans-serif ${(disabled) ? 'disabled' : ''} ${(isDragging) ? 'is-dragging' : ''} role__${type}`} style={{ '--role-color-hex': c.string(), '--role-color-hover': hc.string(), @@ -45,6 +47,12 @@ class Role extends Component { {role.get('name')}
+ + if (type === 'drag' && this.props.connectDragSource != null) { + return this.props.connectDragSource(out) + } + + return out } } diff --git a/UI/src/generic.sass b/UI/src/generic.sass new file mode 100644 index 0000000..0c9528e --- /dev/null +++ b/UI/src/generic.sass @@ -0,0 +1,37 @@ +.rp-button + border: 0 + border-radius: 2px + 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: 2px + 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) + color: var(--c-9) + + &.secondary + background-color: var(--c-3) + color: var(--c-7) \ No newline at end of file diff --git a/UI/src/reducers/index.js b/UI/src/reducers/index.js index 7056466..083e5ef 100644 --- a/UI/src/reducers/index.js +++ b/UI/src/reducers/index.js @@ -3,6 +3,7 @@ import { combineReducers } from 'redux' import servers from './servers' import user from './user' import rolePicker from './role-picker' +import roleEditor from './role-editor' import { routerMiddleware } from 'react-router-redux' // import roles from './roles' @@ -15,6 +16,7 @@ const appState = (state = initialState, { type, data }) => { switch (type) { case Symbol.for('app ready'): return { + ...state, ready: true, fade: false } @@ -36,7 +38,8 @@ const rootReducer = combineReducers({ user, router: routerMiddleware, // roles, - rolePicker + rolePicker, + roleEditor }) export default rootReducer diff --git a/UI/src/reducers/role-editor.js b/UI/src/reducers/role-editor.js new file mode 100644 index 0000000..74425be --- /dev/null +++ b/UI/src/reducers/role-editor.js @@ -0,0 +1,43 @@ +import { Map, OrderedMap, fromJS } from 'immutable' + +const initialState = Map({ + viewMap: OrderedMap({}) +}) + +const reducer = (state = initialState, { type, data }) => { + switch (type) { + case Symbol.for('re: setup'): + const { viewMap, ...rest } = data + return Map({ viewMap: OrderedMap(viewMap), ...rest }) + + case Symbol.for('re: set category'): + return state.setIn(['viewMap', data.name], Map(data)) + + case Symbol.for('re: delete category'): + return state.deleteIn(['viewMap', data]) + + case Symbol.for('re: switch category mode'): + return state.setIn(['viewMap', data.name, 'mode'], data.mode) + + case Symbol.for('re: add role to category'): + const category = state.getIn(['viewMap', data.name]) + return state.setIn(['viewMap', data.name], + category + .set('roles', category.get('roles').add(data.role.get('id'))) + .set('roles_map', category.get('roles_map').add(data.role)) + ) + + case Symbol.for('re: remove role from category'): + const rmCat = state.getIn(['viewMap', data.name]) + return state.setIn(['viewMap', data.name], + rmCat + .set('roles', rmCat.get('roles').filterNot(r => r === data.role.get('id'))) + .set('roles_map', rmCat.get('roles_map').filterNot(r => r.get('id') === data.role.get('id'))) + ) + + default: + return state + } +} + +export default reducer diff --git a/UI/src/router/index.js b/UI/src/router/index.js index 1e7fd55..5aa7596 100644 --- a/UI/src/router/index.js +++ b/UI/src/router/index.js @@ -1,11 +1,11 @@ import React, { Component, Fragment } from 'react' import { Route } from 'react-router-dom' import { connect } from 'react-redux' +import { withRouter } from 'react-router' import Servers from '../components/servers' import OauthCallback from '../components/oauth-callback' import OauthFlow from '../components/oauth-flow' -import { withRouter } from 'react-router'; const aaa = (props) => (
{ JSON.stringify(props) }
) diff --git a/UI/yarn.lock b/UI/yarn.lock index d9d8c82..78dd2a2 100644 --- a/UI/yarn.lock +++ b/UI/yarn.lock @@ -2140,7 +2140,7 @@ date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" -debug@*, debug@^3.0.1, debug@^3.1.0: +debug@*, debug@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: @@ -2623,9 +2623,9 @@ eslint-config-react-app@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-2.0.1.tgz#fd0503da01ae608f0c6ae8861de084975142230e" -eslint-config-standard@^10.2.1: - version "10.2.1" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591" +eslint-config-standard@^11.0.0-beta.0: + version "11.0.0-beta.0" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-11.0.0-beta.0.tgz#f8afe69803d95c685a4b8392b8793188eb03cbb3" eslint-import-resolver-node@^0.3.1: version "0.3.1" @@ -2740,6 +2740,10 @@ eslint-scope@^3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-visitor-keys@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" + eslint@4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.4.1.tgz#99cd7eafcffca2ff99a5c8f5f2a474d6364b4bd3" @@ -2781,21 +2785,21 @@ eslint@4.4.1: table "^4.0.1" text-table "~0.2.0" -eslint@^4.13.0: - version "4.13.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.13.0.tgz#1991aa359586af83877bde59de9d41f53e20826d" +eslint@^4.14.0: + version "4.14.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.14.0.tgz#96609768d1dd23304faba2d94b7fefe5a5447a82" dependencies: ajv "^5.3.0" babel-code-frame "^6.22.0" chalk "^2.1.0" concat-stream "^1.6.0" cross-spawn "^5.1.0" - debug "^3.0.1" + debug "^3.1.0" doctrine "^2.0.2" eslint-scope "^3.7.1" + eslint-visitor-keys "^1.0.0" espree "^3.5.2" esquery "^1.0.0" - estraverse "^4.2.0" esutils "^2.0.2" file-entry-cache "^2.0.0" functional-red-black-tree "^1.0.1" @@ -6300,9 +6304,9 @@ reduce-function-call@^1.0.1: dependencies: balanced-match "^0.4.2" -redux-devtools-dock-monitor@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/redux-devtools-dock-monitor/-/redux-devtools-dock-monitor-1.1.2.tgz#eb213a021f8c25b892f6c98bdb87368615e3d201" +redux-devtools-dock-monitor@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/redux-devtools-dock-monitor/-/redux-devtools-dock-monitor-1.1.3.tgz#1205e823c82536570aac8551a1c4b70972cba6aa" dependencies: babel-runtime "^6.2.0" parse-key "^0.2.1"