diff --git a/public/index.html b/public/index.html index afc2a967a..c45130f51 100644 --- a/public/index.html +++ b/public/index.html @@ -11,6 +11,6 @@ -
+
diff --git a/src/components/Catalog.vue b/src/components/Catalog.vue index 7473bc737..42c9f02df 100644 --- a/src/components/Catalog.vue +++ b/src/components/Catalog.vue @@ -33,6 +33,11 @@

+ +

+
+ Discover in openEO Web Editor +

@@ -406,6 +411,12 @@ export default { // ToDo: Merge all bands from assets return Array.isArray(this.summaries['eo:bands']) ? this.summaries['eo:bands'] : []; }, + openEO() { + if (typeof this.entity.api_version === 'string' && Array.isArray(this.entity.endpoints)) { + return `https://editor.openeo.org/?server=${this.url}&discover=1`; + } + return null; + }, catalog() { return this.entity; }, diff --git a/src/components/base.css b/src/components/base.css index fa9694efa..ce6c4b106 100644 --- a/src/components/base.css +++ b/src/components/base.css @@ -1,148 +1,114 @@ -html { - position: relative; - min-height: 100%; -} - -body { - line-height: 24px; - color: #111; - font-family: Arial, sans-serif; - margin-bottom: 40px; -} - -blockquote, -body { - font-size: 16px; -} -table { - font-size: 80%; -} -h1, -h2, -h3, -h4, -h5, -h6 { +#stac-browser h1, +#stac-browser h2, +#stac-browser h3, +#stac-browser h4, +#stac-browser h5, +#stac-browser h6 { padding: 0; margin: 0; } -h1, -h2, -h3, -h4 { +#stac-browser h1, +#stac-browser h2, +#stac-browser h3, +#stac-browser h4 { font-family: Arial, sans-serif; text-rendering: optimizeLegibility; padding-bottom: 4px; } -h1:last-child, -h2:last-child, -h3:last-child, -h4:last-child { +#stac-browser h1:last-child, +#stac-browser h2:last-child, +#stac-browser h3:last-child, +#stac-browser h4:last-child { padding-bottom: 0; } -h1 { +#stac-browser h1 { font-weight: 400; font-size: 28px; line-height: 1.2; } -h2 { +#stac-browser h2 { font-weight: 700; font-size: 21px; line-height: 1.3; } -h3 { +#stac-browser h3 { font-weight: 700; } -h3, -h4 { +#stac-browser h3, +#stac-browser h4 { font-size: 17px; line-height: 1.255; } -h4 { +#stac-browser h4 { font-weight: 400; } -h5 { +#stac-browser h5 { font-size: 13px; line-height: 19px; } -h5, -h6 { +#stac-browser h5, +#stac-browser h6 { font-weight: 700; } -h6 { +#stac-browser h6 { text-transform: uppercase; font-size: 11px; line-height: 1.465; padding-bottom: 1px; } -p { +#stac-browser p { padding: 0; margin: 0 0 14px; } -p:last-child { +#stac-browser p:last-child { margin-bottom: 0; } -p + p { +#stac-browser p + #stac-browser p { margin-top: -4px; } -b, -strong { +#stac-browser b, +#stac-browser strong { font-weight: 700; } -em, -i { +#stac-browser em, +#stac-browser i { font-style: italic; } -blockquote { +#stac-browser blockquote { margin: 13px; } -small { - font-size: 12px; +#stac-browser header { + padding: 0 0 0.5em; } -a, -a:active, -a:link, -a:visited { - color: #0066c0; -} -header { - padding: 1.5em 0 0.5em; -} -code { +#stac-browser code { color: #555; white-space: nowrap; } -.scroll { +#stac-browser .scroll { overflow-x: scroll; -ms-overflow-style: none; overflow: -moz-scrollbars-none; scrollbar-width: none; } -.scroll::-webkit-scrollbar { +#stac-browser .scroll::-webkit-scrollbar { display: none; } -.btn code { +#stac-browser .btn code { font-size: 10.5px; } -.footer { - position: absolute; - bottom: 0; - width: 100%; +#stac-browser .footer { height: 40px; line-height: 40px; text-align: right; font-size: 0.75em; } -.poweredby { - border: 1px dotted hotpink; - border-radius: 4px; +#stac-browser .poweredby { padding: 5px 10px; - background-color: #f9f9f9; } #thumbnail { @@ -152,35 +118,42 @@ code { max-height: 500px; } -.tabs { +#stac-browser .tabs { margin-top: 25px; + height: auto; } -.table th, -.table td { +#stac-browser .table th, +#stac-browser .table td { border: none; padding: 0.25rem; vertical-align: middle; } -.table td.title { +#stac-browser .table td.title { border-right: 1px solid #ddd; } -.table td.group { +#stac-browser .table td.group { border-radius: 5px; background-color: #ddd; padding-left: 7px; } -.table td.group h4 { +#stac-browser .table td.group h4 { font-size: 14px; font-weight: normal; color: #555; text-transform: uppercase; } -.table th { +#stac-browser .table th { border-top: none; border-bottom: 1px solid #dee2e6; +} + +#stac-browser .metadata td.title { + font-weight: bold; + width: 33%; + text-align: right; } \ No newline at end of file diff --git a/src/components/common.js b/src/components/common.js index a86f451ca..c30dbe38d 100644 --- a/src/components/common.js +++ b/src/components/common.js @@ -42,7 +42,7 @@ export default { ], __dangerouslyDisableSanitizers: ["script"], title: this.title, - titleTemplate: "%s :: STAC Browser" + titleTemplate: "%s - STAC Index" }; }, computed: { diff --git a/src/config.js b/src/config.js index e288dea05..23ee597a0 100644 --- a/src/config.js +++ b/src/config.js @@ -3,4 +3,4 @@ export const TILE_SOURCE_TEMPLATE = process.env.TILE_SOURCE_TEMPLATE; export const STAC_PROXY_URL = process.env.STAC_PROXY_URL; export const TILE_PROXY_URL = process.env.TILE_PROXY_URL; export const PATH_PREFIX = process.env.PATH_PREFIX; -export const HISTORY_MODE = process.env.HISTORY_MODE; \ No newline at end of file +export const HISTORY_MODE = process.env.HISTORY_MODE; diff --git a/src/main.js b/src/main.js index 8ccae5d56..d06a2b09c 100644 --- a/src/main.js +++ b/src/main.js @@ -37,49 +37,49 @@ Vue.use(Meta); Vue.use(VueRouter); Vue.use(Vuex); -const makeRelative = uri => { - const rootURI = url.parse(CATALOG_URL); - const localURI = url.parse(uri); - - if (rootURI.hostname !== localURI.hostname) { - return uri; - } - - const rootPath = rootURI.path - .split("/") - .slice(0, -1) - .join("/"); - - return path.relative(rootPath, `${localURI.path}${localURI.hash || ""}`); -}; - -/** - * Generate a slug (short, URL-encodable string) for a URI. - * - * @param {String} uri URI to generate a slug for. - * @returns Base58-encoded relative path to the root catalog. - */ -const slugify = uri => bs58.encode(Buffer.from(makeRelative(uri))); - -const resolve = (href, base = CATALOG_URL) => { - // Encode colons from all but schema, as they create errors in URL resolving. - const proxiedUri = getProxiedUri(href); - const hrefEncoded = proxiedUri - .replace(":", encodeURIComponent(":")) - .replace(encodeURIComponent(":") + "//", "://"); - return new URL(hrefEncoded, base).toString(); -}; - -function decode(s) { - try { - return resolve(bs58.decode(s).toString()); - } catch (err) { - console.warn(err); - return CATALOG_URL; +async function main(CATALOG_URL, INDEX_PATH) { + const makeRelative = uri => { + const rootURI = url.parse(CATALOG_URL); + const localURI = url.parse(uri); + + if (rootURI.hostname !== localURI.hostname) { + return uri; + } + + const rootPath = rootURI.path + .split("/") + .slice(0, -1) + .join("/"); + + return path.relative(rootPath, `${localURI.path}${localURI.hash || ""}`); + }; + + /** + * Generate a slug (short, URL-encodable string) for a URI. + * + * @param {String} uri URI to generate a slug for. + * @returns Base58-encoded relative path to the root catalog. + */ + const slugify = uri => bs58.encode(Buffer.from(makeRelative(uri))); + + const resolve = (href, base = CATALOG_URL) => { + // Encode colons from all but schema, as they create errors in URL resolving. + const proxiedUri = getProxiedUri(href); + const hrefEncoded = + proxiedUri.replace(':', encodeURIComponent(':')) + .replace(encodeURIComponent(':') + '//', '://'); + return new URL(hrefEncoded, base).toString(); + }; + + function decode(s) { + try { + return resolve(bs58.decode(s).toString()); + } catch (err) { + console.warn(err); + return CATALOG_URL; + } } -} -const main = async () => { let persistedState = {}; const renderedState = document.querySelector( "script.state[type='application/json']" @@ -218,8 +218,12 @@ const main = async () => { if (rsp.ok) { const entity = await rsp.json(); - - commit("LOADED", { entity, url }); + if (!entity) { + commit("FAILED", { err: new Error("Can't load data. Likely a CORS issue."), url }); + } + else { + commit("LOADED", { entity, url }); + } } else { commit("FAILED", { err: new Error(await rsp.text()), url }); } @@ -234,13 +238,11 @@ const main = async () => { }); const router = new VueRouter({ - base: PATH_PREFIX, - mode: HISTORY_MODE, + base: INDEX_PATH, + mode: "hash", routes }); - window.router = router; - await store.dispatch("load", CATALOG_URL); router.beforeEach(async (to, from, next) => { @@ -272,20 +274,17 @@ const main = async () => { return next(); }); - // initial load - let el = document.getElementById("app"); - - // replace existing content - if (document.getElementById("rendered") != null) { - el = document.getElementById("rendered"); - } - - new Vue({ + let el = document.getElementById("stac-browser"); + return new Vue({ el, router, store, - template: `` + template: `` }); }; -main(); +export default main; + +if (CATALOG_URL) { + main(CATALOG_URL, '/'); +} \ No newline at end of file diff --git a/vue.config.js b/vue.config.js index 702b28a9d..c47d8f620 100644 --- a/vue.config.js +++ b/vue.config.js @@ -1,6 +1,6 @@ const { argv } = require("yargs"); -const DEFAULT_PATH_PREFIX = '/'; +const DEFAULT_PATH_PREFIX = '/browse/'; function getVar(name, defaultValue) { let value;