mirror of
https://github.com/nasa/openmct.git
synced 2025-04-09 04:14:32 +00:00
Add right click actions on imagery to allow high resolution download (#7371)
* action stubs in place * first draft of actions * delete copy * add test * remove console.debug
This commit is contained in:
parent
3ff2f029eb
commit
6fd7b6f7a3
@ -61,6 +61,31 @@ test.describe('Example Imagery Object', () => {
|
||||
await expect(page.locator('.c-hud')).toBeHidden();
|
||||
});
|
||||
|
||||
test('Can right click on image and open it in a new tab', async ({ page, context }) => {
|
||||
// try to right click on image
|
||||
const backgroundImage = await page.locator(backgroundImageSelector);
|
||||
await backgroundImage.click({
|
||||
button: 'right',
|
||||
// eslint-disable-next-line playwright/no-force-option
|
||||
force: true
|
||||
});
|
||||
// expect context menu to appear
|
||||
await expect(page.getByText('Save Image As')).toBeVisible();
|
||||
await expect(page.getByText('Open Image in New Tab')).toBeVisible();
|
||||
|
||||
// click on open image in new tab
|
||||
const pagePromise = context.waitForEvent('page');
|
||||
await page.getByText('Open Image in New Tab').click();
|
||||
// expect new tab to be in browser
|
||||
const newPage = await pagePromise;
|
||||
await newPage.waitForLoadState();
|
||||
// expect new tab url to have jpg in it
|
||||
await expect(newPage.url()).toContain('.jpg');
|
||||
});
|
||||
|
||||
// this requires CORS to be enabled in some fashion
|
||||
test.fixme('Can right click on image and save it as a file', async ({ page }) => {});
|
||||
|
||||
test('Can adjust image brightness/contrast by dragging the sliders', async ({
|
||||
page,
|
||||
browserName
|
||||
|
46
src/plugins/imagery/actions/OpenImageInNewTabAction.js
Normal file
46
src/plugins/imagery/actions/OpenImageInNewTabAction.js
Normal file
@ -0,0 +1,46 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2024, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
export default class OpenImageInNewTabAction {
|
||||
constructor(openmct) {
|
||||
this.openmct = openmct;
|
||||
|
||||
this.cssClass = 'icon-new-window';
|
||||
this.description = 'Open the image in a new tab';
|
||||
this.group = 'action';
|
||||
this.key = 'openImageInNewTab';
|
||||
this.name = 'Open Image in New Tab';
|
||||
this.priority = 1;
|
||||
}
|
||||
|
||||
invoke(objectPath, view) {
|
||||
const viewContext = (view.getViewContext && view.getViewContext()) || {};
|
||||
window.open(viewContext.imageUrl, '_blank').focus();
|
||||
}
|
||||
|
||||
appliesTo(objectPath, view = {}) {
|
||||
const viewContext = (view.getViewContext && view.getViewContext()) || {};
|
||||
if (!viewContext.imageUrl) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
67
src/plugins/imagery/actions/SaveImageAsAction.js
Normal file
67
src/plugins/imagery/actions/SaveImageAsAction.js
Normal file
@ -0,0 +1,67 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2024, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
export default class SaveImageAction {
|
||||
constructor(openmct) {
|
||||
this.openmct = openmct;
|
||||
|
||||
this.cssClass = 'icon-save-as';
|
||||
this.description = 'Save image to file';
|
||||
this.group = 'action';
|
||||
this.key = 'saveImageAs';
|
||||
this.name = 'Save Image As';
|
||||
this.priority = 1;
|
||||
}
|
||||
|
||||
async invoke(objectPath, view) {
|
||||
const viewContext = (view.getViewContext && view.getViewContext()) || {};
|
||||
try {
|
||||
const filename =
|
||||
viewContext.imageUrl.split('/').pop().split('#')[0].split('?')[0] || 'downloaded-image.png';
|
||||
const response = await fetch(viewContext.imageUrl);
|
||||
const blob = await response.blob();
|
||||
const blobUrl = URL.createObjectURL(blob);
|
||||
|
||||
// Create a temporary anchor element and trigger the download
|
||||
const a = document.createElement('a');
|
||||
a.href = blobUrl;
|
||||
a.download = filename; // Set the filename for the download
|
||||
|
||||
// Append anchor to body, trigger click, then remove it from the DOM
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
|
||||
// Revoke the blob URL after the download
|
||||
URL.revokeObjectURL(blobUrl);
|
||||
} catch (error) {
|
||||
console.error('Could not download the image.', error);
|
||||
}
|
||||
}
|
||||
|
||||
appliesTo(objectPath, view = {}) {
|
||||
const viewContext = (view.getViewContext && view.getViewContext()) || {};
|
||||
if (!viewContext.imageUrl) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@
|
||||
@mousedown="clearSelectedAnnotations"
|
||||
@mousemove="trackAnnotationDrag"
|
||||
@click="selectOrCreateAnnotation"
|
||||
@contextmenu="showContextMenu"
|
||||
></canvas>
|
||||
</template>
|
||||
|
||||
@ -43,8 +44,10 @@ const EXISTING_ANNOTATION_FILL_STYLE = 'rgba(202, 202, 142, 0.2)';
|
||||
const SELECTED_ANNOTATION_STROKE_COLOR = '#BD8ECC';
|
||||
const SELECTED_ANNOTATION_FILL_STYLE = 'rgba(199, 87, 231, 0.2)';
|
||||
|
||||
const CONTEXT_MENU_ACTIONS = ['openImageInNewTab', 'saveImageAs'];
|
||||
|
||||
export default {
|
||||
inject: ['openmct', 'domainObject', 'objectPath'],
|
||||
inject: ['openmct', 'domainObject', 'objectPath', 'currentView'],
|
||||
props: {
|
||||
image: {
|
||||
type: Object,
|
||||
@ -481,6 +484,21 @@ export default {
|
||||
drawnRectangles.push(annotationRectangle);
|
||||
}
|
||||
});
|
||||
},
|
||||
showContextMenu: function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
let objectPath = this.objectPath;
|
||||
|
||||
const actions = CONTEXT_MENU_ACTIONS.map((key) => this.openmct.actions.getAction(key));
|
||||
const menuItems = this.openmct.menus.actionsToMenuItems(
|
||||
actions,
|
||||
objectPath,
|
||||
this.currentView
|
||||
);
|
||||
if (menuItems.length) {
|
||||
this.openmct.menus.showMenu(event.x, event.y, menuItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -20,6 +20,8 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import OpenImageInNewTabAction from './actions/OpenImageInNewTabAction.js';
|
||||
import SaveImageAsAction from './actions/SaveImageAsAction.js';
|
||||
import ImageryTimestripViewProvider from './ImageryTimestripViewProvider.js';
|
||||
import ImageryViewProvider from './ImageryViewProvider.js';
|
||||
|
||||
@ -27,5 +29,7 @@ export default function (options) {
|
||||
return function install(openmct) {
|
||||
openmct.objectViews.addProvider(new ImageryViewProvider(openmct, options));
|
||||
openmct.objectViews.addProvider(new ImageryTimestripViewProvider(openmct));
|
||||
openmct.actions.register(new OpenImageInNewTabAction(openmct));
|
||||
openmct.actions.register(new SaveImageAsAction(openmct));
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user