@@ -22,16 +72,19 @@ export default function BasemapSelector() {
+ {(imageryType === "PlanetNICFI") && nicfiDateSelector()}
Adding imagery to basemaps is available on the
this.updateTitle(e.target.value)}
- placeholder="Enter title"
+ placeholder={
+ this.getWidgetDesign("basemapNICFIDate") ?
+ "Planet NICFI " +
+ this.getWidgetDesign("basemapNICFIDate").slice(
+ 34, this.getWidgetDesign("basemapNICFIDate").length - 7)
+ : "Enter Title"}
type="text"
value={this.state.title}
/>
From 4dba5d6696c2753de1b5775d838e60611faae599 Mon Sep 17 00:00:00 2001
From: Andrew Carlile
Date: Wed, 11 Oct 2023 17:21:11 -0400
Subject: [PATCH 04/19] injects user-selected NICFI date layer into tile
request
---
src/js/geodash/MapWidget.jsx | 7 +++++--
src/js/geodash/form/BasemapSelector.jsx | 1 +
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/js/geodash/MapWidget.jsx b/src/js/geodash/MapWidget.jsx
index 4eb501dce..9b05270c9 100644
--- a/src/js/geodash/MapWidget.jsx
+++ b/src/js/geodash/MapWidget.jsx
@@ -157,10 +157,13 @@ export default class MapWidget extends React.Component {
const { sourceConfig, id, attribution, isProxied } =
this.props.imageryList.find((imagery) => imagery.id === widget.basemapId) ||
this.props.imageryList.find((imagery) => imagery.title === "Open Street Map") ||
- this.props.imageryList[0];
+ this.props.imageryList[0];
+ console.log("getting widget type", widget);
const basemapLayer = new TileLayer({
source: mercator.createSource(
- sourceConfig,
+ (widget.basemapType === "PlanetNICFI") ?
+ {... sourceConfig, time: widget.basemapNICFIDate}
+ : sourceConfig,
id,
attribution,
isProxied,
diff --git a/src/js/geodash/form/BasemapSelector.jsx b/src/js/geodash/form/BasemapSelector.jsx
index 37fd55c3b..e9dfbfe48 100644
--- a/src/js/geodash/form/BasemapSelector.jsx
+++ b/src/js/geodash/form/BasemapSelector.jsx
@@ -46,6 +46,7 @@ export default function BasemapSelector() {
};
useEffect(()=> {
+ setWidgetDesign("basemapType", imageryType);
(imageryType === "PlanetNICFI") ?
getNICFILayers()
: setWidgetDesign("basemapNICFIDate", null);
From f77e786e55d9b87ebc016413f59550484e8ed731 Mon Sep 17 00:00:00 2001
From: Andrew Carlile
Date: Thu, 12 Oct 2023 16:26:37 -0400
Subject: [PATCH 05/19] updates to nicfi date persist to dashboard
---
src/js/geodash/MapWidget.jsx | 1 -
src/js/geodash/TimeSeriesDesigner.jsx | 1 -
src/js/geodash/form/BasemapSelector.jsx | 37 +++++++++++++++----------
src/js/widgetLayoutEditor.jsx | 6 ++--
4 files changed, 26 insertions(+), 19 deletions(-)
diff --git a/src/js/geodash/MapWidget.jsx b/src/js/geodash/MapWidget.jsx
index 9b05270c9..145963e63 100644
--- a/src/js/geodash/MapWidget.jsx
+++ b/src/js/geodash/MapWidget.jsx
@@ -158,7 +158,6 @@ export default class MapWidget extends React.Component {
this.props.imageryList.find((imagery) => imagery.id === widget.basemapId) ||
this.props.imageryList.find((imagery) => imagery.title === "Open Street Map") ||
this.props.imageryList[0];
- console.log("getting widget type", widget);
const basemapLayer = new TileLayer({
source: mercator.createSource(
(widget.basemapType === "PlanetNICFI") ?
diff --git a/src/js/geodash/TimeSeriesDesigner.jsx b/src/js/geodash/TimeSeriesDesigner.jsx
index c26e22537..d50b0a187 100644
--- a/src/js/geodash/TimeSeriesDesigner.jsx
+++ b/src/js/geodash/TimeSeriesDesigner.jsx
@@ -24,7 +24,6 @@ export async function getBandsFromGateway(setBands, assetId, assetType) {
}
);
const data = await res.json();
- console.log("data is: ", data);
if (data.hasOwnProperty("bands")) {
setBands(data.bands);
} else if (data.hasOwnProperty("errMsg")) {
diff --git a/src/js/geodash/form/BasemapSelector.jsx b/src/js/geodash/form/BasemapSelector.jsx
index e9dfbfe48..0d996a956 100644
--- a/src/js/geodash/form/BasemapSelector.jsx
+++ b/src/js/geodash/form/BasemapSelector.jsx
@@ -5,11 +5,12 @@ import SvgIcon from "../../components/svg/SvgIcon";
export default function BasemapSelector() {
- const { setWidgetDesign, getWidgetDesign, imagery, getInstitutionImagery, institutionId } =
+ const { widget, widgetDesign, setWidgetDesign, getWidgetDesign, imagery, getInstitutionImagery, institutionId } =
useContext(EditorContext);
const [nicfiLayers, setNICFILayers] = useState([]);
const [imageryType, setImageryType] = useState("");
-
+ const [basemap, setBasemap] = useState(imagery.filter((i)=>i.id === getWidgetDesign("basemapId")));
+
function nicfiDateSelector(){
const options = (
nicfiLayers || []).map(
@@ -22,17 +23,22 @@ export default function BasemapSelector() {
>
{name}
);}
- );
-
+ );
return (
- );
+
+
+
+
);
}
const getNICFILayers = () => {
@@ -40,7 +46,7 @@ export default function BasemapSelector() {
.then((response) => (response.ok ? response.json() : Promise.reject(response)))
.then((layers) => {
setNICFILayers(layers);
- setWidgetDesign("basemapNICFIDate", layers[0]);
+ setWidgetDesign("basemapNICFIDate", widget[0].basemapNICFIDate);
})
.catch((error) => console.error(error));
};
@@ -54,13 +60,13 @@ export default function BasemapSelector() {
useEffect(()=>{
setImageryType((imagery || []).filter((i)=> i.id === getWidgetDesign("basemapId"))[0].sourceConfig.type);
-
+ setBasemap((imagery || []).filter((i)=> i.id === getWidgetDesign("basemapId"))[0]);
}, [imagery]);
return (
-
+
{`- ${plotOptions[plotDistribution].description}`}
+ {plotOptions[plotDistribution].alert &&
+
- {plotOptions[plotDistribution].alert}
}
{plotOptions[plotDistribution].layout}
Date: Mon, 30 Oct 2023 04:32:14 -0300
Subject: [PATCH 07/19] Add grid to map in collection page
---
src/js/collection.jsx | 16 ++++++++++++++++
src/js/utils/mercator.js | 30 +++++++++++++++++++++++++++++-
2 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/src/js/collection.jsx b/src/js/collection.jsx
index b01d29985..bfccf8e33 100644
--- a/src/js/collection.jsx
+++ b/src/js/collection.jsx
@@ -1585,9 +1585,15 @@ class ImageryOptions extends React.Component {
super(props);
this.state = {
showImageryOptions: true,
+ enableGrid: false,
};
}
+ enableGrid() {
+ this.setState({ enableGrid: !this.state.enableGrid });
+ return mercator.addGridLayer(this.props.mapConfig, !this.state.enableGrid);
+ }
+
render() {
const { props } = this;
const commonProps = {
@@ -1658,6 +1664,16 @@ class ImageryOptions extends React.Component {
}[imagery.sourceConfig.type]
);
})}
+ this.enableGrid()}
+ type="checkbox"
+ />
+
);
diff --git a/src/js/utils/mercator.js b/src/js/utils/mercator.js
index b1d3cb064..d28ad5969 100644
--- a/src/js/utils/mercator.js
+++ b/src/js/utils/mercator.js
@@ -23,7 +23,7 @@ import { platformModifierKeyOnly } from "ol/events/condition";
import { Circle, LineString, Point, Polygon } from "ol/geom";
import { DragBox, Select, Draw, Modify, Snap } from "ol/interaction";
import { GeoJSON, KML } from "ol/format";
-import { Tile as TileLayer, Vector as VectorLayer, Group as LayerGroup } from "ol/layer";
+import { Tile as TileLayer, Vector as VectorLayer, Group as LayerGroup, Graticule } from "ol/layer";
import { BingMaps, Cluster, OSM, TileWMS, Vector as VectorSource, XYZ } from "ol/source";
import { Circle as CircleStyle, Fill, Stroke, Style, Text as StyleText } from "ol/style";
import { fromLonLat, transform, transformExtent, getPointResolution } from "ol/proj";
@@ -475,6 +475,34 @@ mercator.addVectorLayer = (mapConfig, layerId, vectorSource, style) => {
return mapConfig;
};
+mercator.addGridLayer = (mapConfig, showLayer) => {
+ const gridIntervals = [90, 45, 30, 20, 10, 5, 2, 1, 30/60, 20/60,
+ 10/60, 5/60, 2/60, 1/60, 30/3600, 20/3600,
+ 10/3600, 5/3600, 2/3600, 1/3600, 0.8/3600,
+ 0.5/3600, 0.3/3600, 0.2/3600, 0.1/3600];
+ const grid = new Graticule({
+ // the style to use for the lines, optional.
+ strokeStyle: new Stroke({
+ color: 'rgba(255,120,0,0.9)',
+ width: 2,
+ lineDash: [0.5, 4],
+ }),
+ id: 9999,
+ showLabels: false,
+ minResolution: 0.0001,
+ intervals: gridIntervals,
+ wrapX: false,
+ });
+ if(showLayer) {
+ mapConfig.map.addLayer(grid);
+ } else {
+ const layerId = 9999;
+ const layer = mercator.getLayerById(layerId);
+ mapConfig.map.removeLayer(layer);
+ }
+ return mapConfig;
+};
+
/*****************************************************************************
***
*** Functions to verify map input arguments
From 670d4a432d337bd7f31952d30ae0301709421053 Mon Sep 17 00:00:00 2001
From: a-luz
Date: Mon, 30 Oct 2023 04:46:26 -0300
Subject: [PATCH 08/19] Fix input types for institutional imagery
---
src/js/imagery/imageryOptions.js | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/js/imagery/imageryOptions.js b/src/js/imagery/imageryOptions.js
index 1d1a45017..c55f12862 100644
--- a/src/js/imagery/imageryOptions.js
+++ b/src/js/imagery/imageryOptions.js
@@ -253,18 +253,18 @@ export const imageryOptions = [
{
key: "min",
display: "Min",
- type: "number",
+ type: "text",
options: {
- placeholder: "1-100",
+ placeholder: "[1-100] | [0.1,0.2,0.1]",
step: "0.01",
},
},
{
key: "max",
display: "Max",
- type: "number",
+ type: "text",
options: {
- placeholder: "2800-3200",
+ placeholder: "[2800-3200] | [0.3,0.5,0.3]",
step: "0.01",
},
},
@@ -309,18 +309,18 @@ export const imageryOptions = [
{
key: "min",
display: "Min",
- type: "number",
+ type: "text",
options: {
- placeholder: "1-100",
+ placeholder: "[1-100] | [0.1,0.2,0.1]",
step: "0.01",
},
},
{
key: "max",
display: "Max",
- type: "number",
+ type: "text",
options: {
- placeholder: "2800-3200",
+ placeholder: "[2800-3200] | [0.3,0.5,0.3]",
step: "0.01",
},
},
From c273836512ed8c304a5b19adb7201238cd90945a Mon Sep 17 00:00:00 2001
From: a-luz
Date: Mon, 30 Oct 2023 05:02:53 -0300
Subject: [PATCH 09/19] Fix disable mapgrid
---
src/js/utils/mercator.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/js/utils/mercator.js b/src/js/utils/mercator.js
index d28ad5969..9004a7561 100644
--- a/src/js/utils/mercator.js
+++ b/src/js/utils/mercator.js
@@ -497,7 +497,7 @@ mercator.addGridLayer = (mapConfig, showLayer) => {
mapConfig.map.addLayer(grid);
} else {
const layerId = 9999;
- const layer = mercator.getLayerById(layerId);
+ const layer = mercator.getLayerById(mapConfig, layerId);
mapConfig.map.removeLayer(layer);
}
return mapConfig;
From 893bc675d6479e0633964ad2c290e77193096de1 Mon Sep 17 00:00:00 2001
From: a-luz
Date: Wed, 1 Nov 2023 12:20:32 -0300
Subject: [PATCH 10/19] Making the worker function public
---
src/clj/collect_earth_online/workers.clj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/clj/collect_earth_online/workers.clj b/src/clj/collect_earth_online/workers.clj
index aa6a8e601..ba2143704 100644
--- a/src/clj/collect_earth_online/workers.clj
+++ b/src/clj/collect_earth_online/workers.clj
@@ -19,7 +19,7 @@
file (reverse (file-seq d))]
(io/delete-file file))))
-(defn- start-clean-up-service! []
+(defn start-clean-up-service! []
(log-str "Starting temp file removal service.")
(future
(while true
From c42c90c14e98d818321f95d076de5e343ebdcef3 Mon Sep 17 00:00:00 2001
From: Gary Johnson
Date: Wed, 1 Nov 2023 12:02:10 -0400
Subject: [PATCH 11/19] Switch CEO to use
triangulum.handler/authenticated-routing-handler
---
config.example.edn | 6 ++-
src/clj/collect_earth_online/handlers.clj | 33 ++++++++++++++++
src/clj/collect_earth_online/routing.clj | 48 ++---------------------
3 files changed, 41 insertions(+), 46 deletions(-)
create mode 100644 src/clj/collect_earth_online/handlers.clj
diff --git a/config.example.edn b/config.example.edn
index b09ea8329..d69737579 100644
--- a/config.example.edn
+++ b/config.example.edn
@@ -7,12 +7,16 @@
:triangulum.server/mode "dev"
:triangulum.server/log-dir "logs"
- :triangulum.server/handler collect-earth-online.routing/authenticated-routing-handler
+ :triangulum.server/handler triangulum.handler/authenticated-routing-handler
:triangulum.server/keystore-file "keystore.pkcs12"
:triangulum.server/keystore-type "pkcs12"
:triangulum.server/keystore-password "foobar"
;; handler (server)
+ :triangulum.handler/not-found-handler triangulum.views/not-found-page
+ :triangulum.handler/redirect-handler collect-earth-online.handlers/redirect-handler
+ :triangulum.handler/route-authenticator collect-earth-online.handlers/route-authenticator
+ :triangulum.handler/routing-tables [collect-earth-online.routing/routes]
:triangulum.handler/session-key "changeme12345678" ; must be 16 characters
:triangulum.handler/bad-tokens #{".php"}
:triangulum.handler/private-request-keys #{:base64Image :plotFileBase64 :sampleFileBase64}
diff --git a/src/clj/collect_earth_online/handlers.clj b/src/clj/collect_earth_online/handlers.clj
new file mode 100644
index 000000000..33c7f4005
--- /dev/null
+++ b/src/clj/collect_earth_online/handlers.clj
@@ -0,0 +1,33 @@
+(ns collect-earth-online.handlers
+ (:require [collect-earth-online.db.institutions :refer [is-inst-admin?]]
+ [collect-earth-online.db.projects :refer [can-collect? is-proj-admin?]]
+ [ring.util.codec :refer [url-encode]]
+ [ring.util.response :refer [redirect]]
+ [triangulum.response :refer [no-cross-traffic?]]
+ [triangulum.type-conversion :refer [val->int]]))
+
+(defn route-authenticator [{:keys [session params headers] :as _request} auth-type]
+ (let [user-id (:userId session -1)
+ institution-id (val->int (:institutionId params))
+ project-id (val->int (:projectId params))
+ token-key (:tokenKey params)]
+ (condp = auth-type
+ :user (pos? user-id)
+ :super (= 1 user-id)
+ :collect (can-collect? user-id project-id token-key)
+ :token (can-collect? -99 project-id token-key)
+ :admin (cond
+ (pos? project-id) (is-proj-admin? user-id project-id token-key)
+ (pos? institution-id) (is-inst-admin? user-id institution-id))
+ :no-cross (no-cross-traffic? headers)
+ true)))
+
+(defn redirect-handler [{:keys [session query-string uri] :as _request}]
+ (let [full-url (url-encode (str uri (when query-string (str "?" query-string))))]
+ (if (:userId session)
+ (redirect (str "/home?flash_message=You do not have permission to access "
+ full-url))
+ (redirect (str "/login?returnurl="
+ full-url
+ "&flash_message=You must login to see "
+ full-url)))))
diff --git a/src/clj/collect_earth_online/routing.clj b/src/clj/collect_earth_online/routing.clj
index d9b09147a..9128517e5 100644
--- a/src/clj/collect_earth_online/routing.clj
+++ b/src/clj/collect_earth_online/routing.clj
@@ -1,17 +1,13 @@
(ns collect-earth-online.routing
- (:require [triangulum.views :refer [render-page not-found-page]]
- [ring.util.response :refer [redirect]]
- [ring.util.codec :refer [url-encode]]
- [triangulum.type-conversion :as tc]
- [triangulum.response :refer [forbidden-response no-cross-traffic?]]
- [collect-earth-online.db.doi :as doi]
+ (:require [collect-earth-online.db.doi :as doi]
[collect-earth-online.db.geodash :as geodash]
[collect-earth-online.db.imagery :as imagery]
[collect-earth-online.db.institutions :as institutions]
[collect-earth-online.db.plots :as plots]
[collect-earth-online.db.projects :as projects]
[collect-earth-online.db.users :as users]
- [collect-earth-online.proxy :as proxy]))
+ [collect-earth-online.proxy :as proxy]
+ [triangulum.views :refer [render-page]]))
(def routes
{;; Page Routes
@@ -194,41 +190,3 @@
[:get "/get-nicfi-tiles"] {:handler proxy/get-nicfi-tiles
:auth-type :no-cross
:auth-action :block}})
-
-(defn- redirect-auth [user-id]
- (fn [request]
- (let [{:keys [query-string uri]} request
- full-url (url-encode (str uri (when query-string (str "?" query-string))))]
- (if (pos? user-id)
- (redirect (str "/home?flash_message=You do not have permission to access "
- full-url))
- (redirect (str "/login?returnurl="
- full-url
- "&flash_message=You must login to see "
- full-url))))))
-
-(defn authenticated-routing-handler [{:keys [uri request-method params headers session] :as request}]
- (let [{:keys [auth-type auth-action handler] :as route} (get routes [request-method uri])
- user-id (:userId session -1)
- institution-id (tc/val->int (:institutionId params))
- project-id (tc/val->int (:projectId params))
- next-handler (if route
- (if (condp = auth-type
- :user (pos? user-id)
- :super (= 1 user-id)
- :collect (projects/can-collect? user-id project-id (:tokenKey params))
- :token (projects/can-collect? -99 project-id (:tokenKey params))
- :admin (cond
- (pos? project-id)
- (projects/is-proj-admin? user-id project-id (:tokenKey params))
-
- (pos? institution-id)
- (institutions/is-inst-admin? user-id institution-id))
- :no-cross (no-cross-traffic? headers)
- true)
- handler
- (if (= :redirect auth-action)
- (redirect-auth user-id)
- forbidden-response))
- not-found-page)]
- (next-handler request)))
From 89642958de5b367928988902f5854bd9da3651ec Mon Sep 17 00:00:00 2001
From: a-luz
Date: Wed, 1 Nov 2023 16:32:12 -0300
Subject: [PATCH 12/19] Updating triangulum git hash
---
deps.edn | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/deps.edn b/deps.edn
index f31083d69..2acdfb329 100644
--- a/deps.edn
+++ b/deps.edn
@@ -7,7 +7,7 @@
org.clojure/data.json {:mvn/version "1.0.0"}
ring/ring {:mvn/version "1.8.2"}
sig-gis/triangulum {:git/url "https://github.com/sig-gis/triangulum"
- :git/sha "5cffefc2e8a8027a178d7ff1103cb2e38e174bba"}}
+ :git/sha "4aab4f9b6af8a7af1814c235f5709a27eb38f2c6"}}
:aliases {:build-db {:main-opts ["-m" "triangulum.build-db"]}
:config {:main-opts ["-m" "triangulum.config"]}
From 24a6b16c6d9aedcba5b2b6c808fcb6ecb59d738f Mon Sep 17 00:00:00 2001
From: a-luz
Date: Fri, 3 Nov 2023 03:08:03 -0300
Subject: [PATCH 13/19] Fix content-type header
---
src/clj/collect_earth_online/db/doi.clj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/clj/collect_earth_online/db/doi.clj b/src/clj/collect_earth_online/db/doi.clj
index bc5a38dfc..def503a20 100644
--- a/src/clj/collect_earth_online/db/doi.clj
+++ b/src/clj/collect_earth_online/db/doi.clj
@@ -116,7 +116,7 @@
[bucket-url project-id zip-file]
(let [headers (req-headers)]
(http/put (str bucket-url "/" project-id)
- {:content-type :multipart/form-data
+ {:content-type "application/octet-stream"
:headers headers
:as :json
:multipart [{:name "Content/type" :content "application/octet-stream"}
From 899d243ca34a1dbdd0c43218cffde065f0500fe4 Mon Sep 17 00:00:00 2001
From: Andrew Carlile
Date: Mon, 6 Nov 2023 15:03:29 -0500
Subject: [PATCH 14/19] addresses notes
---
src/js/geodash/MapWidget.jsx | 2 +-
src/js/geodash/form/BasemapSelector.jsx | 2 +-
src/js/widgetLayoutEditor.jsx | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/js/geodash/MapWidget.jsx b/src/js/geodash/MapWidget.jsx
index 145963e63..0697c74c5 100644
--- a/src/js/geodash/MapWidget.jsx
+++ b/src/js/geodash/MapWidget.jsx
@@ -157,7 +157,7 @@ export default class MapWidget extends React.Component {
const { sourceConfig, id, attribution, isProxied } =
this.props.imageryList.find((imagery) => imagery.id === widget.basemapId) ||
this.props.imageryList.find((imagery) => imagery.title === "Open Street Map") ||
- this.props.imageryList[0];
+ this.props.imageryList[0];
const basemapLayer = new TileLayer({
source: mercator.createSource(
(widget.basemapType === "PlanetNICFI") ?
diff --git a/src/js/geodash/form/BasemapSelector.jsx b/src/js/geodash/form/BasemapSelector.jsx
index 0d996a956..bae824c50 100644
--- a/src/js/geodash/form/BasemapSelector.jsx
+++ b/src/js/geodash/form/BasemapSelector.jsx
@@ -66,7 +66,7 @@ export default function BasemapSelector() {
return (
-
+