diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2020-06-06 16:30:51 +0200 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2020-06-06 16:30:51 +0200 |
| commit | 434e53dea597f61ad59e14012f528ceac58ead85 (patch) | |
| tree | f4dc6bae69f4c46dad9cfce1f74684cccfc26388 | |
| parent | a42008b2d8c051ec2110d866c2da288a66a1d989 (diff) | |
tile list. drag items to sort them
| -rw-r--r-- | cli/app/controllers/crud_controller.py | 2 | ||||
| -rw-r--r-- | cli/app/controllers/page_controller.py | 19 | ||||
| -rw-r--r-- | cli/app/sql/models/page.py | 2 | ||||
| -rw-r--r-- | cli/app/sql/models/tile.py | 2 | ||||
| -rw-r--r-- | cli/app/sql/versions/202006041801_add_sort_order_to_tiles.py | 29 | ||||
| -rw-r--r-- | frontend/store.js | 2 | ||||
| -rw-r--r-- | frontend/types.js | 2 | ||||
| -rw-r--r-- | frontend/views/graph/graph.css | 7 | ||||
| -rw-r--r-- | frontend/views/page/components/page.header.js | 1 | ||||
| -rw-r--r-- | frontend/views/page/components/tile.form.js | 8 | ||||
| -rw-r--r-- | frontend/views/page/components/tile.list.js | 73 | ||||
| -rw-r--r-- | frontend/views/page/components/tile.new.js | 1 | ||||
| -rw-r--r-- | frontend/views/page/page.actions.js | 24 | ||||
| -rw-r--r-- | frontend/views/page/page.container.js | 2 | ||||
| -rw-r--r-- | frontend/views/page/page.css | 29 | ||||
| -rw-r--r-- | frontend/views/page/page.reducer.js | 46 | ||||
| -rw-r--r-- | package-lock.json | 347 | ||||
| -rw-r--r-- | package.json | 4 |
18 files changed, 359 insertions, 241 deletions
diff --git a/cli/app/controllers/crud_controller.py b/cli/app/controllers/crud_controller.py index 7692d26..c1bde8d 100644 --- a/cli/app/controllers/crud_controller.py +++ b/cli/app/controllers/crud_controller.py @@ -108,7 +108,7 @@ class CrudView(FlaskView): if item: raw_form = MultiDict(request.json) if request.json is not None else request.form form = self.form(raw_form, obj=item) - print(item.toJSON()) + # print(item.toJSON()) if form.validate(): form.populate_obj(item) self.on_update(session, raw_form, item) diff --git a/cli/app/controllers/page_controller.py b/cli/app/controllers/page_controller.py index b6bfaa8..3da2068 100644 --- a/cli/app/controllers/page_controller.py +++ b/cli/app/controllers/page_controller.py @@ -28,6 +28,25 @@ class PageView(CrudView): def on_destroy(self, session, item): session.query(Tile).filter(Tile.page_id == item.id).delete(synchronize_session=False) + @route('/sort/<int:page_id>', methods=['POST']) + def set_sort_order(self, page_id): + page = session.query(Page).get(page_id) + if not page: + session.close() + return jsonify({ + 'status': 'error', + 'error': 'page not found' + }) + + print(request.json) + + result = { + 'status': 'ok', + # 'res': page.toFullJSON() if hasattr(page, 'toFullJSON') else page.toJSON(), + } + session.close() + return jsonify(result) + @route('/name/<graph_path>/<page_path>', methods=['GET']) def get_name(self, graph_path: str, page_path: str): """ diff --git a/cli/app/sql/models/page.py b/cli/app/sql/models/page.py index 2e6bbad..960ffd7 100644 --- a/cli/app/sql/models/page.py +++ b/cli/app/sql/models/page.py @@ -22,7 +22,7 @@ class Page(Base): created_at = Column(UtcDateTime(), default=utcnow()) updated_at = Column(UtcDateTime(), onupdate=utcnow()) - tiles = relationship("Tile", foreign_keys="Tile.page_id", lazy='dynamic') + tiles = relationship("Tile", foreign_keys="Tile.page_id", lazy='dynamic', order_by="asc(Tile.sort_order)") def toJSON(self): return { diff --git a/cli/app/sql/models/tile.py b/cli/app/sql/models/tile.py index 7dfa80b..3f6ce31 100644 --- a/cli/app/sql/models/tile.py +++ b/cli/app/sql/models/tile.py @@ -20,6 +20,7 @@ class Tile(Base): page_id = Column(Integer, ForeignKey('page.id'), nullable=True) target_page_id = Column(Integer, ForeignKey('page.id'), nullable=True) type = Column(String(16, convert_unicode=True), nullable=False) + sort_order = Column(Integer, default=0) settings = Column(JSON, default={}, nullable=True) created_at = Column(UtcDateTime(), default=utcnow()) updated_at = Column(UtcDateTime(), onupdate=utcnow()) @@ -31,6 +32,7 @@ class Tile(Base): 'page_id': self.page_id, 'target_page_id': self.target_page_id, 'type': self.type, + 'sort_order': self.sort_order, 'settings': self.settings, 'created_at': self.created_at, 'updated_at': self.updated_at, diff --git a/cli/app/sql/versions/202006041801_add_sort_order_to_tiles.py b/cli/app/sql/versions/202006041801_add_sort_order_to_tiles.py new file mode 100644 index 0000000..2c670a8 --- /dev/null +++ b/cli/app/sql/versions/202006041801_add_sort_order_to_tiles.py @@ -0,0 +1,29 @@ +"""add sort order to tiles + +Revision ID: 91a729020584 +Revises: 453787357254 +Create Date: 2020-06-04 18:01:33.482300 + +""" +from alembic import op +import sqlalchemy as sa +import sqlalchemy_utc + + +# revision identifiers, used by Alembic. +revision = '91a729020584' +down_revision = '453787357254' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('tile', sa.Column('sort_order', sa.Integer(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('tile', 'sort_order') + # ### end Alembic commands ### diff --git a/frontend/store.js b/frontend/store.js index 40c8d9c..9af2b96 100644 --- a/frontend/store.js +++ b/frontend/store.js @@ -1,6 +1,7 @@ import { applyMiddleware, compose, combineReducers, createStore } from 'redux' import { connectRouter, routerMiddleware } from 'connected-react-router' import { createBrowserHistory } from 'history' +import createDebounce from 'redux-debounced'; import thunk from 'redux-thunk' // import { login } from './util' @@ -33,6 +34,7 @@ const configureStore = (initialState = {}, history) => { composeEnhancers( applyMiddleware( thunk, + createDebounce(), routerMiddleware(history) ), ), diff --git a/frontend/types.js b/frontend/types.js index 98c18cb..10fb411 100644 --- a/frontend/types.js +++ b/frontend/types.js @@ -12,6 +12,8 @@ export const page = crud_type('page', [ 'show_add_tile_form', 'hide_add_tile_form', 'toggle_add_tile_form', 'show_edit_tile_form', 'hide_edit_tile_form', 'toggle_edit_tile_form', 'update_page_tile', + 'set_tile_sort_order', 'update_tile_sort_order', + 'show_tile_list', 'hide_tile_list', 'toggle_tile_list', ]) export const tile = crud_type('tile', [ diff --git a/frontend/views/graph/graph.css b/frontend/views/graph/graph.css index d6a0ff0..60a4c81 100644 --- a/frontend/views/graph/graph.css +++ b/frontend/views/graph/graph.css @@ -17,8 +17,11 @@ .sidebar { position: absolute; - top: 1rem; - right: 1rem; + top: 0; + right: 0; + padding: 1rem; + overflow: auto; + max-height: 100%; z-index: 2000; } .box { diff --git a/frontend/views/page/components/page.header.js b/frontend/views/page/components/page.header.js index 4170f8b..2898f86 100644 --- a/frontend/views/page/components/page.header.js +++ b/frontend/views/page/components/page.header.js @@ -13,6 +13,7 @@ function PageHeader(props) { </div> <div> <button onClick={() => props.pageActions.toggleAddTileForm()}>+ Add tile</button> + <button onClick={() => props.pageActions.toggleTileList()}>+ Sort tiles</button> </div> </header> ) diff --git a/frontend/views/page/components/tile.form.js b/frontend/views/page/components/tile.form.js index 31d49e3..6cf9474 100644 --- a/frontend/views/page/components/tile.form.js +++ b/frontend/views/page/components/tile.form.js @@ -77,7 +77,7 @@ class TileForm extends Component { } componentDidMount() { - const { graph, page, isNew, initialData } = this.props + const { graph, page, isNew, initialData, sortOrder } = this.props const title = isNew ? 'new tile' : 'editing tile' const submitTitle = isNew ? "Create Tile" : "Save Changes" this.setState({ @@ -86,11 +86,13 @@ class TileForm extends Component { errorFields: new Set([]), }) if (isNew) { - this.props.tileActions.updateTemporaryTile(newImage({ + const newTile = newImage({ id: "new", graph_id: graph.show.res.id, page_id: page.show.res.id, - })) + sort_order: sortOrder, + }) + this.props.tileActions.updateTemporaryTile(newTile) } else { this.props.tileActions.updateTemporaryTile({ ...initialData }) } diff --git a/frontend/views/page/components/tile.list.js b/frontend/views/page/components/tile.list.js new file mode 100644 index 0000000..232516d --- /dev/null +++ b/frontend/views/page/components/tile.list.js @@ -0,0 +1,73 @@ +import React, { Component } from 'react' +// import { Link } from 'react-router-dom' +import { bindActionCreators } from 'redux' +import { connect } from 'react-redux' +import { ReactSortable } from "react-sortablejs" + +// import actions from '../../../actions' +import * as tileActions from '../../tile/tile.actions' +import * as pageActions from '../../page/page.actions' + +class TileList extends Component { + state = { + tiles: [], + } + + componentDidMount(prevProps) { + const { tiles } = this.props.page.show.res + this.setState({ tiles }) + // this.props.pageActions.setTileSortOrder(list) + } + + componentDidUpdate(prevProps, prevState) { + const { tiles } = this.state + const { tiles: oldTiles } = prevState + // const { tiles } = this.props.page.show.res + // const { tiles: oldTiles } = prevProps.page.show.res + if (tiles !== oldTiles) { + this.props.pageActions.setTileSortOrder(tiles) + } + } + + render() { + const { tiles } = this.state + return ( + <div className='box tileList'> + <ReactSortable + list={tiles} + setList={newTiles => this.setState({ tiles: newTiles })} + > + {tiles.map(tile => ( + tile.type === 'image' + ? <TileListImage key={tile.id} tile={tile} /> + : <TileListText key={tile.id} tile={tile} /> + ))} + </ReactSortable> + </div> + ) + } +} + +const TileListImage = ({ tile }) => ( + <div className='row'> + <div className='thumb' style={{ backgroundImage: 'url(' + tile.settings.url + ')' }} /> + </div> +) + +const TileListText = ({ tile }) => ( + <div className='row'> + <span className='snippet'>{tile.settings.content.substr(0, 100)}</span> + </div> +) + +const mapStateToProps = state => ({ + graph: state.graph, + page: state.page, +}) + +const mapDispatchToProps = dispatch => ({ + tileActions: bindActionCreators({ ...tileActions }, dispatch), + pageActions: bindActionCreators({ ...pageActions }, dispatch), +}) + +export default connect(mapStateToProps, mapDispatchToProps)(TileList) diff --git a/frontend/views/page/components/tile.new.js b/frontend/views/page/components/tile.new.js index 3c97c31..c5ebeab 100644 --- a/frontend/views/page/components/tile.new.js +++ b/frontend/views/page/components/tile.new.js @@ -35,6 +35,7 @@ class TileNew extends Component { graph={this.props.graph.show.res} page={this.props.page.show.res} initialData={null} + sortOrder={this.props.page.show.res.tiles.length} onSubmit={this.handleSubmit.bind(this)} /> ) diff --git a/frontend/views/page/page.actions.js b/frontend/views/page/page.actions.js index bd38683..dd94936 100644 --- a/frontend/views/page/page.actions.js +++ b/frontend/views/page/page.actions.js @@ -26,6 +26,18 @@ export const toggleEditTileForm = () => dispatch => { dispatch({ type: types.page.toggle_edit_tile_form }) } +export const showTileList = () => dispatch => { + dispatch({ type: types.page.show_tile_list }) +} + +export const hideTileList = () => dispatch => { + dispatch({ type: types.page.hide_tile_list }) +} + +export const toggleTileList = () => dispatch => { + dispatch({ type: types.page.toggle_tile_list }) +} + export const updatePageTile = tile => dispatch => { dispatch({ type: types.page.update_page_tile, tile }) } @@ -52,4 +64,14 @@ export const showGraphIfUnloaded = ({ graph_name }) => dispatch => ( .then(resolve) .catch(reject) }) -)
\ No newline at end of file +) + +export const setTileSortOrder = tiles => dispatch => { + dispatch({ type: types.page.set_tile_sort_order, tiles }) + updateTileSortOrder(tiles)(dispatch) +} + +export const updateTileSortOrder = tiles => dispatch => { + +} + diff --git a/frontend/views/page/page.container.js b/frontend/views/page/page.container.js index 0c366ab..5da41d6 100644 --- a/frontend/views/page/page.container.js +++ b/frontend/views/page/page.container.js @@ -14,6 +14,7 @@ import * as pageActions from './page.actions' import PageEdit from '../graph/components/page.edit' import TileNew from './components/tile.new' import TileEdit from './components/tile.edit' +import TileList from './components/tile.list' import PageHeader from './components/page.header' import PageEditor from './components/page.editor' @@ -72,6 +73,7 @@ class PageContainer extends Component { {this.props.graph.editor.editingPage && <PageEdit />} {this.props.page.editor.addingTile && <TileNew />} {this.props.page.editor.editingTile && <TileEdit />} + {this.props.page.editor.tileList && <TileList />} </div> </div> </div> diff --git a/frontend/views/page/page.css b/frontend/views/page/page.css index 67e35df..d828b82 100644 --- a/frontend/views/page/page.css +++ b/frontend/views/page/page.css @@ -27,3 +27,32 @@ .tile.top_right { top: 0; right: 0; } .tile.center_right { top: 50%; right: 0; } .tile.bottom_right { bottom: 0; right: 0; } + +.tileList .row { + justify-content: flex-start; + align-items: center; + min-height: 2.5rem; + margin-bottom: 0.5rem; + box-shadow: 4px 4px 6px rgba(0,0,0,0.5); +} +.tileList .row:nth-child(odd) { + background: rgba(0,0,0,0.2); +} +.tileList .row:nth-child(even) { + background: rgba(255,255,255,0.2); +} +.tileList span { + display: block; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + white-space: nowrap; + padding: 0.25rem; +} +.tileList .thumb { + width: 100%; + height: 2.5rem; + background-position: center center; + background-size: cover; + background-repeat: no-repeat; +}
\ No newline at end of file diff --git a/frontend/views/page/page.reducer.js b/frontend/views/page/page.reducer.js index 2b0d102..063e22d 100644 --- a/frontend/views/page/page.reducer.js +++ b/frontend/views/page/page.reducer.js @@ -7,6 +7,7 @@ const initialState = crudState('page', { editor: { addingTile: false, editingTile: false, + tileList: false, }, options: { } @@ -49,6 +50,7 @@ export default function pageReducer(state = initialState, action) { } } + // add tile UI case types.page.show_add_tile_form: return { ...state, @@ -77,6 +79,7 @@ export default function pageReducer(state = initialState, action) { } } + // edit tile UI case types.page.show_edit_tile_form: return { ...state, @@ -96,6 +99,49 @@ export default function pageReducer(state = initialState, action) { } } + // tile list UI + case types.page.show_tile_list: + return { + ...state, + editor: { + ...state.editor, + addingTile: false, + editingTile: false, + tileList: true, + } + } + + case types.page.hide_tile_list: + return { + ...state, + editor: { + ...state.editor, + tileList: false, + } + } + + case types.page.toggle_tile_list: + return { + ...state, + editor: { + ...state.editor, + tileList: !state.editor.tileList, + } + } + + case types.page.set_tile_sort_order: + return { + ...state, + show: { + ...state.show, + res: { + ...state.res, + tiles: action.tiles, + } + } + } + + default: return state } diff --git a/package-lock.json b/package-lock.json index d4bf57f..0956159 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3287,6 +3287,11 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, + "@types/sortablejs": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.10.4.tgz", + "integrity": "sha512-iXdJUEM09Hc0RacStDvkEi5BBdHuuwdys0L5/GtsRiEht69Df4hapA3FwFIeXn2STicqJjBAkowyD1OA3jGgwA==" + }, "@webassemblyjs/ast": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", @@ -3456,9 +3461,9 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", "dev": true }, "acorn-jsx": { @@ -3467,11 +3472,6 @@ "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", "dev": true }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" - }, "aggregate-error": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", @@ -3607,11 +3607,6 @@ "es-abstract": "^1.17.0-next.1" } }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" - }, "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -3674,11 +3669,6 @@ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" - }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -4378,11 +4368,6 @@ "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" - }, "bail": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", @@ -4459,24 +4444,11 @@ "integrity": "sha512-V6YHUbjLxN1ymqNLb1DPHoU1CpfdL7d2YTIp5W3U4hhoG4hhxNmsFDs66M9EXxBiSEke5Bt5dwdfMwwZF70iLA==", "dev": true }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" - }, "base64-js": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "requires": { - "callsite": "1.0.0" - } - }, "big.js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", @@ -4496,11 +4468,6 @@ "file-uri-to-path": "1.0.0" } }, - "blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" - }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -4737,11 +4704,6 @@ } } }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" - }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -4858,6 +4820,11 @@ } } }, + "classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" + }, "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -4983,21 +4950,11 @@ } } }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" - }, "component-emitter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5522,51 +5479,6 @@ "once": "^1.4.0" } }, - "engine.io-client": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.0.tgz", - "integrity": "sha512-a4J5QO2k99CM2a0b12IznnyQndoEvtA4UAldhGzKqnHf42I3Qs2W5SPnDvatZRcMaNZs4IevVicBPayxYt6FwA==", - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~4.1.0", - "engine.io-parser": "~2.2.0", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~6.1.0", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "engine.io-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz", - "integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==", - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, "enhanced-resolve": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz", @@ -6391,6 +6303,14 @@ "readable-stream": "^2.3.6" } }, + "flux-standard-action": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/flux-standard-action/-/flux-standard-action-0.6.1.tgz", + "integrity": "sha1-bzQhG5SDTqHDzDD056+tPQ+/caI=", + "requires": { + "lodash.isplainobject": "^3.2.0" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -7060,26 +6980,6 @@ "ansi-regex": "^2.0.0" } }, - "has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "requires": { - "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - } - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -7317,11 +7217,6 @@ "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" - }, "infer-owner": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", @@ -7880,11 +7775,63 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, + "lodash._basefor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", + "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=" + }, "lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, + "lodash.isplainobject": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-3.2.0.tgz", + "integrity": "sha1-moI4rhayAEMpYM1zRlEtASP79MU=", + "requires": { + "lodash._basefor": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.keysin": "^3.0.0" + } + }, + "lodash.keysin": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-3.0.8.tgz", + "integrity": "sha1-IsRJPrvtsUJ5YqVLRFssinZ/tH8=", + "requires": { + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=" + }, + "lodash.throttle": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.0.1.tgz", + "integrity": "sha1-syEWYu6dgvVpA9BzEmKqqoc6YzA=", + "requires": { + "lodash.debounce": "^4.0.0" + } + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -8351,11 +8298,6 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" - }, "object-copy": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", @@ -8626,22 +8568,6 @@ "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "requires": { - "better-assert": "~1.0.0" - } - }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -9125,6 +9051,17 @@ "tiny-warning": "^1.0.0" } }, + "react-sortablejs": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/react-sortablejs/-/react-sortablejs-2.0.11.tgz", + "integrity": "sha512-Id44yygU6H/fNRp0uWkGZnKGuBF8GF/Ts6gKX5NfwmzceRjH0e0XHsmBuQ6WXhBIVnMM+XgkEPub851mdti0TA==", + "requires": { + "@types/sortablejs": "^1.10.0", + "classnames": "^2.2.6", + "sortablejs": "1.10.1", + "tiny-invariant": "^1.0.6" + } + }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -9493,6 +9430,29 @@ "symbol-observable": "^1.2.0" } }, + "redux-debounce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/redux-debounce/-/redux-debounce-1.0.1.tgz", + "integrity": "sha1-dqcJU/uz+J6f1Aw5BnSs7vQA0QU=", + "requires": { + "flux-standard-action": "^0.6.1", + "lodash.debounce": "^4.0.6", + "lodash.mapvalues": "^4.3.0" + } + }, + "redux-debounced": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/redux-debounced/-/redux-debounced-0.5.0.tgz", + "integrity": "sha512-O2anhB0A6yQZH19uLETFtajcUQLcyiJcgC0hHSoFr5T3hWGtt0C5s6KNnb2RX51MwCh5VCl9ehZTv91F/rsZww==" + }, + "redux-throttle": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/redux-throttle/-/redux-throttle-0.1.1.tgz", + "integrity": "sha1-QwcFc/AzHRKuFvrmVyrZ1/y3Ya4=", + "requires": { + "lodash.throttle": "4.0.1" + } + }, "redux-thunk": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", @@ -10009,66 +9969,10 @@ "kind-of": "^3.2.0" } }, - "socket.io-client": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", - "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "engine.io-client": "~3.4.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "socket.io-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", - "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - } - } + "sortablejs": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.10.1.tgz", + "integrity": "sha512-N6r7GrVmO8RW1rn0cTdvK3JR0BcqecAJ0PmYMCL3ZuqTH3pY+9QyqkmJSkkLyyDvd+AJnwaxTP22Ybr/83V9hQ==" }, "source-list-map": { "version": "2.0.0", @@ -10791,11 +10695,6 @@ "os-tmpdir": "~1.0.2" } }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" - }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", @@ -11527,14 +11426,6 @@ "mkdirp": "^0.5.1" } }, - "ws": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", - "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", - "requires": { - "async-limiter": "~1.0.0" - } - }, "x-is-string": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", @@ -11560,11 +11451,6 @@ "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==", "optional": true }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" - }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", @@ -11619,18 +11505,13 @@ } }, "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" } } } diff --git a/package.json b/package.json index a2844ab..b3cfada 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,11 @@ "react-redux": "^7.2.0", "react-router": "^5.1.2", "react-router-dom": "^5.1.2", + "react-sortablejs": "^2.0.11", "redux": "^4.0.5", + "redux-debounce": "^1.0.1", + "redux-debounced": "^0.5.0", + "redux-throttle": "^0.1.1", "redux-thunk": "^2.3.0", "store2": "^2.10.0", "style-loader": "^1.1.3", |
