Add ordering.

pull/7/head
Sander Vocke 5 years ago
parent 98a01bb3ca
commit 2bf21aa28f
  1. 8
      client/src/App.tsx
  2. 20
      client/src/api.ts
  3. 35
      client/src/components/BrowseWindow.tsx
  4. 19
      client/src/components/DraggableItemListItem.tsx
  5. 4
      client/src/components/ItemList.tsx
  6. 13
      client/src/components/QueryBrowseWindow.tsx
  7. 3
      client/src/types/DragTypes.tsx
  8. 4
      package.json
  9. 23
      server/endpoints/QueryEndpointHandler.ts
  10. 116
      yarn.lock

@ -3,6 +3,8 @@ import React, { useState, useEffect } from 'react';
import AppBar, { ActiveTab as AppBarActiveTab } from './components/AppBar'; import AppBar, { ActiveTab as AppBarActiveTab } from './components/AppBar';
import { Query, isQuery, QueryKeys } from './types/Query'; import { Query, isQuery, QueryKeys } from './types/Query';
import QueryBrowseWindow, { TypesIncluded } from './components/QueryBrowseWindow'; import QueryBrowseWindow, { TypesIncluded } from './components/QueryBrowseWindow';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { import {
BrowserRouter as Router, BrowserRouter as Router,
@ -30,7 +32,7 @@ function AppBody() {
const location = useLocation(); const location = useLocation();
const queryParams = new URLSearchParams(location.search); const queryParams = new URLSearchParams(location.search);
const [ types, setTypes ] = useState<TypesIncluded>({songs: true, artists: true, tags: true}); const [types, setTypes] = useState<TypesIncluded>({ songs: true, artists: true, tags: true });
// If we have an invalid query, change to the default one. // If we have an invalid query, change to the default one.
const itemQuery: Query | undefined = JSURL.tryParse(queryParams.get('query'), undefined); const itemQuery: Query | undefined = JSURL.tryParse(queryParams.get('query'), undefined);
@ -88,7 +90,9 @@ function AppBody() {
function App() { function App() {
return ( return (
<Router> <Router>
<AppBody /> <DndProvider backend={HTML5Backend}>
<AppBody />
</DndProvider>
</Router> </Router>
); );
} }

@ -19,12 +19,18 @@ export interface ArtistDetails {
name: String, name: String,
storeLinks?: String[], storeLinks?: String[],
} }
export function isArtistDetails(q: any): q is ArtistDetails {
return 'artistId' in q;
}
export interface TagDetails { export interface TagDetails {
tagId: Number, tagId: Number,
name: String, name: String,
parent?: TagDetails, parent?: TagDetails,
storeLinks?: String[], storeLinks?: String[],
} }
export function isTagDetails(q: any): q is TagDetails {
return 'tagId' in q;
}
export interface RankingDetails { export interface RankingDetails {
rankingId: Number, rankingId: Number,
type: ItemType, // The item type being ranked type: ItemType, // The item type being ranked
@ -32,6 +38,9 @@ export interface RankingDetails {
context: ArtistDetails | TagDetails, context: ArtistDetails | TagDetails,
value: Number, // The ranking (higher = better) value: Number, // The ranking (higher = better)
} }
export function isRankingDetails(q: any): q is RankingDetails {
return 'rankingId' in q;
}
export interface SongDetails { export interface SongDetails {
songId: Number, songId: Number,
title: String, title: String,
@ -40,6 +49,9 @@ export interface SongDetails {
storeLinks?: String[], storeLinks?: String[],
rankings?: RankingDetails[], rankings?: RankingDetails[],
} }
export function isSongDetails(q: any): q is SongDetails {
return 'songId' in q;
}
// Query for items (POST). // Query for items (POST).
export const QueryEndpoint = '/query'; export const QueryEndpoint = '/query';
@ -60,6 +72,9 @@ export enum QueryElemProperty {
artistName = "artistName", artistName = "artistName",
albumName = "albumName", albumName = "albumName",
} }
export enum OrderBy {
Name = 0
}
export interface QueryElem { export interface QueryElem {
prop?: QueryElemProperty, prop?: QueryElemProperty,
propOperand?: any, propOperand?: any,
@ -67,6 +82,10 @@ export interface QueryElem {
children?: QueryElem[] children?: QueryElem[]
childrenOperator?: QueryElemOp, childrenOperator?: QueryElemOp,
} }
export interface Ordering {
orderBy: OrderBy,
ascending: boolean,
}
export interface Query extends QueryElem { } export interface Query extends QueryElem { }
export interface QueryRequest { export interface QueryRequest {
query: Query, query: Query,
@ -76,6 +95,7 @@ export interface QueryRequest {
artistLimit: number, artistLimit: number,
tagOffset: number, tagOffset: number,
tagLimit: number, tagLimit: number,
ordering: Ordering,
} }
export interface QueryResponse { export interface QueryResponse {
songs: SongDetails[], songs: SongDetails[],

@ -2,37 +2,14 @@ import React from 'react';
import { Paper } from '@material-ui/core'; import { Paper } from '@material-ui/core';
import { DisplayItem } from '../types/DisplayItem'; import { DisplayItem } from '../types/DisplayItem';
import ItemListItem from './ItemListItem'; import DraggableItemListItem from './DraggableItemListItem';
import ItemList from './ItemList'; import ItemList from './ItemList';
import * as serverApi from '../api'; import * as serverApi from '../api';
import StoreIcon from '@material-ui/icons/Store'; import StoreIcon from '@material-ui/icons/Store';
import { ReactComponent as GooglePlayIcon } from '../assets/googleplaymusic_icon.svg'; import { ReactComponent as GooglePlayIcon } from '../assets/googleplaymusic_icon.svg';
type SongItem = serverApi.SongDetails;
export interface SongItem extends serverApi.SongDetails { type ArtistItem = serverApi.ArtistDetails;
songSignature: any
}
export function isSongItem(q: any): q is SongItem {
return 'songSignature' in q;
}
export function toSongItem(i: serverApi.SongDetails) {
const r: any = i;
r['songSignature'] = true;
return r;
}
export interface ArtistItem extends serverApi.ArtistDetails {
artistSignature: any
}
export function isArtistItem(q: any): q is ArtistItem {
return 'artistSignature' in q;
}
export function toArtistItem(i: serverApi.ArtistDetails) {
const r: any = i;
r['artistSignature'] = true;
return r;
}
export type Item = SongItem | ArtistItem; export type Item = SongItem | ArtistItem;
const getStoreIcon = (url: String) => { const getStoreIcon = (url: String) => {
@ -43,7 +20,7 @@ const getStoreIcon = (url: String) => {
} }
function toDisplayItem(item: Item): DisplayItem | undefined { function toDisplayItem(item: Item): DisplayItem | undefined {
if (isSongItem(item)) { if (serverApi.isSongDetails(item)) {
return { return {
title: item.title, title: item.title,
artistNames: item.artists && item.artists.map((artist: serverApi.ArtistDetails) => { artistNames: item.artists && item.artists.map((artist: serverApi.ArtistDetails) => {
@ -59,7 +36,7 @@ function toDisplayItem(item: Item): DisplayItem | undefined {
} }
}) || [], }) || [],
} }
} else if (isArtistItem(item)) { } else if (serverApi.isArtistDetails(item)) {
return { return {
name: item.name ? item.name : "Unknown", name: item.name ? item.name : "Unknown",
tagNames: [], // TODO tagNames: [], // TODO
@ -84,7 +61,7 @@ export default function BrowseWindow(props: IProps) {
<ItemList> <ItemList>
{props.items.map((item: Item) => { {props.items.map((item: Item) => {
const di = toDisplayItem(item); const di = toDisplayItem(item);
return di && <ItemListItem item={di} />; return di && <DraggableItemListItem item={di} />;
})} })}
</ItemList> </ItemList>
</Paper>; </Paper>;

@ -0,0 +1,19 @@
import React from 'react';
import ItemListItem from './ItemListItem';
import { useDrag } from 'react-dnd';
import { dragTypes } from '../types/DragTypes';
export default function DraggableItemListItem(props: any) {
const [{ isDragging: boolean }, drag] = useDrag({
item: { type: dragTypes.ListItem },
collect: (monitor: any) => ({
isDragging: !!monitor.isDragging(),
}),
});
return <div
ref={drag}
>
<ItemListItem {...props} />
</div>;
}

@ -17,9 +17,7 @@ export default function ItemList(props:any) {
return ( return (
<div className={classes.root}> <div className={classes.root}>
<List dense={true}> <List dense={true}>
{props.children.map((child: any) => { {props.children}
return child;
})}
</List> </List>
</div> </div>
); );

@ -3,7 +3,7 @@ import React, { useState, useEffect } from 'react';
import { Query, toApiQuery } from '../types/Query'; import { Query, toApiQuery } from '../types/Query';
import FilterControl from './FilterControl'; import FilterControl from './FilterControl';
import * as serverApi from '../api'; import * as serverApi from '../api';
import BrowseWindow, { toSongItem, toArtistItem, Item } from './BrowseWindow'; import BrowseWindow, { Item } from './BrowseWindow';
import { FormControl, FormLabel, FormGroup, FormControlLabel, Checkbox } from '@material-ui/core'; import { FormControl, FormLabel, FormGroup, FormControlLabel, Checkbox } from '@material-ui/core';
const _ = require('lodash'); const _ = require('lodash');
@ -73,12 +73,9 @@ export default function QueryBrowseWindow(props: IProps) {
const [artists, setArtists] = useState<serverApi.ArtistDetails[]>([]); const [artists, setArtists] = useState<serverApi.ArtistDetails[]>([]);
//const [tags, setTags] = useState<serverApi.TagDetails[]>([]); //const [tags, setTags] = useState<serverApi.TagDetails[]>([]);
const songItems: Item[] = songs.map(toSongItem);
const artistItems: Item[] = artists.map(toArtistItem);
var items: Item[] = []; var items: Item[] = [];
props.typesIncluded.songs && items.push(...songItems); props.typesIncluded.songs && items.push(...songs);
props.typesIncluded.artists && items.push(...artistItems); props.typesIncluded.artists && items.push(...artists);
useEffect(() => { useEffect(() => {
if (!props.query) { return; } if (!props.query) { return; }
@ -92,6 +89,10 @@ export default function QueryBrowseWindow(props: IProps) {
artistLimit: 5, artistLimit: 5,
tagOffset: 0, tagOffset: 0,
tagLimit: 5, tagLimit: 5,
ordering: {
orderBy: serverApi.OrderBy.Name,
ascending: true,
}
} }
const requestOpts = { const requestOpts = {
method: 'POST', method: 'POST',

@ -0,0 +1,3 @@
export const dragTypes = {
ListItem: 'list item'
}

@ -8,5 +8,9 @@
}, },
"devDependencies": { "devDependencies": {
"concurrently": "^4.0.1" "concurrently": "^4.0.1"
},
"dependencies": {
"react-dnd": "^11.1.3",
"react-dnd-html5-backend": "^11.1.3"
} }
} }

@ -40,6 +40,18 @@ const sequelizeProps: any = {
} }
}; };
const sequelizeOrderColumns: any = {
[QueryType.Song]: {
[api.OrderBy.Name]: 'title'
},
[QueryType.Artist]: {
[api.OrderBy.Name]: 'name'
},
[QueryType.Tag]: {
[api.OrderBy.Name]: 'name'
},
}
// Returns the "where" clauses for Sequelize, per object type. // Returns the "where" clauses for Sequelize, per object type.
const getSequelizeWhere = (queryElem: api.QueryElem, type: QueryType) => { const getSequelizeWhere = (queryElem: api.QueryElem, type: QueryType) => {
var where: any = { var where: any = {
@ -66,6 +78,14 @@ const getSequelizeWhere = (queryElem: api.QueryElem, type: QueryType) => {
return where; return where;
} }
function getSequelizeOrder(order: api.Ordering, type: QueryType) {
const ascstring = order.ascending ? 'ASC' : 'DESC';
return [
[ sequelizeOrderColumns[type][order.orderBy], ascstring ]
];
}
export const QueryEndpointHandler: EndpointHandler = async (req: any, res: any) => { export const QueryEndpointHandler: EndpointHandler = async (req: any, res: any) => {
if (!api.checkQueryRequest(req.body)) { if (!api.checkQueryRequest(req.body)) {
const e: EndpointError = { const e: EndpointError = {
@ -81,6 +101,7 @@ export const QueryEndpointHandler: EndpointHandler = async (req: any, res: any)
// NOTE: have to disable limit and offset because of bug: https://github.com/sequelize/sequelize/issues/11938. // NOTE: have to disable limit and offset because of bug: https://github.com/sequelize/sequelize/issues/11938.
// Custom pagination is implemented before responding. // Custom pagination is implemented before responding.
where: getSequelizeWhere(reqObject.query, QueryType.Song), where: getSequelizeWhere(reqObject.query, QueryType.Song),
order: getSequelizeOrder(reqObject.ordering, QueryType.Song),
include: [models.Artist, models.Album, models.Tag, models.Ranking], include: [models.Artist, models.Album, models.Tag, models.Ranking],
//limit: reqObject.limit, //limit: reqObject.limit,
//offset: reqObject.offset, //offset: reqObject.offset,
@ -89,6 +110,7 @@ export const QueryEndpointHandler: EndpointHandler = async (req: any, res: any)
// NOTE: have to disable limit and offset because of bug: https://github.com/sequelize/sequelize/issues/11938. // NOTE: have to disable limit and offset because of bug: https://github.com/sequelize/sequelize/issues/11938.
// Custom pagination is implemented before responding. // Custom pagination is implemented before responding.
where: getSequelizeWhere(reqObject.query, QueryType.Artist), where: getSequelizeWhere(reqObject.query, QueryType.Artist),
order: getSequelizeOrder(reqObject.ordering, QueryType.Artist),
include: [models.Song, models.Album, models.Tag], include: [models.Song, models.Album, models.Tag],
//limit: reqObject.limit, //limit: reqObject.limit,
//offset: reqObject.offset, //offset: reqObject.offset,
@ -97,6 +119,7 @@ export const QueryEndpointHandler: EndpointHandler = async (req: any, res: any)
// NOTE: have to disable limit and offset because of bug: https://github.com/sequelize/sequelize/issues/11938. // NOTE: have to disable limit and offset because of bug: https://github.com/sequelize/sequelize/issues/11938.
// Custom pagination is implemented before responding. // Custom pagination is implemented before responding.
where: getSequelizeWhere(reqObject.query, QueryType.Tag), where: getSequelizeWhere(reqObject.query, QueryType.Tag),
order: getSequelizeOrder(reqObject.ordering, QueryType.Tag),
include: [models.Song, models.Album, models.Artist], include: [models.Song, models.Album, models.Artist],
//limit: reqObject.limit, //limit: reqObject.limit,
//offset: reqObject.offset, //offset: reqObject.offset,

@ -2,6 +2,42 @@
# yarn lockfile v1 # yarn lockfile v1
"@react-dnd/asap@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@react-dnd/asap/-/asap-4.0.0.tgz#b300eeed83e9801f51bd66b0337c9a6f04548651"
integrity sha512-0XhqJSc6pPoNnf8DhdsPHtUhRzZALVzYMTzRwV4VI6DJNJ/5xxfL9OQUwb8IH5/2x7lSf7nAZrnzUD+16VyOVQ==
"@react-dnd/invariant@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@react-dnd/invariant/-/invariant-2.0.0.tgz#09d2e81cd39e0e767d7da62df9325860f24e517e"
integrity sha512-xL4RCQBCBDJ+GRwKTFhGUW8GXa4yoDfJrPbLblc3U09ciS+9ZJXJ3Qrcs/x2IODOdIE5kQxvMmE2UKyqUictUw==
"@react-dnd/shallowequal@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz#a3031eb54129f2c66b2753f8404266ec7bf67f0a"
integrity sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==
"@types/hoist-non-react-statics@^3.3.1":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
dependencies:
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
"@types/prop-types@*":
version "15.7.3"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
"@types/react@*":
version "16.9.44"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.44.tgz#da84b179c031aef67dc92c33bd3401f1da2fa3bc"
integrity sha512-BtLoJrXdW8DVZauKP+bY4Kmiq7ubcJq+H/aCpRfvPF7RAT3RwR73Sg8szdc2YasbAlWBDrQ6Q+AFM0KwtQY+WQ==
dependencies:
"@types/prop-types" "*"
csstype "^3.0.2"
ansi-regex@^2.0.0: ansi-regex@^2.0.0:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
@ -85,6 +121,11 @@ cross-spawn@^6.0.0:
shebang-command "^1.2.0" shebang-command "^1.2.0"
which "^1.2.9" which "^1.2.9"
csstype@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.2.tgz#ee5ff8f208c8cd613b389f7b222c9801ca62b3f7"
integrity sha512-ofovWglpqoqbfLNOTBNZLSbMuGrblAf1efvvArGKOZMBrIoJeu5UsAipQolkijtyQx5MtAzT/J9IHj/CEY1mJw==
date-fns@^1.30.1: date-fns@^1.30.1:
version "1.30.1" version "1.30.1"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c"
@ -95,6 +136,15 @@ decamelize@^1.2.0:
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
dnd-core@^11.1.3:
version "11.1.3"
resolved "https://registry.yarnpkg.com/dnd-core/-/dnd-core-11.1.3.tgz#f92099ba7245e49729d2433157031a6267afcc98"
integrity sha512-QugF55dNW+h+vzxVJ/LSJeTeUw9MCJ2cllhmVThVPEtF16ooBkxj0WBE5RB+AceFxMFo1rO6bJKXtqKl+JNnyA==
dependencies:
"@react-dnd/asap" "^4.0.0"
"@react-dnd/invariant" "^2.0.0"
redux "^4.0.4"
end-of-stream@^1.1.0: end-of-stream@^1.1.0:
version "1.4.4" version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
@ -156,6 +206,13 @@ has-flag@^3.0.0:
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
hoist-non-react-statics@^3.3.0:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
dependencies:
react-is "^16.7.0"
hosted-git-info@^2.1.4: hosted-git-info@^2.1.4:
version "2.8.8" version "2.8.8"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
@ -193,6 +250,11 @@ isexe@^2.0.0:
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
"js-tokens@^3.0.0 || ^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
json-parse-better-errors@^1.0.1: json-parse-better-errors@^1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
@ -218,6 +280,13 @@ lodash@^4.17.15:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
map-age-cleaner@^0.1.1: map-age-cleaner@^0.1.1:
version "0.1.3" version "0.1.3"
resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
@ -352,6 +421,28 @@ pump@^3.0.0:
end-of-stream "^1.1.0" end-of-stream "^1.1.0"
once "^1.3.1" once "^1.3.1"
react-dnd-html5-backend@^11.1.3:
version "11.1.3"
resolved "https://registry.yarnpkg.com/react-dnd-html5-backend/-/react-dnd-html5-backend-11.1.3.tgz#2749f04f416ec230ea193f5c1fbea2de7dffb8f7"
integrity sha512-/1FjNlJbW/ivkUxlxQd7o3trA5DE33QiRZgxent3zKme8DwF4Nbw3OFVhTRFGaYhHFNL1rZt6Rdj1D78BjnNLw==
dependencies:
dnd-core "^11.1.3"
react-dnd@^11.1.3:
version "11.1.3"
resolved "https://registry.yarnpkg.com/react-dnd/-/react-dnd-11.1.3.tgz#f9844f5699ccc55dfc81462c2c19f726e670c1af"
integrity sha512-8rtzzT8iwHgdSC89VktwhqdKKtfXaAyC4wiqp0SywpHG12TTLvfOoL6xNEIUWXwIEWu+CFfDn4GZJyynCEuHIQ==
dependencies:
"@react-dnd/shallowequal" "^2.0.0"
"@types/hoist-non-react-statics" "^3.3.1"
dnd-core "^11.1.3"
hoist-non-react-statics "^3.3.0"
react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
read-pkg@^4.0.1: read-pkg@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237"
@ -361,6 +452,14 @@ read-pkg@^4.0.1:
parse-json "^4.0.0" parse-json "^4.0.0"
pify "^3.0.0" pify "^3.0.0"
redux@^4.0.4:
version "4.0.5"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f"
integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==
dependencies:
loose-envify "^1.4.0"
symbol-observable "^1.2.0"
require-directory@^2.1.1: require-directory@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
@ -493,6 +592,11 @@ supports-color@^5.3.0:
dependencies: dependencies:
has-flag "^3.0.0" has-flag "^3.0.0"
symbol-observable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
tree-kill@^1.2.1: tree-kill@^1.2.1:
version "1.2.2" version "1.2.2"
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
@ -503,18 +607,6 @@ tslib@^1.9.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==
typescript-require@^0.2.10:
version "0.2.10"
resolved "https://registry.yarnpkg.com/typescript-require/-/typescript-require-0.2.10.tgz#8c8ee2aa75f3530b560b849c2927cd3697eba68e"
integrity sha1-jI7iqnXzUwtWC4ScKSfNNpfrpo4=
dependencies:
typescript "^1.5.3"
typescript@^1.5.3:
version "1.8.10"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-1.8.10.tgz#b475d6e0dff0bf50f296e5ca6ef9fbb5c7320f1e"
integrity sha1-tHXW4N/wv1DyluXKbvn7tccyDx4=
validate-npm-package-license@^3.0.1: validate-npm-package-license@^3.0.1:
version "3.0.4" version "3.0.4"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"

Loading…
Cancel
Save