diff --git a/package-lock.json b/package-lock.json
index 9289f18..fc2b68f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1582,6 +1582,36 @@
"chalk": "^4.0.0"
}
},
+ "@mapbox/jsonlint-lines-primitives": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz",
+ "integrity": "sha1-zlblOfg1UrWNENZy6k1vya3HsjQ="
+ },
+ "@mapbox/mapbox-gl-style-spec": {
+ "version": "13.19.0",
+ "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-style-spec/-/mapbox-gl-style-spec-13.19.0.tgz",
+ "integrity": "sha512-qA9P4WHU4a1iLKM/W2EIxCxcwlxa6isPF6P+jSPaIs4VlZKYO1DMVWNiY03SXu6a+K3dB3GEhRLvEh1f/8VG2w==",
+ "requires": {
+ "@mapbox/jsonlint-lines-primitives": "~2.0.2",
+ "@mapbox/point-geometry": "^0.1.0",
+ "@mapbox/unitbezier": "^0.0.0",
+ "csscolorparser": "~1.0.2",
+ "json-stringify-pretty-compact": "^2.0.0",
+ "minimist": "^1.2.5",
+ "rw": "^1.3.3",
+ "sort-object": "^0.3.2"
+ }
+ },
+ "@mapbox/point-geometry": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz",
+ "integrity": "sha1-ioP5M1x4YO/6Lu7KJUMyqgru2PI="
+ },
+ "@mapbox/unitbezier": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.0.tgz",
+ "integrity": "sha1-FWUb1VOme4WB+zmIEMmK2Go0Uk4="
+ },
"@nodelib/fs.scandir": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
@@ -1977,6 +2007,16 @@
"integrity": "sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==",
"dev": true
},
+ "@types/hoist-non-react-statics": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
+ "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
+ "dev": true,
+ "requires": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
"@types/html-minifier-terser": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz",
@@ -2022,6 +2062,12 @@
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4="
},
+ "@types/lodash": {
+ "version": "4.14.168",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz",
+ "integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==",
+ "dev": true
+ },
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@@ -2074,6 +2120,18 @@
"@types/react": "*"
}
},
+ "@types/react-redux": {
+ "version": "7.1.16",
+ "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.16.tgz",
+ "integrity": "sha512-f/FKzIrZwZk7YEO9E1yoxIuDNRiDducxkFlkw/GNMGEnK9n4K8wJzlJBghpSuOVDgEUHoDkDF7Gi9lHNQR4siw==",
+ "dev": true,
+ "requires": {
+ "@types/hoist-non-react-statics": "^3.3.0",
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0",
+ "redux": "^4.0.0"
+ }
+ },
"@types/react-router": {
"version": "5.1.11",
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.11.tgz",
@@ -4409,6 +4467,11 @@
"resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
"integrity": "sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s="
},
+ "csscolorparser": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz",
+ "integrity": "sha1-s085HupNqPPpgjHizNjfnAQfFxs="
+ },
"cssdb": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz",
@@ -8697,6 +8760,11 @@
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE="
},
+ "json-stringify-pretty-compact": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-2.0.0.tgz",
+ "integrity": "sha512-WRitRfs6BGq4q8gTgOy4ek7iPFXjbra0H3PmDLKm2xnZ+Gh1HUhiKGgCZkSPNULlP7mvfu6FV/mOLhCarspADQ=="
+ },
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
@@ -8953,6 +9021,11 @@
"yallist": "^4.0.0"
}
},
+ "luxon": {
+ "version": "1.25.0",
+ "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.25.0.tgz",
+ "integrity": "sha512-hEgLurSH8kQRjY6i4YLey+mcKVAWXbDNlZRmM6AgWDJ1cY3atl8Ztf5wEY7VBReFbmGnwQPz7KYJblL8B2k0jQ=="
+ },
"lz-string": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz",
@@ -9008,6 +9081,11 @@
"object-visit": "^1.0.0"
}
},
+ "mapbox-to-css-font": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/mapbox-to-css-font/-/mapbox-to-css-font-2.4.0.tgz",
+ "integrity": "sha512-v674D0WtpxCXlA6E+sBlG1QJWdUkz/s9qAD91bJSXBGuBL5lL4tJXpoJEftecphCh2SVQCjWMS2vhylc3AIQTg=="
+ },
"md5.js": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
@@ -9976,6 +10054,26 @@
"resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
"integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg=="
},
+ "ol": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/ol/-/ol-6.5.0.tgz",
+ "integrity": "sha512-a5ebahrjF5yCPFle1rc0aHzKp/9A4LlUnjh+S3I+x4EgcvcddDhpOX3WDOs0Pg9/wEElrikHSGEvbeej2Hh4Ug==",
+ "requires": {
+ "ol-mapbox-style": "^6.1.1",
+ "pbf": "3.2.1",
+ "rbush": "^3.0.1"
+ }
+ },
+ "ol-mapbox-style": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/ol-mapbox-style/-/ol-mapbox-style-6.3.1.tgz",
+ "integrity": "sha512-hZsvPVkk1Y+qmifxRX/gCaZJ5Mo04vWj6lbFhXpHDloQquHD3kTY0q8o3xbg4FehucuG7HyQteKWeFJRh3FMww==",
+ "requires": {
+ "@mapbox/mapbox-gl-style-spec": "^13.14.0",
+ "mapbox-to-css-font": "^2.4.0",
+ "webfont-matcher": "^1.1.0"
+ }
+ },
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@@ -10292,6 +10390,15 @@
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="
},
+ "pbf": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz",
+ "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==",
+ "requires": {
+ "ieee754": "^1.1.12",
+ "resolve-protobuf-schema": "^2.1.0"
+ }
+ },
"pbkdf2": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz",
@@ -11557,6 +11664,11 @@
"react-is": "^16.8.1"
}
},
+ "protocol-buffers-schema": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.5.1.tgz",
+ "integrity": "sha512-YVCvdhxWNDP8/nJDyXLuM+UFsuPk4+1PB7WGPVDzm3HTHbzFLxQYeW2iZpS4mmnXrQJGBzt230t/BbEb7PrQaw=="
+ },
"proxy-addr": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
@@ -11670,6 +11782,11 @@
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="
},
+ "quickselect": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz",
+ "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw=="
+ },
"raf": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
@@ -11718,6 +11835,14 @@
}
}
},
+ "rbush": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz",
+ "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==",
+ "requires": {
+ "quickselect": "^2.0.0"
+ }
+ },
"react": {
"version": "17.0.1",
"resolved": "https://registry.npmjs.org/react/-/react-17.0.1.tgz",
@@ -12426,6 +12551,14 @@
"resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
"integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng=="
},
+ "resolve-protobuf-schema": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz",
+ "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==",
+ "requires": {
+ "protocol-buffers-schema": "^3.3.1"
+ }
+ },
"resolve-url": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
@@ -12689,6 +12822,11 @@
"aproba": "^1.1.1"
}
},
+ "rw": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
+ "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q="
+ },
"rxjs": {
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz",
@@ -13524,6 +13662,16 @@
}
}
},
+ "sort-asc": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.1.0.tgz",
+ "integrity": "sha1-q3md9h/HPqCVbHnEtTHtHp53J+k="
+ },
+ "sort-desc": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.1.1.tgz",
+ "integrity": "sha1-GYuMDN6wlcRjNBhh45JdTuNZqe4="
+ },
"sort-keys": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
@@ -13532,6 +13680,15 @@
"is-plain-obj": "^1.0.0"
}
},
+ "sort-object": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-0.3.2.tgz",
+ "integrity": "sha1-mODRme3kDgfGGoRAPGHWw7KQ+eI=",
+ "requires": {
+ "sort-asc": "^0.1.0",
+ "sort-desc": "^0.1.1"
+ }
+ },
"source-list-map": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
@@ -15178,6 +15335,11 @@
"resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-0.2.4.tgz",
"integrity": "sha512-6BjspCO9VriYy12z356nL6JBS0GYeEcA457YyRzD+dD6XYCQ75NKhcOHUMHentOE7OcVCIXXDvOm0jKFfQG2Gg=="
},
+ "webfont-matcher": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/webfont-matcher/-/webfont-matcher-1.1.0.tgz",
+ "integrity": "sha1-mM6VCXsp4x++czBT4Q5XFkLRxsc="
+ },
"webidl-conversions": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz",
diff --git a/package.json b/package.json
index 8295f9e..b1d03fc 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,9 @@
"@types/node": "^14.14.25",
"@types/react": "^17.0.1",
"@types/react-dom": "^17.0.0",
+ "luxon": "^1.25.0",
"node-sass": "^4.14.1",
+ "ol": "^6.5.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-redux": "^7.2.2",
@@ -52,6 +54,8 @@
"proxy": "http://localhost:3000",
"port": 3001,
"devDependencies": {
+ "@types/lodash": "^4.14.168",
+ "@types/react-redux": "^7.1.16",
"@types/react-router-dom": "^5.1.7"
}
}
diff --git a/src/App.js b/src/App.js
index 9e231d0..0b316dc 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,127 +1,13 @@
import React from 'react'
import {connect} from 'react-redux'
-import {Item, Tab, Button, Loader, Pagination, Icon} from 'semantic-ui-react'
-import {useObservable} from 'rxjs-hooks'
-import {BrowserRouter as Router, Switch, Route, Link, useParams, useHistory, useRouteMatch} from 'react-router-dom'
-import {of, from, concat} from 'rxjs'
-import {map, switchMap, distinctUntilChanged, debounceTime} from 'rxjs/operators'
+import {Button} from 'semantic-ui-react'
+import {BrowserRouter as Router, Switch, Route, Link} from 'react-router-dom'
import _ from 'lodash'
-import {Page} from './components'
import styles from './App.module.scss'
import api from './api'
-import {LoginPage, LogoutPage, NotFoundPage} from './pages'
-import {useQueryParam, stringifyParams} from './query.ts'
-
-function TracksPageTabs() {
- const history = useHistory()
- const panes = React.useMemo(
- () => [
- {menuItem: 'Global Feed', url: '/'},
- {menuItem: 'Your Feed', url: '/my-tracks'},
- ],
- []
- )
-
- const onTabChange = React.useCallback(
- (e, data) => {
- history.push(panes[data.activeIndex].url)
- },
- [history, panes]
- )
-
- const isFeedPage = useRouteMatch('/my-tracks')
- const activeIndex = isFeedPage ? 1 : 0
-
- return
-}
-
-function TrackList({path}) {
- const [page, setPage] = useQueryParam('page', 1)
-
- const privateFeed = path === '/my-tracks'
- const pageSize = 20
-
- const data = useObservable(
- (_$, inputs$) =>
- inputs$.pipe(
- map(([page, privateFeed]) => {
- const url = '/tracks' + (privateFeed ? '/feed' : '')
- const params = {limit: pageSize, offset: pageSize * (page - 1)}
- return {url, params}
- }),
- debounceTime(100),
- distinctUntilChanged(_.isEqual),
- switchMap((request) => concat(of(null), from(api.fetch(request.url + '?' + stringifyParams(request.params)))))
- ),
- null,
- [page, privateFeed]
- )
-
- const {tracks, trackCount} = data || {}
- const loading = !data
-
- const totalPages = trackCount / pageSize
-
- return (
-
-
- {!loading && totalPages > 1 &&
}
-
- {tracks && (
-
- {tracks.map((track) => (
- -
-
-
- {track.title}
-
- Created by {track.author.username} on {track.createdAt}
-
- {track.description}
-
- {track.visible ? (
- <>
- Public
- >
- ) : (
- <>
- Private
- >
- )}
-
-
-
- ))}
-
- )}
-
- )
-}
-
-function PublicTracksPage({login}) {
- return (
-
- {login ? : null}
-
-
- )
-}
-
-function OwnTracksPage({login}) {
- return (
-
- {login ? : null}
-
-
- )
-}
-
-function Track() {
- let {slug} = useParams()
- return Track {slug}
-}
+import {LoginPage, LogoutPage, NotFoundPage, TracksPage, TrackPage, HomePage} from './pages'
const App = connect((state) => ({login: state.login}))(function App({login}) {
// update the API header on each render, the App is rerendered when the login changes
@@ -139,10 +25,13 @@ const App = connect((state) => ({login: state.login}))(function App({login}) {