mirror of
https://github.com/pds-nest/nest.git
synced 2024-11-25 14:34:19 +00:00
💥 Fix bugs, refactor things, document stuff
This commit is contained in:
parent
ac1a218677
commit
2870a46726
15 changed files with 57 additions and 31 deletions
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
.Button[disabled] {
|
.Button[disabled] {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
|
|
||||||
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Button:focus-visible {
|
.Button:focus-visible {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { useCallback, useContext } from "react"
|
import React, { useCallback, useContext } from "react"
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import { faLocationArrow, faMapPin, faPlus } from "@fortawesome/free-solid-svg-icons"
|
import { faLocationArrow, faPlus } from "@fortawesome/free-solid-svg-icons"
|
||||||
import ButtonIconOnly from "../base/ButtonIconOnly"
|
import ButtonIconOnly from "../base/ButtonIconOnly"
|
||||||
import useRepositoryEditor from "../../hooks/useRepositoryEditor"
|
import useRepositoryEditor from "../../hooks/useRepositoryEditor"
|
||||||
import ContextLanguage from "../../contexts/ContextLanguage"
|
import ContextLanguage from "../../contexts/ContextLanguage"
|
||||||
|
|
|
@ -20,7 +20,7 @@ export default function BoxFilterDatetime({ ...props }) {
|
||||||
const strings = useStrings()
|
const strings = useStrings()
|
||||||
const { appendFilter } = useRepositoryViewer()
|
const { appendFilter } = useRepositoryViewer()
|
||||||
|
|
||||||
const submit = ({ timeRay }) => {
|
const submit = (timeRay) => {
|
||||||
appendFilter(new FilterInsideTimeRay(timeRay))
|
appendFilter(new FilterInsideTimeRay(timeRay))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import FormInline from "../base/FormInline"
|
||||||
import useRepositoryViewer from "../../hooks/useRepositoryViewer"
|
import useRepositoryViewer from "../../hooks/useRepositoryViewer"
|
||||||
import useStrings from "../../hooks/useStrings"
|
import useStrings from "../../hooks/useStrings"
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import { faLocationArrow, faPlus } from "@fortawesome/free-solid-svg-icons"
|
import { faLocationArrow, faMapMarkerAlt, faPlus } from "@fortawesome/free-solid-svg-icons"
|
||||||
import { FilterWithPlace } from "../../objects/Filter"
|
import { FilterWithPlace } from "../../objects/Filter"
|
||||||
import ButtonIconOnly from "../base/ButtonIconOnly"
|
import ButtonIconOnly from "../base/ButtonIconOnly"
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ export default function BoxFilterHasPlace({ ...props }) {
|
||||||
<span>
|
<span>
|
||||||
{strings.searchBy}
|
{strings.searchBy}
|
||||||
|
|
||||||
<FontAwesomeIcon icon={faLocationArrow}/>
|
<FontAwesomeIcon icon={faMapMarkerAlt}/>
|
||||||
|
|
||||||
{strings.byHasPlace}
|
{strings.byHasPlace}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import BoxFull from "../base/BoxFull"
|
import BoxFull from "../base/BoxFull"
|
||||||
import { faClock } from "@fortawesome/free-solid-svg-icons"
|
import { faClock, faHashtag } from "@fortawesome/free-solid-svg-icons"
|
||||||
import useRepositoryViewer from "../../hooks/useRepositoryViewer"
|
import useRepositoryViewer from "../../hooks/useRepositoryViewer"
|
||||||
import useStrings from "../../hooks/useStrings"
|
import useStrings from "../../hooks/useStrings"
|
||||||
import { FilterHashtag } from "../../objects/Filter"
|
import { FilterHashtag } from "../../objects/Filter"
|
||||||
|
@ -30,9 +30,9 @@ export default function BoxFilterHashtag({ ...props }) {
|
||||||
<span>
|
<span>
|
||||||
{strings.searchBy}
|
{strings.searchBy}
|
||||||
|
|
||||||
<FontAwesomeIcon icon={faClock}/>
|
<FontAwesomeIcon icon={faHashtag}/>
|
||||||
|
|
||||||
{strings.byTimePeriod}
|
{strings.byHashtag}
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import BoxFull from "../base/BoxFull"
|
||||||
import useRepositoryViewer from "../../hooks/useRepositoryViewer"
|
import useRepositoryViewer from "../../hooks/useRepositoryViewer"
|
||||||
import useStrings from "../../hooks/useStrings"
|
import useStrings from "../../hooks/useStrings"
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||||
import { faMapPin } from "@fortawesome/free-solid-svg-icons"
|
import { faLocationArrow, faMapPin } from "@fortawesome/free-solid-svg-icons"
|
||||||
import FormInlineLocation from "./FormInlineLocation"
|
import FormInlineLocation from "./FormInlineLocation"
|
||||||
import { FilterInsideMapArea } from "../../objects/Filter"
|
import { FilterInsideMapArea } from "../../objects/Filter"
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ import { FilterInsideMapArea } from "../../objects/Filter"
|
||||||
*
|
*
|
||||||
* It connects to the `mapViewHook` of the RepositoryViewer.
|
* It connects to the `mapViewHook` of the RepositoryViewer.
|
||||||
*
|
*
|
||||||
|
* @deprecated to be refactored
|
||||||
* @param props - Additional props to pass to the box.
|
* @param props - Additional props to pass to the box.
|
||||||
* @returns {JSX.Element}
|
* @returns {JSX.Element}
|
||||||
* @constructor
|
* @constructor
|
||||||
|
@ -23,7 +24,7 @@ export default function BoxFilterLocation({ ...props }) {
|
||||||
const { appendFilter, mapViewHook } = useRepositoryViewer()
|
const { appendFilter, mapViewHook } = useRepositoryViewer()
|
||||||
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
appendFilter(new FilterInsideMapArea(false, mapViewHook.center, mapViewHook.radius))
|
appendFilter(new FilterInsideMapArea(mapViewHook.mapArea))
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -32,7 +33,7 @@ export default function BoxFilterLocation({ ...props }) {
|
||||||
<span>
|
<span>
|
||||||
{strings.searchBy}
|
{strings.searchBy}
|
||||||
|
|
||||||
<FontAwesomeIcon icon={faMapPin}/>
|
<FontAwesomeIcon icon={faLocationArrow}/>
|
||||||
|
|
||||||
{strings.byZone}
|
{strings.byZone}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, { useContext, useMemo } from "react"
|
||||||
import BoxMap from "../base/BoxMap"
|
import BoxMap from "../base/BoxMap"
|
||||||
import ContextLanguage from "../../contexts/ContextLanguage"
|
import ContextLanguage from "../../contexts/ContextLanguage"
|
||||||
import { Marker, Popup } from "react-leaflet"
|
import { Marker, Popup } from "react-leaflet"
|
||||||
import { Location } from "../../objects/location"
|
import Coordinates from "../../objects/Coordinates"
|
||||||
import ContextRepositoryViewer from "../../contexts/ContextRepositoryViewer"
|
import ContextRepositoryViewer from "../../contexts/ContextRepositoryViewer"
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,10 +20,12 @@ export default function BoxVisualizationMap({ ...props }) {
|
||||||
const markers = useMemo(
|
const markers = useMemo(
|
||||||
() => {
|
() => {
|
||||||
return tweets.filter(tweet => tweet.location).map(tweet => {
|
return tweets.filter(tweet => tweet.location).map(tweet => {
|
||||||
const location = Location.fromTweet(tweet)
|
if(!tweet.location) return null
|
||||||
|
|
||||||
|
const coords = Coordinates.fromCrawlerString(tweet.location)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Marker key={tweet["snowflake"]} position={location.toArray()}>
|
<Marker key={tweet["snowflake"]} position={coords.toLatLng()}>
|
||||||
<Popup>
|
<Popup>
|
||||||
<p>
|
<p>
|
||||||
{tweet["content"]}
|
{tweet["content"]}
|
||||||
|
|
|
@ -11,12 +11,11 @@ const INVALID_CHARACTERS = /([^a-z0-9_\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u00ff\u0
|
||||||
/**
|
/**
|
||||||
* A {@link FormInline} allowing the user to select a Twitter hashtag.
|
* A {@link FormInline} allowing the user to select a Twitter hashtag.
|
||||||
*
|
*
|
||||||
* @param submit - Function <string> called when the submit button is pressed.
|
|
||||||
* @param props - Additional props to pass to the form.
|
* @param props - Additional props to pass to the form.
|
||||||
* @returns {JSX.Element}
|
* @returns {JSX.Element}
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
export default function FormInlineHashtag({ submit, ...props }) {
|
export default function FormInlineHashtag({ ...props }) {
|
||||||
|
|
||||||
const validate = value => {
|
const validate = value => {
|
||||||
return value.replace(INVALID_CHARACTERS, "")
|
return value.replace(INVALID_CHARACTERS, "")
|
||||||
|
@ -27,7 +26,6 @@ export default function FormInlineHashtag({ submit, ...props }) {
|
||||||
textIcon={faHashtag}
|
textIcon={faHashtag}
|
||||||
placeholder={"hashtag"}
|
placeholder={"hashtag"}
|
||||||
validate={validate}
|
validate={validate}
|
||||||
submit={submit}
|
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
|
@ -47,21 +47,21 @@ export default function FormInlineLocation(
|
||||||
className={Style.Radius}
|
className={Style.Radius}
|
||||||
type={"text"}
|
type={"text"}
|
||||||
icon={radIcon}
|
icon={radIcon}
|
||||||
value={`${mapViewHook.radius} m`}
|
value={`${Math.round(mapViewHook.mapArea.radius / 1000)} km`}
|
||||||
disabled={true}
|
disabled={true}
|
||||||
/>
|
/>
|
||||||
<InputWithIcon
|
<InputWithIcon
|
||||||
className={Style.Latitude}
|
className={Style.Latitude}
|
||||||
type={"text"}
|
type={"text"}
|
||||||
icon={latIcon}
|
icon={latIcon}
|
||||||
value={mapViewHook.center.lat.toFixed(3)}
|
value={mapViewHook.mapArea.center.lat.toFixed(3)}
|
||||||
disabled={true}
|
disabled={true}
|
||||||
/>
|
/>
|
||||||
<InputWithIcon
|
<InputWithIcon
|
||||||
className={Style.Longitude}
|
className={Style.Longitude}
|
||||||
type={"text"}
|
type={"text"}
|
||||||
icon={lngIcon}
|
icon={lngIcon}
|
||||||
value={mapViewHook.center.lng.toFixed(3)}
|
value={mapViewHook.mapArea.center.lng.toFixed(3)}
|
||||||
disabled={true}
|
disabled={true}
|
||||||
/>
|
/>
|
||||||
<ButtonIconOnly
|
<ButtonIconOnly
|
||||||
|
|
|
@ -34,6 +34,7 @@ export default function FormInlineText(
|
||||||
|
|
||||||
const _onSubmit = event => {
|
const _onSubmit = event => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
if(!value) return
|
||||||
submit(value)
|
submit(value)
|
||||||
setValue("")
|
setValue("")
|
||||||
}
|
}
|
||||||
|
@ -56,6 +57,7 @@ export default function FormInlineText(
|
||||||
icon={buttonIcon}
|
icon={buttonIcon}
|
||||||
color={buttonColor}
|
color={buttonColor}
|
||||||
onClick={_onSubmit}
|
onClick={_onSubmit}
|
||||||
|
disabled={!value}
|
||||||
/>
|
/>
|
||||||
</FormInline>
|
</FormInline>
|
||||||
)
|
)
|
||||||
|
|
|
@ -8,7 +8,7 @@ import ButtonToggleBeforeAfter from "./ButtonToggleBeforeAfter"
|
||||||
import TimeRay from "../../objects/TimeRay"
|
import TimeRay from "../../objects/TimeRay"
|
||||||
|
|
||||||
|
|
||||||
const INVALID_CHARACTERS = /[^0-9TZ:+-]/g
|
const INVALID_CHARACTERS = /[^0-9TZ:+.-]/g
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,12 +40,14 @@ export default function FormInlineTimeRay(
|
||||||
|
|
||||||
const _onSubmit = event => {
|
const _onSubmit = event => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
if(!value) return
|
||||||
|
console.debug(value)
|
||||||
submit(new TimeRay(isBefore, new Date(value)))
|
submit(new TimeRay(isBefore, new Date(value)))
|
||||||
setValue("")
|
setValue("")
|
||||||
}
|
}
|
||||||
|
|
||||||
const _onChange = event => {
|
const _onChange = event => {
|
||||||
setValue(validate(event.target.value.replace(INVALID_CHARACTERS, "")))
|
setValue(validate(event.target.value.toUpperCase().replace(INVALID_CHARACTERS, "")))
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -67,6 +69,7 @@ export default function FormInlineTimeRay(
|
||||||
icon={buttonIcon}
|
icon={buttonIcon}
|
||||||
color={buttonColor}
|
color={buttonColor}
|
||||||
onClick={_onSubmit}
|
onClick={_onSubmit}
|
||||||
|
disabled={!value}
|
||||||
/>
|
/>
|
||||||
</FormInline>
|
</FormInline>
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,12 +9,11 @@ const INVALID_CHARACTERS = /[^a-zA-Z0-9]/g
|
||||||
/**
|
/**
|
||||||
* A {@link FormInline} allowing the user to select a Twitter user.
|
* A {@link FormInline} allowing the user to select a Twitter user.
|
||||||
*
|
*
|
||||||
* @param submit - Function <string> called when the submit button is pressed.
|
|
||||||
* @param props - Additional props to pass to the form.
|
* @param props - Additional props to pass to the form.
|
||||||
* @returns {JSX.Element}
|
* @returns {JSX.Element}
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
export default function FormInlineUser({ submit, ...props }) {
|
export default function FormInlineUser({ ...props }) {
|
||||||
|
|
||||||
const validate = value => {
|
const validate = value => {
|
||||||
return value.replace(INVALID_CHARACTERS, "")
|
return value.replace(INVALID_CHARACTERS, "")
|
||||||
|
@ -25,7 +24,6 @@ export default function FormInlineUser({ submit, ...props }) {
|
||||||
textIcon={faAt}
|
textIcon={faAt}
|
||||||
placeholder={"jack"}
|
placeholder={"jack"}
|
||||||
validate={validate}
|
validate={validate}
|
||||||
submit={submit}
|
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
import React, { useContext } from "react"
|
import React, { useContext } from "react"
|
||||||
import ButtonIconOnly from "../base/ButtonIconOnly"
|
import ButtonIconOnly from "../base/ButtonIconOnly"
|
||||||
import { faAt, faClock, faFont, faHashtag, faLocationArrow, faMapPin } from "@fortawesome/free-solid-svg-icons"
|
import {
|
||||||
|
faAt,
|
||||||
|
faClock,
|
||||||
|
faFont,
|
||||||
|
faHashtag,
|
||||||
|
faLocationArrow,
|
||||||
|
faMapMarkerAlt,
|
||||||
|
faMapPin,
|
||||||
|
} from "@fortawesome/free-solid-svg-icons"
|
||||||
import ButtonPicker from "./ButtonPicker"
|
import ButtonPicker from "./ButtonPicker"
|
||||||
import ContextRepositoryViewer from "../../contexts/ContextRepositoryViewer"
|
import ContextRepositoryViewer from "../../contexts/ContextRepositoryViewer"
|
||||||
|
|
||||||
|
@ -45,7 +53,7 @@ export default function PickerFilter({ ...props }) {
|
||||||
currentTab={filterTab}
|
currentTab={filterTab}
|
||||||
setTab={setFilterTab}
|
setTab={setFilterTab}
|
||||||
name={"place"}
|
name={"place"}
|
||||||
icon={faLocationArrow}
|
icon={faMapMarkerAlt}
|
||||||
/>
|
/>
|
||||||
<ButtonIconOnly
|
<ButtonIconOnly
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -54,7 +62,7 @@ export default function PickerFilter({ ...props }) {
|
||||||
}}
|
}}
|
||||||
disabled={filterTab === "location"}
|
disabled={filterTab === "location"}
|
||||||
color={"Grey"}
|
color={"Grey"}
|
||||||
icon={faMapPin}
|
icon={faLocationArrow}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
/**
|
/**
|
||||||
* A pair of coordinates, latitude `lat` and longitude `lng`.
|
* A pair of coordinates, latitude `lat` and longitude `lng`.
|
||||||
*/
|
*/
|
||||||
|
import { LatLng } from "leaflet/dist/leaflet-src.esm"
|
||||||
|
|
||||||
|
|
||||||
export default class Coordinates {
|
export default class Coordinates {
|
||||||
lat
|
lat
|
||||||
lng
|
lng
|
||||||
|
@ -25,7 +28,7 @@ export default class Coordinates {
|
||||||
if(!match) {
|
if(!match) {
|
||||||
throw new Error(`Invalid location string: ${str}`)
|
throw new Error(`Invalid location string: ${str}`)
|
||||||
}
|
}
|
||||||
return new Coordinates(match[0], match[1])
|
return new Coordinates(match[1], match[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,4 +65,13 @@ export default class Coordinates {
|
||||||
toArray() {
|
toArray() {
|
||||||
return [this.lat, this.lng]
|
return [this.lat, this.lng]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform this object in a {@link LatLng} / Leaflet compatible-one.
|
||||||
|
*
|
||||||
|
* @returns {LatLng}
|
||||||
|
*/
|
||||||
|
toLatLng() {
|
||||||
|
return new LatLng(this.lat, this.lng)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,9 +59,9 @@ export class Filter {
|
||||||
export class FilterContains extends Filter {
|
export class FilterContains extends Filter {
|
||||||
string
|
string
|
||||||
|
|
||||||
constructor(word, negate = false) {
|
constructor(string, negate = false) {
|
||||||
super(negate)
|
super(negate)
|
||||||
this.string = word.toLowerCase().trim()
|
this.string = string.toLowerCase().trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
check(tweet) {
|
check(tweet) {
|
||||||
|
@ -85,7 +85,7 @@ export class FilterHashtag extends FilterContains {
|
||||||
hashtag
|
hashtag
|
||||||
|
|
||||||
constructor(hashtag, negate = false) {
|
constructor(hashtag, negate = false) {
|
||||||
super(negate, `#${hashtag}`)
|
super(`#${hashtag}`, negate)
|
||||||
this.hashtag = hashtag
|
this.hashtag = hashtag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue