From 773bf87dbad42569bdbeb72654cd7a8f83d38572 Mon Sep 17 00:00:00 2001 From: Vincent Privat Date: Fri, 7 Nov 2025 17:02:33 +0100 Subject: [PATCH 1/4] Add item actions --- docs/actions.md | 56 +++++++++++++++++++++++++++------ itemActions.config.js | 5 +++ src/actions/ItemActionPlugin.js | 9 ++++++ src/actions/items/StacMap.js | 18 +++++++++++ src/components/HrefActions.vue | 20 +++++++++--- src/components/Item.vue | 7 +++++ src/views/Item.vue | 7 +++++ 7 files changed, 109 insertions(+), 13 deletions(-) create mode 100644 itemActions.config.js create mode 100644 src/actions/ItemActionPlugin.js create mode 100644 src/actions/items/StacMap.js diff --git a/docs/actions.md b/docs/actions.md index 2efe25805..fe899918e 100644 --- a/docs/actions.md +++ b/docs/actions.md @@ -1,12 +1,13 @@ # Actions -STAC Browser has a pluggable interface to share or open assets and links with other services, which we call "actions". +STAC Browser has a pluggable interface to share or open assets, items and links with other services, which we call "actions". -An action adds a button to an asset or link if certain requirements are met, which can then be executed by users. +An action adds a button to an asset, item or link if certain requirements are met, which can then be executed by users. For example, you could open COPC files in a dedicated COPC Viewer, which otherwise you could only download. - [User Guide](#user-guide) - [Assets](#assets) + - [Items](#items) - [Links](#links) - [Developer Guide](#developer-guide) @@ -50,6 +51,37 @@ export default { Save the file and restart / rebuild STAC Browser. +### Items + +The following actions are available: + +- `stac-map`: Allows to open items through stac-map at . + +All actions for items are stored in the folder [`src/actions/items`](../src/actions/items) if you want to inspect them. + +The actions can be enabled by adding them to the [`itemActions.config.js`](../itemActions.config.js) file. +Open the file and you'll see a number of imports and exports. +Import the file for the action that you want to enable, e.g. for stac-map: + +```js +import Stacmap from './src/actions/items/Stacmap.js'; +``` + +The path is fixed to `./src/actions/items/`, the file extension is always `.js`. +In-between add the file name from the list above. +The import name should be the file name without extension (i.e. `Stacmap` again). + +Lastly, add the import name to the list of exports, e.g. + +```js +export default { + OtherAction, + Stacmap +}; +``` + +Save the file and rebuild / restart STAC Browser. + ### Links The following actions are available: @@ -86,16 +118,22 @@ Save the file and rebuild / restart STAC Browser. ## Developer Guide -Implementing actions for assets and links follows a very similar pattern. -The main difference is that assets implement the [`AssetActionPlugin` interface](../src/actions/AssetActionPlugin.js) while links implement the [`LinkActionPlugin` interface](../src/actions/LinkActionPlugin.js). -Similarly, actions for assets are stored in the folder links are stored in the folder [`src/actions/assets`](../src/actions/assets) while links are stored in the folder [`src/actions/links`](../src/actions/links). +Implementing actions for assets, items and links follows a very similar pattern. +The main difference is that each action implements its own interface: +- assets implement the [`AssetActionPlugin` interface](../src/actions/AssetActionPlugin.js) +- items implement the [`ItemActionPlugin` interface](../src/actions/ItemActionPlugin.js) +- links implement the [`LinkActionPlugin` interface](../src/actions/LinkActionPlugin.js) +Similarly, actions are stored in their own folder: +- assets are stored in the folder [`src/actions/assets`](../src/actions/assets) +- items are stored in the folder [`src/actions/items`](../src/actions/items) +- links are stored in the folder [`src/actions/links`](../src/actions/links) -The interfaces for both look as follows: +All interfaces look as follows: - `constructor(data: object, component: Vue, id: string)` - - `data`: The asset or link object, it is available in the class through `this.asset` (for assets) and `this.link` (for links). - - `component`: The parent Asset/Link Vue component (available in the class through `this.component`) - - `id`: Internal ID of the asset or link, not meant to be used. + - `data`: The asset, item or link object, it is available in the class through `this.asset` (for assets) and `this.link` (for links). + - `component`: The parent Asset/Item/Link Vue component (available in the class through `this.component`) + - `id`: Internal ID of the asset, item or link, not meant to be used. - `get btnOptions() : object` - This should return an object of button options, see [VueBootstrap b-button](https://bootstrap-vue.org/docs/components/button/#component-reference) for details. Returns `href`, `rel` (only for links) and `target` (set to `_blank`) by default. - `get onClick() : function(event: MouseEvent)` diff --git a/itemActions.config.js b/itemActions.config.js new file mode 100644 index 000000000..cac14f66a --- /dev/null +++ b/itemActions.config.js @@ -0,0 +1,5 @@ +// import StacMap from './src/actions/items/StacMap.js'; + +export default { + // StacMap, +}; diff --git a/src/actions/ItemActionPlugin.js b/src/actions/ItemActionPlugin.js new file mode 100644 index 000000000..31b42fb38 --- /dev/null +++ b/src/actions/ItemActionPlugin.js @@ -0,0 +1,9 @@ +import ActionPlugin from './ActionPlugin'; + +export default class ItemActionPlugin extends ActionPlugin { + + constructor(item, component, id) { + super(id, component); + this.item = item; + } +} diff --git a/src/actions/items/StacMap.js b/src/actions/items/StacMap.js new file mode 100644 index 000000000..78085873d --- /dev/null +++ b/src/actions/items/StacMap.js @@ -0,0 +1,18 @@ +import ItemActionPlugin from "../ItemActionPlugin"; +import URI from 'urijs'; +import i18n from "../../i18n"; + +export default class StacMap extends ItemActionPlugin { + + get show() { + return true; + } + + get uri() { + return new URI(`https://developmentseed.org/stac-map/?href=${this.item.getAbsoluteUrl()}`); + } + + get text() { + return i18n.t('actions.openIn', {service: 'stac-map'}); + } +} diff --git a/src/components/HrefActions.vue b/src/components/HrefActions.vue index d684d55fd..ac97c8240 100644 --- a/src/components/HrefActions.vue +++ b/src/components/HrefActions.vue @@ -1,6 +1,6 @@ @@ -26,6 +27,7 @@ import { mapState, mapGetters } from 'vuex'; import FileFormatsMixin from './FileFormatsMixin'; import ThumbnailCardMixin from './ThumbnailCardMixin'; +import HrefActions from './HrefActions.vue'; import StacLink from './StacLink.vue'; import { STAC } from 'stac-js'; import { formatTemporalExtent, formatTimestamp, formatMediaType } from '@radiantearth/stac-fields/formatters'; @@ -38,6 +40,7 @@ export default { name: 'Item', components: { StacLink, + HrefActions, Keywords: () => import('./Keywords.vue') }, filters: { @@ -141,6 +144,10 @@ export default { text-align: center; position: relative; } + + &:has(.actions) { + padding-bottom: 0.5rem; + } } } diff --git a/src/views/Item.vue b/src/views/Item.vue index 478d6b310..1ec555ac2 100644 --- a/src/views/Item.vue +++ b/src/views/Item.vue @@ -14,6 +14,7 @@ + @@ -38,6 +39,7 @@ diff --git a/src/views/Item.vue b/src/views/Item.vue index 1ec555ac2..69e188bb7 100644 --- a/src/views/Item.vue +++ b/src/views/Item.vue @@ -14,7 +14,7 @@ - + @@ -39,7 +39,7 @@