@nsidc/snow-today-webapp 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/deploy/deploy +34 -0
- package/doc/releasing.md +14 -0
- package/docker-compose.live.yml +2 -2
- package/docker-compose.yml +0 -10
- package/package.json +2 -2
- package/src/components/LinePlot.tsx +28 -7
- package/src/constants/dataServer.ts +1 -1
- package/src/serverState/plotData.ts +1 -0
- package/src/serverState/regionShape.ts +1 -0
- package/src/serverState/regionsIndex.ts +1 -0
- package/src/serverState/variablesIndex.ts +1 -0
- package/src/types/query/plotData.ts +7 -7
- package/webpack.config.js +3 -0
- package/nginx/default.dataserver.conf +0 -25
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# v0.3.0 (2022-08-22)
|
|
2
|
+
|
|
3
|
+
* Add automated deployment script
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# v0.2.0 (2022-08-22)
|
|
7
|
+
|
|
8
|
+
* Use QA data server URL
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# v0.1.1 (2022-08-22)
|
|
12
|
+
|
|
13
|
+
* Fix bug with data "leaking" between variables in the plot.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# v0.1.0 (2022-08-18)
|
|
17
|
+
|
|
18
|
+
* Initial release
|
package/deploy/deploy
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ENVIRONMENT="$1"
|
|
5
|
+
|
|
6
|
+
THIS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
|
+
REPO_ROOT_DIR="$(dirname "$THIS_DIR")"
|
|
8
|
+
|
|
9
|
+
VERSION_FILE="$REPO_ROOT_DIR/package.json"
|
|
10
|
+
CANONICAL_VERSION="$(cat "$VERSION_FILE" | jq -r .version)"
|
|
11
|
+
|
|
12
|
+
source /etc/profile.d/envvars.sh
|
|
13
|
+
|
|
14
|
+
cd "$REPO_ROOT_DIR"
|
|
15
|
+
|
|
16
|
+
if [ "$ENVIRONMENT" = "integration" ]; then
|
|
17
|
+
APP_VERSION="latest"
|
|
18
|
+
version_desc="latest"
|
|
19
|
+
else
|
|
20
|
+
APP_VERSION="$CANONICAL_VERSION"
|
|
21
|
+
version_desc="production"
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
echo "Using $version_desc versions in $ENVIRONMENT..."
|
|
25
|
+
echo "APP_VERSION=$APP_VERSION"
|
|
26
|
+
export APP_VERSION
|
|
27
|
+
|
|
28
|
+
# Replace the current app
|
|
29
|
+
docker-compose pull
|
|
30
|
+
docker-compose down --remove-orphans
|
|
31
|
+
docker-compose up -d
|
|
32
|
+
|
|
33
|
+
# Cleanup
|
|
34
|
+
docker system prune -af
|
package/doc/releasing.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Releasing
|
|
2
|
+
|
|
3
|
+
The `latest` image on Dockerhub will be updated with each commit to `main`.
|
|
4
|
+
|
|
5
|
+
To release a new tagged image to DockerHub and a new version to NPM:
|
|
6
|
+
|
|
7
|
+
* Update version in `package.json`.
|
|
8
|
+
* Run `npm i` to update `package-lock.json`.
|
|
9
|
+
* Update `CHANGELOG.md` following existing convention.
|
|
10
|
+
* Commit
|
|
11
|
+
* Merge to main if necessary
|
|
12
|
+
* Tag the main branch: `git tag vX.Y.Z`
|
|
13
|
+
* Push the tag to GitHub to trigger automated releases of Docker Images and NPM bundle:
|
|
14
|
+
`git push origin vX.Y.Z`
|
package/docker-compose.live.yml
CHANGED
package/docker-compose.yml
CHANGED
|
@@ -5,17 +5,7 @@ version: '3.4'
|
|
|
5
5
|
services:
|
|
6
6
|
webapp:
|
|
7
7
|
image: "nsidc/snow-today-webapp:${APP_VERSION:-latest}"
|
|
8
|
-
# TODO: Pull, don't build in non-dev
|
|
9
|
-
build: .
|
|
10
8
|
logging:
|
|
11
9
|
options:
|
|
12
10
|
max-size: "10m"
|
|
13
11
|
max-file: "10"
|
|
14
|
-
|
|
15
|
-
data-server:
|
|
16
|
-
image: "nginx:1.23"
|
|
17
|
-
volumes:
|
|
18
|
-
- "/share/apps/snow-today:/usr/share/nginx/html:ro"
|
|
19
|
-
- "./nginx/default.dataserver.conf:/etc/nginx/conf.d/default.conf:ro"
|
|
20
|
-
ports:
|
|
21
|
-
- "8000:80"
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"description": "Snow Today Webapp",
|
|
3
3
|
"name": "@nsidc/snow-today-webapp",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "webpack --mode=production --node-env=production",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@fontsource/roboto": "^4.5.7",
|
|
18
|
-
"@tanstack/react-query": "^4.
|
|
18
|
+
"@tanstack/react-query": "^4.2.1",
|
|
19
19
|
"colormap": "^2.3.2",
|
|
20
20
|
"highcharts": "^10.2.0",
|
|
21
21
|
"highcharts-react-official": "^3.1.0",
|
|
@@ -12,6 +12,7 @@ import selectedRegionObjectAtom from '../clientState/selectedRegionObject';
|
|
|
12
12
|
import selectedSatelliteVariableAtom from '../clientState/selectedSatelliteVariable';
|
|
13
13
|
import selectedSatelliteVariableObjectAtom from '../clientState/selectedSatelliteVariableObject';
|
|
14
14
|
import usePlotDataQuery from '../serverState/plotData';
|
|
15
|
+
import {IPlotData} from '../types/query/plotData';
|
|
15
16
|
|
|
16
17
|
HighchartsMore(Highcharts);
|
|
17
18
|
|
|
@@ -35,7 +36,7 @@ const LinePlot: React.FC = () => {
|
|
|
35
36
|
<div className={'card centered-card-text'}><p>Loading...</p></div>
|
|
36
37
|
);
|
|
37
38
|
} else if (plotDataQuery.isError) {
|
|
38
|
-
console.debug(`Error!: ${plotDataQuery.error
|
|
39
|
+
console.debug(`Error!: ${String(plotDataQuery.error)}`);
|
|
39
40
|
const regionStr = selectedSatelliteVariableObject.longname;
|
|
40
41
|
const varStr = selectedRegionObject.longname;
|
|
41
42
|
return (
|
|
@@ -63,18 +64,38 @@ const LinePlot: React.FC = () => {
|
|
|
63
64
|
const chartTitle = `${regionLongname} - ${varLongname}`;
|
|
64
65
|
const yAxisTitle = `${varLongname} (${varUnit})`;
|
|
65
66
|
|
|
67
|
+
// WARNING: It is _critical_ that the data is copied before passing to
|
|
68
|
+
// Highcharts. Highcharts will mutate the arrays, and we don't want state to
|
|
69
|
+
// be mutated!!!
|
|
70
|
+
type IPlotDataMutable = {
|
|
71
|
+
[Property in keyof IPlotData]: number[];
|
|
72
|
+
}
|
|
73
|
+
// TODO: Is there a programmatic way to do this object transformation
|
|
74
|
+
// *WITHOUT* type casting? This is not friendly to maintain. Easy to
|
|
75
|
+
// make mistakes with values, but Typescript protects us from messing up
|
|
76
|
+
// structure (keys and types of values).
|
|
77
|
+
const data: IPlotDataMutable = {
|
|
78
|
+
day_of_water_year: [...plotDataQuery.data['day_of_water_year']],
|
|
79
|
+
max: [...plotDataQuery.data['max']],
|
|
80
|
+
median: [...plotDataQuery.data['median']],
|
|
81
|
+
min: [...plotDataQuery.data['min']],
|
|
82
|
+
prc25: [...plotDataQuery.data['prc25']],
|
|
83
|
+
prc75: [...plotDataQuery.data['prc75']],
|
|
84
|
+
year_to_date: [...plotDataQuery.data['year_to_date']],
|
|
85
|
+
};
|
|
86
|
+
|
|
66
87
|
const chartData: Highcharts.SeriesOptionsType[] = [
|
|
67
88
|
{
|
|
68
89
|
name: 'Year to date',
|
|
69
90
|
type: 'line',
|
|
70
|
-
data:
|
|
91
|
+
data: data['year_to_date'],
|
|
71
92
|
zIndex: 99,
|
|
72
93
|
// color: '#000000',
|
|
73
94
|
},
|
|
74
95
|
{
|
|
75
96
|
name: 'Median',
|
|
76
97
|
type: 'line',
|
|
77
|
-
data:
|
|
98
|
+
data: data['median'],
|
|
78
99
|
zIndex: 10,
|
|
79
100
|
color: '#8d8d8d',
|
|
80
101
|
dashStyle: 'Dash',
|
|
@@ -82,7 +103,7 @@ const LinePlot: React.FC = () => {
|
|
|
82
103
|
{
|
|
83
104
|
name: 'Maximum',
|
|
84
105
|
type: 'line',
|
|
85
|
-
data:
|
|
106
|
+
data: data['max'],
|
|
86
107
|
zIndex: 9,
|
|
87
108
|
color: '#666666',
|
|
88
109
|
dashStyle: 'ShortDashDot',
|
|
@@ -90,7 +111,7 @@ const LinePlot: React.FC = () => {
|
|
|
90
111
|
{
|
|
91
112
|
name: 'Minimum',
|
|
92
113
|
type: 'line',
|
|
93
|
-
data:
|
|
114
|
+
data: data['min'],
|
|
94
115
|
zIndex: 8,
|
|
95
116
|
color: '#666666',
|
|
96
117
|
dashStyle: 'ShortDot',
|
|
@@ -98,8 +119,8 @@ const LinePlot: React.FC = () => {
|
|
|
98
119
|
{
|
|
99
120
|
name: 'Interquartile Range',
|
|
100
121
|
type: 'arearange',
|
|
101
|
-
data:
|
|
102
|
-
return [low,
|
|
122
|
+
data: data['prc25'].map((low, index) => {
|
|
123
|
+
return [low, data['prc75'][index]];
|
|
103
124
|
}),
|
|
104
125
|
zIndex: 0,
|
|
105
126
|
lineWidth: 0,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// TODO: Should we just develop an API that serves the correct TIF or GeoJSON
|
|
2
2
|
// (or other data)?
|
|
3
|
-
export const dataServerUrl = 'http://
|
|
3
|
+
export const dataServerUrl = 'http://qa.snow-today.apps.int.nsidc.org'
|
|
4
4
|
|
|
5
5
|
// Information about regions:
|
|
6
6
|
export const regionsIndexUrl = `${dataServerUrl}/regions.json`;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export interface IPlotData {
|
|
2
|
-
day_of_water_year: number[];
|
|
3
|
-
max: number[];
|
|
4
|
-
median: number[];
|
|
5
|
-
min: number[];
|
|
6
|
-
prc25: number[];
|
|
7
|
-
prc75: number[];
|
|
8
|
-
year_to_date: number[];
|
|
2
|
+
readonly day_of_water_year: readonly number[];
|
|
3
|
+
readonly max: readonly number[];
|
|
4
|
+
readonly median: readonly number[];
|
|
5
|
+
readonly min: readonly number[];
|
|
6
|
+
readonly prc25: readonly number[];
|
|
7
|
+
readonly prc75: readonly number[];
|
|
8
|
+
readonly year_to_date: readonly number[];
|
|
9
9
|
}
|
package/webpack.config.js
CHANGED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
server {
|
|
2
|
-
listen 80;
|
|
3
|
-
|
|
4
|
-
server_name localhost;
|
|
5
|
-
|
|
6
|
-
real_ip_header X-Forwarded-For;
|
|
7
|
-
real_ip_recursive on;
|
|
8
|
-
|
|
9
|
-
location / {
|
|
10
|
-
root /usr/share/nginx/html;
|
|
11
|
-
autoindex on;
|
|
12
|
-
|
|
13
|
-
add_header 'Access-Control-Allow-Origin' '*';
|
|
14
|
-
|
|
15
|
-
# Hacky support for CORS pre-flight OPTIONS requests
|
|
16
|
-
if ($request_method = OPTIONS) {
|
|
17
|
-
add_header 'Access-Control-Allow-Origin' '*';
|
|
18
|
-
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
|
|
19
|
-
add_header 'Access-Control-Allow-Headers' 'Range, Origin, X-Requested-With, Content-Type, Accept';
|
|
20
|
-
add_header 'Content-Type' 'text/plain';
|
|
21
|
-
add_header 'Content-Length' '0';
|
|
22
|
-
return 204;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|