Skip to content

Commit

Permalink
Merge commit 'b77751b02d1e639795ff04e4c35967f840212b68'
Browse files Browse the repository at this point in the history
  • Loading branch information
m-mohr committed Jan 2, 2025
2 parents 91fd51d + b77751b commit 465dd0d
Show file tree
Hide file tree
Showing 14 changed files with 226 additions and 26 deletions.
9 changes: 7 additions & 2 deletions config.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,20 @@ export default {

// List of supported batch job sharing services
supportedBatchJobSharingServices: [
'ShareEditor',
'CopyUrl',
'TwitterShare'
'BlueskyShare',
'MastodonSocialShare',
'XShare'
],

// List of supported web service sharing services
supportedWebServiceSharingServices: [
'ShareEditor',
'CopyUrl',
'TwitterShare'
'BlueskyShare',
'MastodonSocialShare',
'XShare'
],

// List of supported wizards
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@openeo/web-editor",
"version": "0.14.0-beta.2",
"version": "0.14.0-beta.4",
"apiVersions": [
"1.0.0-rc.2",
"1.0.0",
Expand Down
4 changes: 2 additions & 2 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="preload" as="font" type="font/woff2" crossorigin href="https://use.fontawesome.com/releases/v5.13.0/webfonts/fa-solid-900.woff2"/>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.13.0/css/all.css" type="text/css" media="all" />
<link rel="preload" as="font" type="font/woff2" crossorigin href="https://use.fontawesome.com/releases/v6.7.0/webfonts/fa-solid-900.woff2"/>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v6.7.0/css/all.css" type="text/css" media="all" />
<link rel="icon" type="image/png" href="logo.png">
</head>

Expand Down
13 changes: 10 additions & 3 deletions src/components/IDE.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,23 @@
</ul>
</header>
<Splitpanes class="default-theme" @resize="resized" @pane-maximize="resized">
<Pane id="discovery" :size="splitpaneSizeH[0]">
<Pane v-if="!appMode || isAuthenticated" id="discovery" :size="splitpaneSizeH[0]">
<DiscoveryToolbar class="toolbar tour-ide-discovery" :onAddProcess="insertProcess" :collectionPreview="true" :persist="true" />
</Pane>
<Pane id="workspace" :size="splitpaneSizeH[1]">
<Pane v-if="!appMode || isAuthenticated || hasProcess" id="workspace" :size="splitpaneSizeH[1]">
<Splitpanes class="default-theme" horizontal @resize="resized" @pane-maximize="resized">
<Pane id="editor" :size="splitpaneSizeV[0]">
<Editor ref="editor" class="mainEditor tour-ide-editor" id="main" :value="process" @input="updateEditor" :title="contextTitle" showIntro>
<template #file-toolbar>
<button type="button" @click="importProcess" title="Import process from external source"><i class="fas fa-cloud-download-alt"></i></button>
<button type="button" v-show="saveSupported" :disabled="!hasProcess" @click="saveProcess" :title="'Save to ' + contextTitle"><i class="fas fa-save"></i></button>
<button type="button" @click="exportJSON" :disabled="!hasProcess" title="Download as JSON file"><i class="fas fa-file-download"></i></button>
<button type="button" @click="exportCode" :disabled="!hasProcess" title="Export into another programming language"><i class="fas fa-file-export"></i></button>
<button type="button" v-show="validateSupported" :disabled="!hasProcess" @click="validateProcess" title="Validate process on server-side"><i class="fas fa-tasks"></i></button>
</template>
</Editor>
</Pane>
<Pane id="user" :size="splitpaneSizeV[1]">
<Pane v-if="!appMode || isAuthenticated" id="user" :size="splitpaneSizeV[1]">
<UserWorkspace v-if="isAuthenticated" class="userContent tour-ide-workspace" />
<div v-else class="message info" title="Login is required to interact with the server.">
<i class="fas fa-sign-in-alt"></i>
Expand Down Expand Up @@ -55,6 +56,7 @@ import DiscoveryToolbar from './DiscoveryToolbar.vue';
import { ProcessParameter } from '@openeo/js-commons';
import { Job, Service, UserProcess } from '@openeo/js-client';
import { Splitpanes, Pane } from 'splitpanes';
import { OpenEO } from '@openeo/js-client';
export default {
name: 'IDE',
Expand Down Expand Up @@ -186,6 +188,11 @@ export default {
this.broadcast('replaceProcess', this.context, this.process);
},
exportJSON() {
const filename = (this.contextTitle || "openeo-process") + '.json';
OpenEO.Environment.saveToFile(JSON.stringify(this.process, null, 2), filename);
},
async exportCode() {
this.broadcast('showModal', 'ExportCodeModal');
},
Expand Down
27 changes: 22 additions & 5 deletions src/components/Viewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<template #dynamic="{ tab }">
<LogViewer v-if="logViewerIcons.includes(tab.icon)" :data="tab.data" @mounted="onMounted" @options="onOptionsChanged" />
<component v-else-if="tab.data.component" :is="tab.data.component" v-on="tab.data.events" v-bind="tab.data.props" @mounted="onMounted" @options="onOptionsChanged" /> <!-- for file formats -->
<MetadataViewer v-if="tab.icon === 'fa-info'" :data="tab.data" @mounted="onMounted" @options="onOptionsChanged" /> <!-- for STAC metadata -->
<MapViewer v-else-if="tab.icon === 'fa-map'" :data="tab.data" :removableLayers="isCollectionPreview(tab.data)" @mounted="onMounted" @options="onOptionsChanged" /> <!-- for services -->
<div class="unsupported" v-else>
Sorry, the viewer doesn't support showing this type of data.
Expand Down Expand Up @@ -35,7 +36,8 @@ export default {
TableViewer: () => import('./viewer/TableViewer.vue'),
ImageViewer: () => import('./viewer/ImageViewer.vue'),
LogViewer: () => import('./viewer/LogViewer.vue'),
MapViewer: () => import('./viewer/MapViewer.vue')
MapViewer: () => import('./viewer/MapViewer.vue'),
MetadataViewer: () => import('./viewer/MetadataViewer.vue')
},
mounted() {
this.listen('viewSyncResult', this.showSyncResults);
Expand Down Expand Up @@ -76,17 +78,15 @@ export default {
...Utils.mapMutations('editor', ['setViewerOptions', 'setModelDnD']),
showAppMode() {
if (this.appMode.resultType === 'service') {
console.log(this.appMode);
const service = new Service(this.connection, 'app');
service.title = this.appMode.title;
service.url = this.appMode.resultUrl;
service.type = this.appMode.service;
service.enabled = true;
console.log(service);
this.showWebService(service);
}
else {
this.showJobResults(this.appMode.data, null, this.appMode.title);
this.showJobResults(this.appMode.data, null, this.appMode.title, true);
if (typeof this.appMode.expires === 'string') {
const expires = Formatters.formatTimestamp(this.appMode.expires);
Utils.info(this, `The shared data is available until ${expires}`);
Expand Down Expand Up @@ -183,7 +183,7 @@ export default {
}
});
},
showJobResults(stac, job = null, title = null) {
showJobResults(stac, job = null, title = null, showMetadata = false) {
if (title === null) {
if (stac.title) {
title = stac.title;
Expand All @@ -207,6 +207,9 @@ export default {
else if (files.length > 5 && !Utils.confirmOpenAll(files)) {
return;
}
if (showMetadata) {
this.showMetadataViewer(stac, id, title);
}
this.showViewer(files, title, file => `${id}-${file.getUrl()}`, true)
.catch(error => Utils.exception(this, error));
},
Expand Down Expand Up @@ -234,6 +237,20 @@ export default {
onClose
);
},
showMetadataViewer(resource, id = null, title = null) {
if (!title) {
title = Utils.getResourceTitle(resource, true);
}
if (!id) {
id = this.nextTabId;
this.tabIdCounter++;
}
this.$refs.tabs.addTab(
title, "fa-info", resource, id, true, true,
tab => this.onShow(tab),
tab => this.onHide(tab)
);
},
addToMapChooser({asset, context}) {
const openMapTabs = this.$refs.tabs.tabs.filter(tab => tab.icon === 'fa-map');
const maps = [
Expand Down
2 changes: 1 addition & 1 deletion src/components/VisualEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<div v-if="showHelpOverlay" class="model-overlay">
<h2>Welcome!</h2>
<p>
What you are seeing in this area of the {{ $config.appName }} is the visual model builder.
What you are seeing in this area is the visual model builder.
You can start building your model by dragging collections, processes etc. from the left area and dropping them here.
</p>
<p>
Expand Down
3 changes: 0 additions & 3 deletions src/components/modals/ImportProcessModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,6 @@ export default {
if (!Utils.isObject(data)) {
throw new Error('Process does not contain any data');
}
if (!Utils.hasText(data.id)) {
throw new Error('Process does not contain an id');
}
if (!Utils.isObject(data.process_graph)) {
throw new Error('Process does not contain a process graph');
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<template>
<ShareInterface id="share-twitter" :icon="['fab', 'fa-twitter']" title="Twitter" description="Share your STAC metadata as a tweet">
<ShareInterface id="share-bluesky" :icon="['fab', 'fa-bluesky']" title="Bluesky" description="Share your STAC metadata as a Bluesky post">
<template #customize>
<textarea v-model="text"></textarea><br />
<button @click="tweet">Open Twitter</button>
<button @click="action">Open Bluesky</button>
</template>
</ShareInterface>
</template>
Expand All @@ -12,7 +12,7 @@ import ShareMixin from './ShareMixin';
import ShareInterface from './ShareInterface.vue';
export default {
name: 'TwitterShare',
name: 'BlueskyShare',
components: {
ShareInterface
},
Expand All @@ -28,19 +28,19 @@ export default {
ShareMixin
],
methods: {
tweet() {
let text = encodeURIComponent(this.text);
let url = `https://twitter.com/intent/tweet?text=${text}`;
action() {
let text = encodeURIComponent(this.text);
let url = `https://bsky.app/intent/compose?text=${text}`;
window.open(url, '_blank').focus();
}
}
}
</script>

<style lang="scss">
#share-twitter {
#share-bluesky {
&.shareable:not(.expanded) > .entry {
color: #1DA1F2;
color: #1185fe;
}
textarea {
width: 100%;
Expand Down
52 changes: 52 additions & 0 deletions src/components/share/MastodonSocialShare.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<template>
<ShareInterface id="share-mastodon" :icon="['fab', 'fa-mastodon']" title="Mastodon.social" description="Share your STAC metadata as a toot on Mastodon.social">
<template #customize>
<textarea v-model="text"></textarea><br />
<button @click="action">Open Mastodon.social</button>
</template>
</ShareInterface>
</template>

<script>
import ShareMixin from './ShareMixin';
import ShareInterface from './ShareInterface.vue';
export default {
name: 'MastodonSocialShare',
components: {
ShareInterface
},
data() {
return {
text: ""
};
},
created() {
this.text = `"${this.title}" is available at ${this.url}`;
},
mixins: [
ShareMixin
],
methods: {
action() {
let text = encodeURIComponent(this.text);
let url = `https://mastodon.social/share?text=${text}`;
window.open(url, '_blank').focus();
}
}
}
</script>

<style lang="scss">
#share-mastodon {
&.shareable:not(.expanded) > .entry {
color: #6364FF;
}
textarea {
width: 100%;
height: 5em;
overflow: auto;
box-sizing: border-box;
}
}
</style>
52 changes: 52 additions & 0 deletions src/components/share/XShare.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<template>
<ShareInterface id="share-x" :icon="['fab', 'fa-x']" title="X (Twitter)" description="Share your STAC metadata as a tweet">
<template #customize>
<textarea v-model="text"></textarea><br />
<button @click="action">Open X</button>
</template>
</ShareInterface>
</template>

<script>
import ShareMixin from './ShareMixin';
import ShareInterface from './ShareInterface.vue';
export default {
name: 'XShare',
components: {
ShareInterface
},
data() {
return {
text: ""
};
},
created() {
this.text = `"${this.title}" is available at ${this.url}`;
},
mixins: [
ShareMixin
],
methods: {
action() {
let text = encodeURIComponent(this.text);
let url = `https://x.com/intent/tweet?text=${text}`;
window.open(url, '_blank').focus();
}
}
}
</script>

<style lang="scss">
#share-x {
&.shareable:not(.expanded) > .entry {
color: #000000;
}
textarea {
width: 100%;
height: 5em;
overflow: auto;
box-sizing: border-box;
}
}
</style>
61 changes: 61 additions & 0 deletions src/components/viewer/MetadataViewer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<template>
<div class="metadataViewer">
<Collection v-if="isCollection" :data="data">
<template #spatial-extents="p">
<MapExtentViewer class="jobMap" :footprint="p.extents"></MapExtentViewer>
</template>
</Collection>
<Item v-else-if="isItem" :data="data">
<template #location="p">
<MapExtentViewer class="jobMap" :footprint="p.geometry || p.bbox"></MapExtentViewer>
</template>
</Item>
<ul class="list">
<StacAsset v-for="(asset, id) in data.assets" :key="id" :asset="asset" :id="id" :context="data" />
</ul>
</div>
</template>

<script>
let tabId = 0;
export default {
name: 'MetadataViewer',
props: {
data: {
type: Object,
required: true
}
},
components: {
Collection: () => import('@openeo/vue-components/components/Collection.vue'),
Item: () => import('@openeo/vue-components/components/Item.vue'),
MapExtentViewer: () => import('../maps/MapExtentViewer.vue'),
StacAsset: () => import('@openeo/vue-components/components/internal/StacAsset.vue'),
},
computed: {
isCollection() {
return this.data.type === 'Collection';
},
isItem() {
return this.data.type === 'Feature';
}
},
data() {
return {
tabsId: "metadata_viewer_" + tabId++,
};
},
mounted() {
this.$emit('mounted', this);
}
};
</script>

<style lang="scss" scoped>
.metadataViewer {
width: 98%;
height: 98%;
padding: 1%;
}
</style>
Loading

0 comments on commit 465dd0d

Please sign in to comment.