From ec2d5bcf776a6494fbbf4ca6caab1fef12499d90 Mon Sep 17 00:00:00 2001 From: Paul Bienkowski Date: Sun, 14 Feb 2021 17:18:57 +0100 Subject: [PATCH] Track page --- package-lock.json | 162 ++++++++++++++++++++++++++ package.json | 4 + src/App.js | 144 +++-------------------- src/components/LoginForm.js | 58 +++++++++ src/components/Map/index.js | 62 ++++++++++ src/components/index.js | 2 + src/pages/HomePage.js | 118 +++++++++++++++++++ src/pages/LoginPage.js | 53 +-------- src/pages/TrackPage.tsx | 226 ++++++++++++++++++++++++++++++++++++ src/pages/TracksPage.tsx | 115 ++++++++++++++++++ src/pages/index.js | 3 + src/query.ts | 3 +- src/types.ts | 45 +++++++ 13 files changed, 819 insertions(+), 176 deletions(-) create mode 100644 src/components/LoginForm.js create mode 100644 src/components/Map/index.js create mode 100644 src/pages/HomePage.js create mode 100644 src/pages/TrackPage.tsx create mode 100644 src/pages/TracksPage.tsx create mode 100644 src/types.ts 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}) {