Files
openmct/src/plugins/notebook/components/NotebookEmbed.vue
Jamie V 20c7b23a4f [Notebook] Embed enhancements (#5809)
* added new menu and actions to notebook embed as well as new information on embed

* fix method name case

* Add action messages. Fix margins

* Added bg icons. Change sizing of icons and thumbnails. Add scrolling to overflow embeds

* Rename embed wrapper

* adding dynamce class for scrolling the embeds wrapper based on need

* Add styling to embed scrolling container

* Change tag margin for better spacing between rows. Class rename. Minor styling changes to embed container. Change supermenu icon size

* Change action menu size

* Fix inner shadows. Revert tag code change. Create new theme constants. Make embed container constant

* Fix scroll and snow theme colors

* Fix overflow bug in entries and embed container. Refactor code so that containers optimize space of each entry

* Fix lint error

* Fix so embed container goes full width

* Fix input container to extend full width. Fix margin between notebook elements

* Addressed PR review comments.

* Address PR changes. Fix text overflow for long words.

* address pr review comments

* fixing tests

* first pass

* i've wasted too much time on this

Co-authored-by: Rukmini Bose <rukmini.bose15@gmail.com>
Co-authored-by: rukmini-bose <48999852+rukmini-bose@users.noreply.github.com>
Co-authored-by: John Hill <john.c.hill@nasa.gov>
2023-01-21 00:53:37 +00:00

385 lines
13 KiB
Vue

<template>
<div class="c-snapshot c-ne__embed">
<div
v-if="embed.snapshot"
class="c-ne__embed__snap-thumb"
@click="openSnapshot()"
>
<img :src="thumbnailImage">
</div>
<div class="c-ne__embed__info">
<div class="c-ne__embed__name">
<a
class="c-ne__embed__link"
:class="embed.cssClass"
@click="navigateToItemInTime"
>{{ embed.name }}</a>
<button
class="c-ne__embed__actions c-icon-button icon-3-dots"
title="More options"
@click.prevent.stop="showMenuItems($event)"
></button>
</div>
<div class="c-ne__embed__time">
{{ createdOn }}
</div>
</div>
</div>
</template>
<script>
import Moment from 'moment';
import PreviewAction from '../../../ui/preview/PreviewAction';
import RemoveDialog from '../utils/removeDialog';
import PainterroInstance from '../utils/painterroInstance';
import SnapshotTemplate from './snapshot-template.html';
import objectPathToUrl from '@/tools/url';
import { updateNotebookImageDomainObject } from '../utils/notebook-image';
import ImageExporter from '../../../exporters/ImageExporter';
import Vue from 'vue';
export default {
inject: ['openmct', 'snapshotContainer'],
props: {
embed: {
type: Object,
default() {
return {};
}
},
isLocked: {
type: Boolean,
default() {
return false;
}
},
isSnapshotContainer: {
type: Boolean,
default() {
return false;
}
},
removeActionString: {
type: String,
default() {
return 'Remove This Embed';
}
}
},
data() {
return {
menuActions: []
};
},
computed: {
createdOn() {
return this.formatTime(this.embed.createdOn, 'YYYY-MM-DD HH:mm:ss');
},
thumbnailImage() {
return this.embed.snapshot.thumbnailImage
? this.embed.snapshot.thumbnailImage.src
: this.embed.snapshot.src;
}
},
watch: {
isLocked(value) {
if (value === true) {
let index = this.menuActions.findIndex((item) => item.id === 'removeEmbed');
this.$delete(this.menuActions, index);
}
}
},
async mounted() {
this.objectPath = [];
await this.setEmbedObjectPath();
this.addMenuActions();
this.imageExporter = new ImageExporter(this.openmct);
},
methods: {
showMenuItems(event) {
const x = event.x;
const y = event.y;
const menuOptions = {
menuClass: 'c-ne__embed__actions-menu',
placement: this.openmct.menus.menuPlacement.TOP_RIGHT
};
this.openmct.menus.showSuperMenu(x, y, this.menuActions, menuOptions);
},
addMenuActions() {
if (this.embed.snapshot) {
const viewSnapshot = {
id: 'viewSnapshot',
cssClass: 'icon-camera',
name: 'View Snapshot',
description: 'View the snapshot image taken in the form of a jpeg.',
onItemClicked: () => this.openSnapshot()
};
this.menuActions = [viewSnapshot];
}
const navigateToItem = {
id: 'navigateToItem',
cssClass: this.embed.cssClass,
name: 'Navigate to Item',
description: 'Navigate to the item with the current time settings.',
onItemClicked: () => this.navigateToItem()
};
const navigateToItemInTime = {
id: 'navigateToItemInTime',
cssClass: this.embed.cssClass,
name: 'Navigate to Item in Time',
description: 'Navigate to the item in its time frame when captured.',
onItemClicked: () => this.navigateToItemInTime()
};
const quickView = {
id: 'quickView',
cssClass: 'icon-eye-open',
name: 'Quick View',
description: 'Full screen overlay view of the item.',
onItemClicked: () => this.previewEmbed()
};
this.menuActions = this.menuActions.concat([quickView, navigateToItem, navigateToItemInTime]);
if (!this.isLocked) {
const removeEmbed = {
id: 'removeEmbed',
cssClass: 'icon-trash',
name: this.removeActionString,
description: 'Permanently delete this embed from this Notebook entry.',
onItemClicked: this.getRemoveDialog.bind(this)
};
this.menuActions.push(removeEmbed);
}
},
async setEmbedObjectPath() {
this.objectPath = await this.openmct.objects.getOriginalPath(this.embed.domainObject.identifier);
if (this.objectPath.length > 0 && this.objectPath[this.objectPath.length - 1].type === 'root') {
this.objectPath.pop();
}
},
annotateSnapshot() {
const annotateVue = new Vue({
template: '<div id="snap-annotation"></div>'
}).$mount();
const painterroInstance = new PainterroInstance(annotateVue.$el);
const annotateOverlay = this.openmct.overlays.overlay({
element: annotateVue.$el,
size: 'large',
dismissable: false,
buttons: [
{
label: 'Cancel',
callback: () => {
painterroInstance.dismiss();
annotateOverlay.dismiss();
}
},
{
label: 'Save',
emphasis: true,
callback: () => {
painterroInstance.save((snapshotObject) => {
annotateOverlay.dismiss();
this.snapshotOverlay.dismiss();
this.updateSnapshot(snapshotObject);
this.openSnapshotOverlay(snapshotObject.fullSizeImage.src);
});
}
}
],
onDestroy: () => {
annotateVue.$destroy(true);
}
});
painterroInstance.intialize();
const fullSizeImageObjectIdentifier = this.embed.snapshot.fullSizeImageObjectIdentifier;
if (!fullSizeImageObjectIdentifier) {
// legacy image data stored in embed
painterroInstance.show(this.embed.snapshot.src);
return;
}
if (this.isSnapshotContainer) {
const snapshot = this.snapshotContainer.getSnapshot(this.embed.id);
const fullSizeImageURL = snapshot.notebookImageDomainObject.configuration.fullSizeImageURL;
painterroInstance.show(fullSizeImageURL);
return;
}
this.openmct.objects.get(fullSizeImageObjectIdentifier)
.then(object => {
painterroInstance.show(object.configuration.fullSizeImageURL);
});
},
navigateToItem() {
const url = objectPathToUrl(this.openmct, this.objectPath);
this.openmct.router.navigate(url);
},
navigateToItemInTime() {
const hash = this.embed.historicLink;
const bounds = this.openmct.time.bounds();
const isTimeBoundChanged = this.embed.bounds.start !== bounds.start
|| this.embed.bounds.end !== bounds.end;
const isFixedTimespanMode = !this.openmct.time.clock();
this.openmct.time.stopClock();
let message = '';
if (isTimeBoundChanged) {
this.openmct.time.bounds({
start: this.embed.bounds.start,
end: this.embed.bounds.end
});
message = 'Time bound values changed';
}
if (!isFixedTimespanMode) {
message = 'Time bound values changed to fixed timespan mode';
}
if (message.length) {
this.openmct.notifications.alert(message);
}
if (this.openmct.editor.isEditing()) {
this.previewEmbed();
} else {
const relativeHash = hash.slice(hash.indexOf('#'));
const url = new URL(relativeHash, `${location.protocol}//${location.host}${location.pathname}`);
this.openmct.router.navigate(url.hash);
}
},
formatTime(unixTime, timeFormat) {
return Moment.utc(unixTime).format(timeFormat);
},
getRemoveDialog() {
const options = {
name: this.removeActionString,
callback: this.removeEmbed.bind(this)
};
const removeDialog = new RemoveDialog(this.openmct, options);
removeDialog.show();
},
openSnapshot() {
const fullSizeImageObjectIdentifier = this.embed.snapshot.fullSizeImageObjectIdentifier;
if (!fullSizeImageObjectIdentifier) {
// legacy image data stored in embed
this.openSnapshotOverlay(this.embed.snapshot.src);
return;
}
if (this.isSnapshotContainer) {
const snapshot = this.snapshotContainer.getSnapshot(this.embed.id);
const fullSizeImageURL = snapshot.notebookImageDomainObject.configuration.fullSizeImageURL;
this.openSnapshotOverlay(fullSizeImageURL);
return;
}
this.openmct.objects.get(fullSizeImageObjectIdentifier)
.then(object => {
this.openSnapshotOverlay(object.configuration.fullSizeImageURL);
});
},
openSnapshotOverlay(src) {
const self = this;
this.snapshot = new Vue({
data: () => {
return {
createdOn: this.createdOn,
name: this.embed.name,
cssClass: this.embed.cssClass,
src
};
},
methods: {
formatTime: self.formatTime,
annotateSnapshot: self.annotateSnapshot,
exportImage: self.exportImage
},
template: SnapshotTemplate
}).$mount();
this.snapshotOverlay = this.openmct.overlays.overlay({
element: this.snapshot.$el,
onDestroy: () => this.snapshot.$destroy(true),
size: 'large',
autoHide: false,
dismissable: true,
buttons: [
{
label: 'Done',
emphasis: true,
callback: () => {
this.snapshotOverlay.dismiss();
}
}
]
});
},
exportImage(type) {
let element = this.snapshot.$refs['snapshot-image'];
if (type === 'png') {
this.imageExporter.exportPNG(element, this.embed.name);
} else {
this.imageExporter.exportJPG(element, this.embed.name);
}
},
previewEmbed() {
const self = this;
const previewAction = new PreviewAction(self.openmct);
this.openmct.objects.get(self.embed.domainObject.identifier)
.then(domainObject => previewAction.invoke([domainObject]));
},
removeEmbed(success) {
if (!success) {
return;
}
this.$emit('removeEmbed', this.embed.id);
},
updateEmbed(embed) {
this.$emit('updateEmbed', embed);
},
updateSnapshot(snapshotObject) {
this.embed.snapshot.thumbnailImage = snapshotObject.thumbnailImage;
this.updateNotebookImageDomainObjectSnapshot(snapshotObject);
this.updateEmbed(this.embed);
},
updateNotebookImageDomainObjectSnapshot(snapshotObject) {
if (this.isSnapshotContainer) {
const snapshot = this.snapshotContainer.getSnapshot(this.embed.id);
snapshot.embedObject.snapshot.thumbnailImage = snapshotObject.thumbnailImage;
snapshot.notebookImageDomainObject.configuration.fullSizeImageURL = snapshotObject.fullSizeImage.src;
this.snapshotContainer.updateSnapshot(snapshot);
} else {
updateNotebookImageDomainObject(this.openmct, this.embed.snapshot.fullSizeImageObjectIdentifier, snapshotObject.fullSizeImage);
}
}
}
};
</script>