Skip to content

Commit 0a94a79

Browse files
committed
#581 configure-beta make stac collections
1 parent c44b0c8 commit 0a94a79

File tree

17 files changed

+2924
-116
lines changed

17 files changed

+2924
-116
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
const {
2+
createProxyMiddleware,
3+
responseInterceptor,
4+
} = require("http-proxy-middleware");
5+
6+
function initAdjacentServersProxy(app, isDocker, ensureAdmin) {
7+
///////////////////////////
8+
// Proxies
9+
//// STAC
10+
if (process.env.WITH_STAC === "true") {
11+
app.use(
12+
"/stac",
13+
ensureAdmin(false, false, true), // true to allow all GETs - others require admin auth
14+
createProxyMiddleware({
15+
target: `http://${isDocker ? "stac-fastapi" : "localhost"}:${
16+
process.env.STAC_PORT || 8881
17+
}`,
18+
changeOrigin: true,
19+
pathRewrite: { "^/stac": "" },
20+
selfHandleResponse: true,
21+
on: {
22+
proxyRes: createSwaggerInterceptor("stac"),
23+
},
24+
})
25+
);
26+
}
27+
28+
//// Tipg
29+
if (process.env.WITH_TIPG === "true") {
30+
app.use(
31+
"/tipg",
32+
ensureAdmin(false, false, true), // true to allow all GETs - others require admin auth
33+
createProxyMiddleware({
34+
target: `http://${isDocker ? "tipg" : "localhost"}:${
35+
process.env.TIPG_PORT || 8882
36+
}`,
37+
changeOrigin: true,
38+
pathRewrite: { "^/tipg": "" },
39+
selfHandleResponse: true,
40+
on: {
41+
proxyRes: createSwaggerInterceptor("tipg"),
42+
},
43+
})
44+
);
45+
}
46+
47+
//// TiTiler
48+
if (process.env.WITH_TITILER === "true") {
49+
app.use(
50+
"/titiler",
51+
ensureAdmin(false, false, true, ["/cog/stac"]), // true to allow all GETs (except /cog/stac) - others require admin auth
52+
createProxyMiddleware({
53+
target: `http://${isDocker ? "titiler" : "localhost"}:${
54+
process.env.TITILER_PORT || 8883
55+
}`,
56+
changeOrigin: true,
57+
pathRewrite: { "^/titiler": "" },
58+
selfHandleResponse: true,
59+
on: {
60+
proxyRes: createSwaggerInterceptor("titiler"),
61+
},
62+
})
63+
);
64+
}
65+
66+
/// TiTiler-pgSTAC
67+
if (process.env.WITH_TITILER_PGSTAC === "true") {
68+
app.use(
69+
"/titilerpgstac",
70+
ensureAdmin(false, false, true), // true to allow all GETs - others require admin auth
71+
createProxyMiddleware({
72+
target: `http://${isDocker ? "titiler-pgstac" : "localhost"}:${
73+
process.env.TITILER_PGSTAC_PORT || 8884
74+
}`,
75+
changeOrigin: true,
76+
pathRewrite: { "^/titilerpgstac": "" },
77+
selfHandleResponse: true,
78+
on: {
79+
proxyRes: createSwaggerInterceptor("titilerpgstac"),
80+
},
81+
})
82+
);
83+
}
84+
}
85+
86+
const createSwaggerInterceptor = (path) => {
87+
return responseInterceptor(async (responseBuffer, proxyRes, req, res) => {
88+
if (req.originalUrl.endsWith(`/${path}/api`)) {
89+
const response = JSON.parse(responseBuffer.toString("utf8")); // convert buffer to string
90+
response.servers = [{ url: `/${path}` }];
91+
return JSON.stringify(response); // manipulate response and return the result
92+
} else if (req.originalUrl.endsWith(`/${path}/api.html`)) {
93+
const response = responseBuffer.toString("utf8"); // convert buffer to string
94+
return response
95+
.replace("'/api'", `'${process.env.ROOT_PATH || ""}/${path}/api'`)
96+
.replace(
97+
"'/docs/oauth2-redirect'",
98+
`'${process.env.ROOT_PATH || ""}/${path}/docs/oauth2-redirect'`
99+
); // manipulate response and return the result
100+
}
101+
return responseBuffer;
102+
});
103+
};
104+
105+
module.exports = initAdjacentServersProxy;

configure/src/components/Main/Main.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import APITokens from "../../pages/APITokens/APITokens";
3838
import GeoDatasets from "../../pages/GeoDatasets/GeoDatasets";
3939
import Datasets from "../../pages/Datasets/Datasets";
4040
import WebHooks from "../../pages/WebHooks/WebHooks";
41+
import STAC from "../../pages/STAC/STAC";
4142

4243
const useStyles = makeStyles((theme) => ({
4344
Main: {
@@ -167,6 +168,9 @@ export default function Main() {
167168
case "webhooks":
168169
Page = <WebHooks />;
169170
break;
171+
case "stac":
172+
Page = <STAC />;
173+
break;
170174
default:
171175
}
172176

configure/src/components/Panel/Panel.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import KeyIcon from "@mui/icons-material/Key";
1818
import PhishingIcon from "@mui/icons-material/Phishing";
1919
import ApiIcon from "@mui/icons-material/Api";
2020
import OpenInNewIcon from "@mui/icons-material/OpenInNew";
21+
import HorizontalSplitIcon from "@mui/icons-material/HorizontalSplit";
2122

2223
const useStyles = makeStyles((theme) => ({
2324
Panel: {
@@ -221,6 +222,22 @@ export default function Panel() {
221222
>
222223
Webhooks
223224
</Button>
225+
226+
{window.mmgisglobal.WITH_STAC === "true" ? (
227+
<Button
228+
className={c.pageButton}
229+
variant="contained"
230+
disableElevation
231+
startIcon={<HorizontalSplitIcon size="small" />}
232+
onClick={() => {
233+
dispatch(setMission(null));
234+
dispatch(setPage({ page: "stac" }));
235+
}}
236+
>
237+
STAC
238+
</Button>
239+
) : null}
240+
224241
{window.mmgisglobal.WITH_STAC === "true" ? (
225242
<Button
226243
className={c.pageButton}

configure/src/components/Tabs/Layers/Modals/LayerModal/LayerModal.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {
1313
setConfiguration,
1414
} from "../../../../../core/ConfigureStore";
1515

16+
import { inject } from "../../../../../core/injectables";
17+
1618
import Button from "@mui/material/Button";
1719
import Dialog from "@mui/material/Dialog";
1820
import DialogActions from "@mui/material/DialogActions";
@@ -196,6 +198,10 @@ const LayerModal = (props) => {
196198
break;
197199
}
198200

201+
config = inject(config);
202+
203+
console.log(config);
204+
199205
return (
200206
<Dialog
201207
className={c.Modal}

configure/src/core/Configure.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Panel from "../components/Panel/Panel";
99
import { calls } from "../core/calls";
1010
import { setMissions, setSnackBarText } from "./ConfigureStore";
1111
import Websocket from "./Websocket";
12+
import { getInjectables } from "./injectables";
1213

1314
const useStyles = makeStyles((theme) => ({
1415
Configure: {
@@ -46,6 +47,8 @@ export default function Configure() {
4647
);
4748
}
4849
);
50+
51+
getInjectables();
4952
}, [dispatch]);
5053

5154
return (

configure/src/core/ConfigureStore.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export const ConfigureStore = createSlice({
1414
toolConfiguration: {},
1515
geodatasets: [],
1616
datasets: [],
17+
stacCollections: [],
1718
page: null,
1819
modal: {
1920
newMission: false,
@@ -30,6 +31,7 @@ export const ConfigureStore = createSlice({
3031
layersUsedByDataset: false,
3132
updateDataset: false,
3233
deleteDataset: false,
34+
newStacCollection: false,
3335
uploadConfig: false,
3436
cloneConfig: false,
3537
deleteConfig: false,
@@ -63,6 +65,9 @@ export const ConfigureStore = createSlice({
6365
setDatasets: (state, action) => {
6466
state.datasets = action.payload;
6567
},
68+
setStacCollections: (state, action) => {
69+
state.stacCollections = action.payload;
70+
},
6671
setPage: (state, action) => {
6772
state.page = action.payload.page;
6873
},
@@ -188,6 +193,7 @@ export const {
188193
setToolConfiguration,
189194
setGeodatasets,
190195
setDatasets,
196+
setStacCollections,
191197
setPage,
192198
setModal,
193199
setSnackBarText,

configure/src/core/calls.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ const c = {
8181
type: "GET",
8282
url: "api/datasets/download",
8383
},
84+
stac_collections: {
85+
type: "GET",
86+
url: "stac/collections",
87+
},
88+
stac_create_collection: {
89+
type: "POST",
90+
url: "stac/collections",
91+
},
8492
longtermtoken_get: {
8593
type: "GET",
8694
url: "api/longtermtoken/get",
@@ -105,6 +113,10 @@ const c = {
105113
type: "POST",
106114
url: "api/webhooks/config",
107115
},
116+
titiler_tileMatrixSets: {
117+
type: "GET",
118+
url: "titiler/tileMatrixSets",
119+
},
108120
};
109121

110122
function api(call, data, success, error) {

configure/src/core/injectables.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { calls } from "./calls";
2+
3+
const injectablesDefaults = {
4+
TILE_MATRIX_SETS: ["WebMercatorQuad"],
5+
};
6+
// Initialize with reasonable defaults
7+
const injectables = {
8+
TILE_MATRIX_SETS: injectablesDefaults["TILE_MATRIX_SETS"],
9+
};
10+
11+
export const getInjectables = () => {
12+
getTileMatrixSets();
13+
};
14+
15+
export const inject = (configJson) => {
16+
console.log(injectables);
17+
let injected = JSON.stringify(configJson);
18+
Object.keys(injectables).forEach((inj) => {
19+
injected = injected.replaceAll(
20+
`"{{${inj}}}"`,
21+
Array.isArray(injectables[inj])
22+
? JSON.stringify(injectables[inj])
23+
: injectables[inj]
24+
);
25+
});
26+
return JSON.parse(injected);
27+
};
28+
29+
function getTileMatrixSets() {
30+
const injectableName = "TILE_MATRIX_SETS";
31+
if (window.mmgisglobal.WITH_TITILER === "true") {
32+
calls.api(
33+
"titiler_tileMatrixSets",
34+
null,
35+
(res) => {
36+
// ... new Set removes duplicates
37+
injectables[injectableName] = [
38+
...new Set(
39+
injectablesDefaults["TILE_MATRIX_SETS"].concat(
40+
res.tileMatrixSets.map((s) => s.id)
41+
)
42+
),
43+
];
44+
},
45+
(res) => {
46+
console.warn(`Failed to query for ${injectableName}. Using defaults.`);
47+
injectables[injectableName] = [
48+
"WebMercatorQuad",
49+
"CanadianNAD83_LCC",
50+
"CDB1GlobalGrid",
51+
"EuropeanETRS89_LAEAQuad",
52+
"GNOSISGlobalGrid",
53+
"LINZAntarticaMapTilegrid",
54+
"NZTM2000Quad",
55+
"UPSAntarcticWGS84Quad",
56+
"UPSArcticWGS84Quad",
57+
"UTM31WGS84Quad",
58+
"WGS1984Quad",
59+
"WorldCRS84Quad",
60+
"WorldMercatorWGS84Quad",
61+
];
62+
}
63+
);
64+
}
65+
}

configure/src/metaconfigs/layer-tile-config.json

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,9 @@
6262
"name": "Tile Format",
6363
"description": "See URL description above. If a COG and 'Use TiTiler' is enabled, this format is overrided to be 'WMTS'.",
6464
"type": "dropdown",
65-
"width": 2,
65+
"width": 4,
6666
"options": ["tms", "wmts", "wms"]
6767
},
68-
{
69-
"field": "throughTileServer",
70-
"name": "Use TiTiler",
71-
"description": "Uses the TiTiler service to serve tiles if URL is a Cloud-Optimized GeoTiff (COG). TiTiler must be configured via the .env.",
72-
"type": "switch",
73-
"width": 2,
74-
"defaultChecked": false
75-
},
7668
{
7769
"field": "controlled",
7870
"name": "Controlled",
@@ -91,6 +83,26 @@
9183
}
9284
]
9385
},
86+
{
87+
"components": [
88+
{
89+
"field": "throughTileServer",
90+
"name": "Use TiTiler",
91+
"description": "Uses the TiTiler service to serve tiles if URL is a Cloud-Optimized GeoTiff (COG). TiTiler must be configured via the .env.",
92+
"type": "switch",
93+
"width": 4,
94+
"defaultChecked": false
95+
},
96+
{
97+
"field": "tileMatrixSet",
98+
"name": "Tile Matrix Set",
99+
"description": "If using TiTiler, specify the projection for which to serve the tiles.",
100+
"type": "dropdown",
101+
"width": 4,
102+
"options": "{{TILE_MATRIX_SETS}}"
103+
}
104+
]
105+
},
94106
{
95107
"components": [
96108
{

0 commit comments

Comments
 (0)