Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions jdaviz/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,10 @@ class ApplicationState(State):
docstring="Nested collection of viewers constructed to support the "
"Golden Layout viewer area.")

plugin_stack_items = ListCallbackProperty(
docstring="List of plugin subcomponents to be displayed in the "
"Golden Layout viewer area")

style_widget = CallbackProperty(
'', docstring="Jupyter widget that won't be displayed but can apply css to the app"
)
Expand Down Expand Up @@ -2290,6 +2294,17 @@ def remove(stack_items):

self.hub.broadcast(ViewerRemovedMessage(cid, sender=self))

def vue_destroy_plugin_stack_item(self, index):
self.state.plugin_stack_items.pop(index)

def vue_data_item_unload(self, event):
"""
Callback for selection events in the front-end data list when clicking to unload an entry
from the viewer.
"""
data_label = self._get_data_item_by_id(event['item_id'])['name']
self.remove_data_from_viewer(event['id'], data_label)

def vue_change_reference_data(self, event):
self._change_reference_data(
self._get_data_item_by_id(event['item_id'])['name'],
Expand Down
58 changes: 40 additions & 18 deletions jdaviz/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,24 +58,38 @@
:has-headers="state.settings.visible.tab_headers"
@state="onLayoutChange"
>
<gl-row :closable="false">
<g-viewer-tab
v-for="(stack, index) in state.stack_items"
:stack="stack"
:key="stack.viewers.map(v => v.id).join('-')"
:data_items="state.data_items"
:app_settings="state.settings"
:icons="state.icons"
:viewer_icons="state.viewer_icons"
:layer_icons="state.layer_icons"
:closefn="destroy_viewer_item"
@data-item-visibility="data_item_visibility($event)"
@data-item-unload="data_item_unload($event)"
@data-item-remove="data_item_remove($event)"
@call-viewer-method="call_viewer_method($event)"
@change-reference-data="change_reference_data($event)"
></g-viewer-tab>
</gl-row>
<gl-col>
<gl-row :closable="false">
<g-viewer-tab
v-for="(stack, index) in state.stack_items"
:stack="stack"
:key="stack.viewers.map(v => v.id).join('-')"
:data_items="state.data_items"
:app_settings="state.settings"
:icons="state.icons"
:viewer_icons="state.viewer_icons"
:layer_icons="state.layer_icons"
:closefn="destroy_viewer_item"
@data-item-visibility="data_item_visibility($event)"
@data-item-unload="data_item_unload($event)"
@data-item-remove="data_item_remove($event)"
@call-viewer-method="call_viewer_method($event)"
@change-reference-data="change_reference_data($event)"
></g-viewer-tab>
</gl-row>
<gl-stack v-if="state.plugin_stack_items.length">
<gl-component
v-for="(plugin_item, index) in state.plugin_stack_items"
:key="index"
:title="plugin_item[0]"
@resize="$emit('resize')"
@destroy="on_destroy_plugin_stack_item($event, index)">
<v-container class="plugin-stack-item" style="padding-left: 24px; padding-right: 24px; padding-top: 12px">
<jupyter-widget :widget="plugin_item[1]"></jupyter-widget>
</v-container>
</gl-component>
</gl-stack>
</gl-col>
</golden-layout>
</pane>
<pane size="25" min-size="25" v-if="state.drawer_content.length > 0" style="background-color: #fafbfc; border-top: 6px solid #C75109; min-width: 250px">
Expand Down Expand Up @@ -210,6 +224,14 @@ export default {
onLayoutChange() {
/* Workaround for #1677, can be removed when bqplot/bqplot#1531 is released */
window.dispatchEvent(new Event('resize'));
},
on_destroy_plugin_stack_item(source, index) {
/* There seems to be no close event provided by vue-golden-layout, so we can't distinguish
* between a user closing a tab or a re-render. However, when the user closes a tab, the
* source of the event is a vue component. We can use that distinction as a close signal. */
if (source.$root) {
this.destroy_plugin_stack_item(index)
};
}
},
mounted() {
Expand Down
9 changes: 6 additions & 3 deletions jdaviz/components/plugin_table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,12 @@
</template>
</v-select>
</div>
<div style="line-height: 64px; width: 32px" class="only-show-in-tray">
<span style="line-height: 64px; width=64px; display: inline-flex" class="only-show-in-tray">
<j-tooltip tipid='plugin-table-send-to-app'>
<v-icon @click="send_to_app">mdi-view-grid-plus-outline</v-icon>
</j-tooltip>
<j-plugin-popout :popout_button="popout_button"></j-plugin-popout>
</div>
</span>
</v-row>

<v-row style="margin: 0px 0px 8px 0px !important">
Expand Down Expand Up @@ -93,7 +96,7 @@ module.exports = {
width: 100%;
}
.tray-plugin .row-select {
width: calc(100% - 40px)
width: calc(100% - 60px)
}

.plugin-table-component {
Expand Down
1 change: 1 addition & 0 deletions jdaviz/components/tooltip.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const tooltips = {
some ad blockers or browser settings may block popup windows,
causing this feature not to work.
</div>`,
'plugin-table-send-to-app': 'Show table in main app view',

'g-data-tools':
'Load data from file',
Expand Down
10 changes: 9 additions & 1 deletion jdaviz/core/template_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4736,6 +4736,11 @@ def __init__(self, plugin, component_type='table', *args, **kwargs):
def display_name(self):
return f'{self._plugin._plugin_name}: {self._component_type}'

def vue_send_to_app(self, data=None, title=None):
title = title if title is not None else self.display_name
self._plugin.app.state.plugin_stack_items += [(title,
'IPY_MODEL_'+self.model_id)]

def vue_popout(self, data=None):
self.show(loc='popout')

Expand Down Expand Up @@ -4787,7 +4792,10 @@ def show(self, loc="inline", title=None): # pragma: no cover
inline, as only JupyterLab has a mechanism to have multiple tabs.
"""
title = title if title is not None else self.display_name
show_widget(self, loc=loc, title=title)
if loc == 'app':
self.vue_send_to_app(title=title)
else:
show_widget(self, loc=loc, title=title)


class Table(PluginSubcomponent):
Expand Down
Loading