mirror of
https://github.com/pds-nest/nest.git
synced 2024-11-21 12:34:19 +00:00
💥 Refactor some things to improve code quality
This commit is contained in:
parent
7a6e72c830
commit
bc2310f18e
11 changed files with 323 additions and 110 deletions
|
@ -11,6 +11,7 @@ module.exports = {
|
||||||
config.roots = config.roots.map(root => root.replace("src", "nest_frontend"))
|
config.roots = config.roots.map(root => root.replace("src", "nest_frontend"))
|
||||||
config.collectCoverageFrom = config.collectCoverageFrom.map(root => root.replace("src", "nest_frontend"))
|
config.collectCoverageFrom = config.collectCoverageFrom.map(root => root.replace("src", "nest_frontend"))
|
||||||
config.testMatch = config.testMatch.map(root => root.replace("src", "nest_frontend"))
|
config.testMatch = config.testMatch.map(root => root.replace("src", "nest_frontend"))
|
||||||
|
console.debug(config)
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
// Link.react.test.js
|
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import "@testing-library/jest-dom/extend-expect"
|
import "@testing-library/jest-dom/extend-expect"
|
||||||
import { render, screen } from "@testing-library/react"
|
import { render, screen } from "@testing-library/react"
|
||||||
|
|
92
nest_frontend/objects/Condition.js
Normal file
92
nest_frontend/objects/Condition.js
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
import { IconDefinition, faQuestionCircle } from "@fortawesome/free-solid-svg-icons"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Condition class for an undefined/unknown condition.
|
||||||
|
*
|
||||||
|
* See [the Condition spec](https://gitlab.steffo.eu/nest/g2-progetto/-/wikis/sprint-2/Specifica-delle-Conditions).
|
||||||
|
*/
|
||||||
|
export class Condition {
|
||||||
|
content
|
||||||
|
type
|
||||||
|
id
|
||||||
|
|
||||||
|
constructor(type, content, id = null) {
|
||||||
|
this.content = content
|
||||||
|
this.type = type
|
||||||
|
this.id = id
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the condition as an object readable by the backend.
|
||||||
|
*
|
||||||
|
* @returns {{id, type, content}}
|
||||||
|
*/
|
||||||
|
serialize() {
|
||||||
|
return {
|
||||||
|
type: this.type,
|
||||||
|
content: this.content,
|
||||||
|
id: this.id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display parameters for the badge representing this condition.
|
||||||
|
*
|
||||||
|
* @returns {{color: string, icon: IconDefinition, title, content}}
|
||||||
|
*/
|
||||||
|
display() {
|
||||||
|
return {
|
||||||
|
color: "Grey",
|
||||||
|
icon: faQuestionCircle,
|
||||||
|
title: this.id,
|
||||||
|
content: this.content,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Require a tweet to contain a specific hashtag to be gathered.
|
||||||
|
*/
|
||||||
|
export class ConditionHashtag extends Condition {
|
||||||
|
constructor(hashtag, id = null) {
|
||||||
|
super(0, hashtag, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Require a tweet to be posted by a certain user to be gathered.
|
||||||
|
*/
|
||||||
|
export class ConditionUser extends Condition {
|
||||||
|
constructor(user, id = null) {
|
||||||
|
super(5, user, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Require a tweet to be posted before or after a certain time to be gathered.
|
||||||
|
*/
|
||||||
|
export class ConditionTime extends Condition {
|
||||||
|
timeRay
|
||||||
|
|
||||||
|
constructor(timeRay, id = null) {
|
||||||
|
super(2, timeRay.toString(), id)
|
||||||
|
this.timeRay = timeRay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Require a tweet to have coordinates associated and to be posted within the {@link MapArea}.
|
||||||
|
*/
|
||||||
|
export class ConditionLocation extends Condition {
|
||||||
|
mapArea
|
||||||
|
|
||||||
|
constructor(mapArea, id = null) {
|
||||||
|
super(3, mapArea.toString(), id)
|
||||||
|
this.mapArea = mapArea
|
||||||
|
}
|
||||||
|
}
|
56
nest_frontend/objects/Condition.test.js
Normal file
56
nest_frontend/objects/Condition.test.js
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import "@testing-library/jest-dom/extend-expect"
|
||||||
|
import { Condition, ConditionHashtag, ConditionLocation, ConditionTime, ConditionUser } from "./Condition"
|
||||||
|
import TimeRay from "./TimeRay"
|
||||||
|
import MapArea from "./MapArea"
|
||||||
|
|
||||||
|
|
||||||
|
test("Condition can be constructed", () => {
|
||||||
|
expect(new Condition(0, "hi")).toBeTruthy()
|
||||||
|
expect(new Condition(0, "hi", 1)).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("ConditionHashtag can be constructed", () => {
|
||||||
|
expect(new ConditionHashtag("PdS2021")).toBeTruthy()
|
||||||
|
expect(new ConditionHashtag("PdS2021", 1)).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("ConditionUser can be constructed", () => {
|
||||||
|
expect(new ConditionUser("USteffo")).toBeTruthy()
|
||||||
|
expect(new ConditionUser("USteffo", 1)).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("ConditionTime can be constructed", () => {
|
||||||
|
const now = new Date()
|
||||||
|
const timeRay = new TimeRay(true, now)
|
||||||
|
|
||||||
|
expect(new ConditionTime(timeRay)).toBeTruthy()
|
||||||
|
expect(new ConditionTime(timeRay, 1)).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("ConditionLocation can be constructed", () => {
|
||||||
|
const mapArea = new MapArea(1000, 0.000, 0.000)
|
||||||
|
|
||||||
|
expect(new ConditionLocation(mapArea)).toBeTruthy()
|
||||||
|
expect(new ConditionLocation(mapArea, 1)).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("ConditionHashtag has the correct type", () => {
|
||||||
|
expect(new ConditionHashtag("PdS2021").type).toBe(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("ConditionUser has the correct type", () => {
|
||||||
|
expect(new ConditionUser("USteffo").type).toBe(5)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("ConditionTime has the correct type", () => {
|
||||||
|
const now = new Date()
|
||||||
|
const timeRay = new TimeRay(true, now)
|
||||||
|
|
||||||
|
expect(new ConditionTime(timeRay).type).toBe(5)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("ConditionLocation has the correct type", () => {
|
||||||
|
const mapArea = new MapArea(1000, 0.000, 0.000)
|
||||||
|
|
||||||
|
expect(new ConditionLocation(mapArea).type).toBe(3)
|
||||||
|
})
|
104
nest_frontend/objects/Errors.js
Normal file
104
nest_frontend/objects/Errors.js
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/**
|
||||||
|
* Error thrown when a function is not implemented in the current class/instance.
|
||||||
|
*/
|
||||||
|
class NotImplementedError {
|
||||||
|
name
|
||||||
|
|
||||||
|
constructor(name) {
|
||||||
|
this.name = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An error in the N.E.S.T. frontend-backend communication.
|
||||||
|
*/
|
||||||
|
class BackendCommunicationError {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error thrown when trying to access a backend view which doesn't exist or isn't allowed in the used hook.
|
||||||
|
*/
|
||||||
|
class ViewNotAllowedError extends BackendCommunicationError {
|
||||||
|
view
|
||||||
|
|
||||||
|
constructor(view) {
|
||||||
|
super()
|
||||||
|
|
||||||
|
this.view = view
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error thrown when trying to access a backend view when outside a {@link ContextServer}.
|
||||||
|
*/
|
||||||
|
class ServerNotConfiguredError extends BackendCommunicationError {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error thrown when trying to access a backend view while another access is ongoing.
|
||||||
|
*
|
||||||
|
* This is not allowed due to potential race conditions.
|
||||||
|
*/
|
||||||
|
class FetchAlreadyRunningError extends BackendCommunicationError {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract class for {@link DecodeError} and {@link ResultError}.
|
||||||
|
*/
|
||||||
|
class FetchError extends BackendCommunicationError {
|
||||||
|
status
|
||||||
|
statusText
|
||||||
|
|
||||||
|
constructor(status, statusText) {
|
||||||
|
super()
|
||||||
|
|
||||||
|
this.status = status
|
||||||
|
this.statusText = statusText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error thrown when the frontend can't parse the data received from the backend.
|
||||||
|
*/
|
||||||
|
class DecodeError extends FetchError {
|
||||||
|
error
|
||||||
|
|
||||||
|
constructor(status, statusText, error) {
|
||||||
|
super(status, statusText)
|
||||||
|
|
||||||
|
this.error = error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error thrown when the backend returns a falsy `"result"` value.
|
||||||
|
*/
|
||||||
|
class ResultError extends FetchError {
|
||||||
|
status
|
||||||
|
statusText
|
||||||
|
data
|
||||||
|
|
||||||
|
constructor(status, statusText, data) {
|
||||||
|
super(status, statusText)
|
||||||
|
|
||||||
|
this.data = data
|
||||||
|
}
|
||||||
|
|
||||||
|
getMsg() {
|
||||||
|
return this.data.msg
|
||||||
|
}
|
||||||
|
|
||||||
|
getCode() {
|
||||||
|
return this.data.code
|
||||||
|
}
|
||||||
|
}
|
34
nest_frontend/objects/MapArea.js
Normal file
34
nest_frontend/objects/MapArea.js
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* An area on a map, defined by a latitude `lat`, a longitude `lng` and a radius `rad` in meters.
|
||||||
|
*/
|
||||||
|
export default class MapArea {
|
||||||
|
/**
|
||||||
|
* @param rad - Radius of the area in meters.
|
||||||
|
* @param lat - Latitude of the center of the radius.
|
||||||
|
* @param lng - Longitude of the center of the radius.
|
||||||
|
*/
|
||||||
|
constructor(rad, lat, lng) {
|
||||||
|
this.rad = rad
|
||||||
|
this.lat = lat
|
||||||
|
this.lng = lng
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
toString() {
|
||||||
|
return `${this.rad} ${this.lat.toFixed(7)} ${this.lng.toFixed(7)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the MapArea as an human-readable string.
|
||||||
|
*
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
toHumanString() {
|
||||||
|
if(this.rad >= 2000) {
|
||||||
|
const kmRadius = Math.round(this.rad / 1000)
|
||||||
|
return `${kmRadius}km ${this.lat.toFixed(3)} ${this.lng.toFixed(3)}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
nest_frontend/objects/TimeRay.js
Normal file
24
nest_frontend/objects/TimeRay.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/**
|
||||||
|
* An half-line of time, defined by a `date` and a boolean `isBefore` indicating if the time before or after the
|
||||||
|
* specified date should be selected.
|
||||||
|
*/
|
||||||
|
export default class TimeRay {
|
||||||
|
isBefore
|
||||||
|
date
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param isBefore - `true` to select times earlier than the date, `false` to select times after the date.
|
||||||
|
* @param date - The date to start measurements from.
|
||||||
|
*/
|
||||||
|
constructor(isBefore, date) {
|
||||||
|
this.isBefore = isBefore
|
||||||
|
this.date = date
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
toString() {
|
||||||
|
return `${this.isBefore ? "<" : ">"} ${this.date.toISOString()}`
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,40 +0,0 @@
|
||||||
import isString from "is-string"
|
|
||||||
|
|
||||||
|
|
||||||
const typeEnums = {
|
|
||||||
"HASHTAG": 0,
|
|
||||||
"TIME": 2,
|
|
||||||
"COORDINATES": 3,
|
|
||||||
"PLACE": 4,
|
|
||||||
"USER": 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A search/filtering Condition.
|
|
||||||
*
|
|
||||||
* See https://gitlab.steffo.eu/nest/g2-progetto/-/wikis/Specifica-delle-Conditions .
|
|
||||||
*/
|
|
||||||
export default class Condition {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new Condition.
|
|
||||||
*
|
|
||||||
* @param type - The type of Condition to create.
|
|
||||||
* It can be a number or one of the following strings:
|
|
||||||
* `"hashtag"`, `"time"`, `"coordinates"`, `"place"`.
|
|
||||||
* @param content - The content of the Condition.
|
|
||||||
* @param id - The id of the Condition on the backend, or null if the Condition hasn't been committed yet.
|
|
||||||
*/
|
|
||||||
constructor(type, content, id = null) {
|
|
||||||
if(isString(type)) {
|
|
||||||
this.type = typeEnums[type.toUpperCase()]
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.type = type
|
|
||||||
}
|
|
||||||
|
|
||||||
this.content = content
|
|
||||||
this.id = id
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
class NestError {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class ViewNotAllowedError extends NestError {
|
|
||||||
view
|
|
||||||
|
|
||||||
constructor(view) {
|
|
||||||
super()
|
|
||||||
|
|
||||||
this.view = view
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class ServerNotConfiguredError extends NestError {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class FetchAlreadyRunningError extends NestError {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class FetchError extends NestError {
|
|
||||||
status
|
|
||||||
statusText
|
|
||||||
|
|
||||||
constructor(status, statusText) {
|
|
||||||
super()
|
|
||||||
|
|
||||||
this.status = status
|
|
||||||
this.statusText = statusText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class DecodeError extends FetchError {
|
|
||||||
error
|
|
||||||
|
|
||||||
constructor(status, statusText, error) {
|
|
||||||
super(status, statusText)
|
|
||||||
|
|
||||||
this.error = error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class ResultError extends FetchError {
|
|
||||||
status
|
|
||||||
statusText
|
|
||||||
data
|
|
||||||
|
|
||||||
constructor(status, statusText, data) {
|
|
||||||
super(status, statusText)
|
|
||||||
|
|
||||||
this.data = data
|
|
||||||
}
|
|
||||||
|
|
||||||
getMsg() {
|
|
||||||
return this.data.msg
|
|
||||||
}
|
|
||||||
|
|
||||||
getCode() {
|
|
||||||
return this.data.code
|
|
||||||
}
|
|
||||||
}
|
|
11
package-lock.json
generated
11
package-lock.json
generated
|
@ -20,6 +20,7 @@
|
||||||
"@testing-library/user-event": "^12.8.3",
|
"@testing-library/user-event": "^12.8.3",
|
||||||
"chart.js": "^3.2.1",
|
"chart.js": "^3.2.1",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
|
"geolib": "^3.3.1",
|
||||||
"is-string": "^1.0.5",
|
"is-string": "^1.0.5",
|
||||||
"leaflet": "^1.7.1",
|
"leaflet": "^1.7.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
|
@ -9416,6 +9417,11 @@
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/geolib": {
|
||||||
|
"version": "3.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/geolib/-/geolib-3.3.1.tgz",
|
||||||
|
"integrity": "sha512-sfahBXFcgELdpumDZV5b3KWiINkZxC5myAkLk067UUcTmTXaiE9SWmxMEHztn/Eus4JX6kesHxaIuZlniYgUtg=="
|
||||||
|
},
|
||||||
"node_modules/get-caller-file": {
|
"node_modules/get-caller-file": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||||
|
@ -30086,6 +30092,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
||||||
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="
|
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="
|
||||||
},
|
},
|
||||||
|
"geolib": {
|
||||||
|
"version": "3.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/geolib/-/geolib-3.3.1.tgz",
|
||||||
|
"integrity": "sha512-sfahBXFcgELdpumDZV5b3KWiINkZxC5myAkLk067UUcTmTXaiE9SWmxMEHztn/Eus4JX6kesHxaIuZlniYgUtg=="
|
||||||
|
},
|
||||||
"get-caller-file": {
|
"get-caller-file": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
"@testing-library/user-event": "^12.8.3",
|
"@testing-library/user-event": "^12.8.3",
|
||||||
"chart.js": "^3.2.1",
|
"chart.js": "^3.2.1",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
|
"geolib": "^3.3.1",
|
||||||
"is-string": "^1.0.5",
|
"is-string": "^1.0.5",
|
||||||
"leaflet": "^1.7.1",
|
"leaflet": "^1.7.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
|
|
Loading…
Reference in a new issue