diff --git a/src/components/FormattedDate.tsx b/src/components/FormattedDate.tsx new file mode 100644 index 0000000..8278be1 --- /dev/null +++ b/src/components/FormattedDate.tsx @@ -0,0 +1,20 @@ +import {DateTime} from 'luxon' + +export default function FormattedDate({date, relative = false}) { + if (date == null) { + return null + } + + const dateTime = + typeof date === 'string' ? DateTime.fromISO(date) : date instanceof Date ? DateTime.fromJSDate(date) : date + + let str + + if (relative) { + str = dateTime.toRelative() + } else { + str = dateTime.toLocaleString(DateTime.DATETIME_MED) + } + + return {str} +} diff --git a/src/components/Map/index.js b/src/components/Map/index.js index 85bfc28..7b03c94 100644 --- a/src/components/Map/index.js +++ b/src/components/Map/index.js @@ -5,14 +5,20 @@ import OlView from 'ol/View' import OlTileLayer from 'ol/layer/Tile' import OlVectorLayer from 'ol/layer/Vector' import OlGroupLayer from 'ol/layer/Group' -import {fromLonLat} from 'ol/proj' import OSM from 'ol/source/OSM' +import proj4 from 'proj4'; +import {register} from 'ol/proj/proj4'; import OlLayerSwitcher from 'ol-layerswitcher' +// Import styles for open layers + addons import 'ol/ol.css' import "ol-layerswitcher/dist/ol-layerswitcher.css"; +// Prepare projection +proj4.defs('projLayer1', '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs'); +register(proj4); + const MapContext = React.createContext() const MapLayerContext = React.createContext() @@ -22,14 +28,7 @@ export function Map({children, ...props}) { const [map, setMap] = React.useState(null) React.useLayoutEffect(() => { - const map = new OlMap({ - target: ref.current, - // view: new View({ - // maxZoom: 22, - // center: fromLonLat([10, 51]), - // zoom: 5, - // }), - }) + const map = new OlMap({target: ref.current}) setMap(map) diff --git a/src/components/index.js b/src/components/index.js index b85aca9..42e6953 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -1,3 +1,4 @@ +export {default as FormattedDate} from './FormattedDate' export {default as LoginForm} from './LoginForm' export {default as Map} from './Map' export {default as Page} from './Page' diff --git a/src/index.js b/src/index.js index 81ce5d2..e7b71fc 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,5 @@ import React from 'react' +import {Settings} from 'luxon' import ReactDOM from 'react-dom' import 'semantic-ui-css/semantic.min.css' import './index.css' @@ -14,9 +15,13 @@ const enhancer = compose(persistState(['login'])) const store = createStore(rootReducer, undefined, enhancer) +// TODO: remove +Settings.defaultLocale = 'de-DE' + ReactDOM.render( , document.getElementById('root') ) + diff --git a/src/pages/TrackPage.tsx b/src/pages/TrackPage.tsx deleted file mode 100644 index 3d612dd..0000000 --- a/src/pages/TrackPage.tsx +++ /dev/null @@ -1,407 +0,0 @@ -import React from 'react' -import {connect} from 'react-redux' -import {Link} from 'react-router-dom' -import {Segment, Dimmer, Form, Button, List, Grid, Loader, Header, Comment} from 'semantic-ui-react' -import {useParams} from 'react-router-dom' -import {concat, combineLatest, of, from} from 'rxjs' -import {pluck, distinctUntilChanged, map, switchMap, startWith} from 'rxjs/operators' -import {useObservable} from 'rxjs-hooks' -import {Settings, DateTime, Duration} from 'luxon' - -import {Vector as VectorSource} from 'ol/source'; -import {Geometry, LineString, Point} from 'ol/geom'; -import Feature from 'ol/Feature'; -import {fromLonLat} from 'ol/proj'; -import proj4 from 'proj4'; -import {register} from 'ol/proj/proj4'; -import {Fill, Stroke, Style, Text, Circle} from 'ol/style'; - -import api from '../api' -import {Map, Page} from '../components' -import type {Track, TrackData, TrackComment} from '../types' - -proj4.defs('projLayer1', '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs'); -register(proj4); - -// TODO: remove -Settings.defaultLocale = 'de-DE' - -function formatDuration(seconds) { - return Duration.fromMillis((seconds ?? 0) * 1000).toFormat("h'h' mm'm'") -} - -function FormattedDate({date, relative = false}) { - if (date == null) { - return null - } - - const dateTime = - typeof date === 'string' ? DateTime.fromISO(date) : date instanceof Date ? DateTime.fromJSDate(date) : date - - let str - - if (relative) { - str = dateTime.toRelative() - } else { - str = dateTime.toLocaleString(DateTime.DATETIME_MED) - } - - return {str} -} - -function TrackDetails({track, isAuthor, trackData}) { - return ( - - {track.visible != null && isAuthor && ( - - Visibility - {track.visible ? 'Public' : 'Private'} - - )} - - {track.originalFileName != null && ( - - Original Filename - {track.originalFileName} - - )} - - {track.uploadedByUserAgent != null && ( - - Uploaded with - {track.uploadedByUserAgent} - - )} - - {track.duration == null && ( - - Duration - {formatDuration(track.duration || 1402)} - - )} - - {track.createdAt != null && ( - - Uploaded on - - - )} - - - - {trackData?.recordedAt != null && ( - - Recorded on - - - )} - - {trackData?.numEvents != null && ( - - Confirmed events - {trackData.numEvents} - - )} - - {trackData?.trackLength != null && ( - - Length - {(trackData.trackLength / 1000).toFixed(2)} km - - )} - - ) -} - -function TrackActions({slug}) { - return ( - - - - - - ) -} - -function TrackComments({comments, login, hideLoader}) { - return ( - - -
- Comments -
- - - - {comments?.map((comment: TrackComment) => ( - - - - {comment.author.username} - -
- -
-
- {comment.body} -
-
- ))} - - {login && comments != null && ( -
- - + + + ) +} diff --git a/src/pages/TrackPage/TrackComments.tsx b/src/pages/TrackPage/TrackComments.tsx new file mode 100644 index 0000000..4692af5 --- /dev/null +++ b/src/pages/TrackPage/TrackComments.tsx @@ -0,0 +1,40 @@ +import React from 'react' +import {Segment, Form, Button, Loader, Header, Comment} from 'semantic-ui-react' + +import {FormattedDate} from 'components' + +export default function TrackComments({comments, login, hideLoader}) { + return ( + + +
+ Comments +
+ + + + {comments?.map((comment: TrackComment) => ( + + + + {comment.author.username} + +
+ +
+
+ {comment.body} +
+
+ ))} + + {login && comments != null && ( +
+ +