mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #17931 from guerler/visualizations_activity
Revises visualizations activity
This commit is contained in:
@@ -61,7 +61,7 @@ function onQuery(newQuery: string) {
|
||||
<template>
|
||||
<div class="activity-settings rounded no-highlight">
|
||||
<DelayedInput :delay="100" placeholder="Search activities" @change="onQuery" />
|
||||
<div v-if="foundActivities" class="activity-settings-content">
|
||||
<div v-if="foundActivities" class="activity-settings-content mt-2">
|
||||
<div v-for="activity in filteredActivities" :key="activity.id">
|
||||
<button class="activity-settings-item p-2 cursor-pointer" @click="onClick(activity)">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
@@ -77,12 +77,12 @@ function onQuery(newQuery: string) {
|
||||
icon="fas fa-check-square"
|
||||
fa-fw />
|
||||
<FontAwesomeIcon v-else class="mr-1" icon="far fa-square" fa-fw />
|
||||
<small>
|
||||
<span>
|
||||
<icon class="mr-1" :icon="activity.icon" />
|
||||
<span v-localize class="font-weight-bold">{{
|
||||
activity.title || "No title available"
|
||||
}}</span>
|
||||
</small>
|
||||
</span>
|
||||
</span>
|
||||
<b-button
|
||||
v-if="activity.mutable"
|
||||
@@ -94,9 +94,9 @@ function onQuery(newQuery: string) {
|
||||
<FontAwesomeIcon icon="fa-trash" fa-fw />
|
||||
</b-button>
|
||||
</div>
|
||||
<small v-localize>
|
||||
<div v-localize class="text-muted">
|
||||
{{ activity.description || "No description available" }}
|
||||
</small>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -134,14 +134,6 @@ function onQuery(newQuery: string) {
|
||||
}
|
||||
}
|
||||
.activity-settings-item:hover {
|
||||
background: $brand-primary;
|
||||
color: $brand-light;
|
||||
border-radius: $border-radius-large;
|
||||
.icon-check {
|
||||
color: $brand-light;
|
||||
}
|
||||
.button-delete {
|
||||
color: $brand-light;
|
||||
}
|
||||
background: $gray-200;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -28,12 +28,6 @@ withDefaults(defineProps<Props>(), {
|
||||
<div class="d-flex flex-column">
|
||||
<div class="d-flex">
|
||||
<Heading h1 separator inline size="xl" class="flex-grow-1 mb-2">Visualizations</Heading>
|
||||
<div v-if="!userStore.isAnonymous">
|
||||
<BButton size="sm" variant="outline-primary" to="/visualizations">
|
||||
<Icon :icon="faPlus" />
|
||||
<span v-localize>Create Visualization</span>
|
||||
</BButton>
|
||||
</div>
|
||||
</div>
|
||||
<BNav pills justified class="mb-2">
|
||||
<BNavItem
|
||||
|
||||
@@ -59,7 +59,6 @@ const emit = defineEmits(["goToAll"]);
|
||||
|
||||
.activity-panel-heading {
|
||||
margin: 0;
|
||||
padding-left: 0.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,7 +68,17 @@ const emit = defineEmits(["goToAll"]);
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
overflow-y: hidden;
|
||||
padding: 0.2rem 0.2rem;
|
||||
button:first-child {
|
||||
background: none;
|
||||
border: none;
|
||||
text-align: left;
|
||||
transition: none;
|
||||
width: 100%;
|
||||
border-color: transparent;
|
||||
}
|
||||
button:first-child:hover {
|
||||
background: $gray-200;
|
||||
}
|
||||
}
|
||||
|
||||
.activity-panel-footer {
|
||||
|
||||
@@ -1,10 +1,115 @@
|
||||
<script setup lang="ts">
|
||||
import { faEye } from "@fortawesome/free-solid-svg-icons";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, onMounted, type Ref, ref } from "vue";
|
||||
|
||||
import { useHistoryStore } from "@/stores/historyStore";
|
||||
import { absPath } from "@/utils/redirect";
|
||||
import { urlData } from "@/utils/url";
|
||||
|
||||
import DelayedInput from "@/components/Common/DelayedInput.vue";
|
||||
import DataDialog from "@/components/DataDialog/DataDialog.vue";
|
||||
import LoadingSpan from "@/components/LoadingSpan.vue";
|
||||
import ActivityPanel from "@/components/Panels/ActivityPanel.vue";
|
||||
import PluginList from "@/components/Visualizations/PluginList.vue";
|
||||
|
||||
interface Plugin {
|
||||
description: string;
|
||||
href: string;
|
||||
html: string;
|
||||
logo?: string;
|
||||
name: string;
|
||||
target?: string;
|
||||
}
|
||||
|
||||
const { currentHistoryId } = storeToRefs(useHistoryStore());
|
||||
|
||||
const plugins: Ref<Array<Plugin>> = ref([]);
|
||||
const query = ref("");
|
||||
const isLoading = ref(true);
|
||||
const currentPlugin: Ref<Plugin | null> = ref(null);
|
||||
const showDataDialog = ref(false);
|
||||
|
||||
const filteredPlugins = computed(() => {
|
||||
const queryLower = query.value.toLowerCase();
|
||||
return plugins.value.filter(
|
||||
(plugin) =>
|
||||
!query.value ||
|
||||
plugin.html.toLowerCase().includes(queryLower) ||
|
||||
(plugin.description && plugin.description.toLowerCase().includes(queryLower))
|
||||
);
|
||||
});
|
||||
|
||||
function createVisualization(dataset: any) {
|
||||
showDataDialog.value = false;
|
||||
if (currentPlugin.value) {
|
||||
const href = `${currentPlugin.value.href}?dataset_id=${dataset.id}`;
|
||||
if (currentPlugin.value.target == "_top") {
|
||||
window.location.href = href;
|
||||
} else {
|
||||
const galaxyMainElement = document.getElementById("galaxy_main");
|
||||
if (galaxyMainElement) {
|
||||
galaxyMainElement.setAttribute("src", href);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function selectVisualization(plugin: Plugin) {
|
||||
currentPlugin.value = plugin;
|
||||
showDataDialog.value = true;
|
||||
}
|
||||
|
||||
async function getPlugins() {
|
||||
plugins.value = await urlData({ url: "/api/plugins" });
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getPlugins();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ActivityPanel title="Visualizations">
|
||||
<PluginList />
|
||||
<ActivityPanel title="Visualizations" go-to-all-title="Saved Visualizations" href="/visualizations/list">
|
||||
<h3>Create Visualization</h3>
|
||||
<DelayedInput :delay="100" placeholder="Search visualizations" @change="query = $event" />
|
||||
<div class="overflow-y mt-2">
|
||||
<LoadingSpan v-if="isLoading" message="Loading visualizations" />
|
||||
<div v-else-if="filteredPlugins.length > 0">
|
||||
<div v-for="plugin in filteredPlugins" :key="plugin.name">
|
||||
<button :data-plugin-name="plugin.name" @click="selectVisualization(plugin)">
|
||||
<div class="d-flex">
|
||||
<div class="plugin-thumbnail mr-2">
|
||||
<img v-if="plugin.logo" alt="visualization" :src="absPath(plugin.logo)" />
|
||||
<icon v-else :icon="faEye" class="plugin-icon" />
|
||||
</div>
|
||||
<div class="text-break">
|
||||
<div class="plugin-list-title font-weight-bold">{{ plugin.html }}</div>
|
||||
<div class="plugin-list-text text-muted">{{ plugin.description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<BAlert v-else v-localize variant="info" show> No matching visualization found. </BAlert>
|
||||
</div>
|
||||
<DataDialog
|
||||
v-if="showDataDialog"
|
||||
format=""
|
||||
:history="currentHistoryId"
|
||||
@onOk="createVisualization"
|
||||
@onCancel="showDataDialog = false" />
|
||||
</ActivityPanel>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.plugin-thumbnail {
|
||||
img {
|
||||
width: 2rem;
|
||||
}
|
||||
.plugin-icon {
|
||||
font-size: 1.3rem;
|
||||
padding: 0.3rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -40,7 +40,9 @@ onUnmounted(() => {
|
||||
<ActivityBar />
|
||||
<div id="center" class="overflow-auto p-3 w-100">
|
||||
<CenterFrame v-show="showCenter" id="galaxy_main" @load="onLoad" />
|
||||
<router-view v-show="!showCenter" :key="$route.fullPath" class="h-100" />
|
||||
<div v-show="!showCenter" class="h-100">
|
||||
<router-view :key="$route.fullPath" class="h-100" />
|
||||
</div>
|
||||
</div>
|
||||
<FlexPanel v-if="showPanels" side="right">
|
||||
<HistoryIndex />
|
||||
|
||||
@@ -72,7 +72,7 @@ export const Activities = [
|
||||
id: "visualizations",
|
||||
mutable: false,
|
||||
optional: true,
|
||||
title: "Visualize",
|
||||
title: "Visualization",
|
||||
to: null,
|
||||
tooltip: "Visualize datasets",
|
||||
visible: true,
|
||||
|
||||
@@ -42,6 +42,7 @@ $fa-font-path: "../../../node_modules/@fortawesome/fontawesome-free/webfonts/";
|
||||
@import "peek-columns.scss";
|
||||
@import "dataset.scss";
|
||||
@import "list-item.scss";
|
||||
@import "panels.scss";
|
||||
|
||||
// ==== Select2 ====
|
||||
/* fix for zero width select2 - remove when fixed there */
|
||||
@@ -124,73 +125,6 @@ body {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// ==== Unified panel styles ====
|
||||
.unified-panel {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
background: $panel-bg-color;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
.unified-panel-header {
|
||||
@extend .unselectable;
|
||||
@extend .px-3;
|
||||
@extend .d-flex;
|
||||
height: $panel_header_height;
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
align-items: center;
|
||||
color: $panel-header-text-color;
|
||||
background: $panel-bg-header-color;
|
||||
a {
|
||||
color: $panel-header-text-color;
|
||||
}
|
||||
.unified-panel-header-inner {
|
||||
@extend .w-100;
|
||||
min-width: max-content;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
display: flex;
|
||||
}
|
||||
.panel-header-buttons {
|
||||
order: 9999;
|
||||
@extend .d-flex;
|
||||
.panel-header-button {
|
||||
text-align: center;
|
||||
&:not(:last-child) {
|
||||
@extend .mr-2;
|
||||
}
|
||||
&:hover {
|
||||
color: $brand-info;
|
||||
}
|
||||
}
|
||||
.panel-header-button-toolbox {
|
||||
color: $brand-dark;
|
||||
flex: 1;
|
||||
@extend .p-1;
|
||||
text-align: center;
|
||||
font-size: $h4-font-size;
|
||||
align-items: center;
|
||||
&:hover {
|
||||
color: $brand-info;
|
||||
background-color: $brand-light;
|
||||
text-decoration: none !important;
|
||||
border-color: $brand-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.unified-panel-controls {
|
||||
@extend .px-3;
|
||||
}
|
||||
.unified-panel-body {
|
||||
@extend .p-0;
|
||||
@extend .w-100;
|
||||
@extend .h-100;
|
||||
@extend .overflow-auto;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
// State colors
|
||||
$galaxy-state-border: (
|
||||
"new": $state-default-border,
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
.unified-panel {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
background: $panel-bg-color;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
.unified-panel-header {
|
||||
@extend .unselectable;
|
||||
@extend .px-3;
|
||||
@extend .d-flex;
|
||||
height: $panel_header_height;
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
align-items: center;
|
||||
color: $panel-header-text-color;
|
||||
background: $panel-bg-header-color;
|
||||
a {
|
||||
color: $panel-header-text-color;
|
||||
}
|
||||
.unified-panel-header-inner {
|
||||
@extend .w-100;
|
||||
min-width: max-content;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
display: flex;
|
||||
}
|
||||
.panel-header-buttons {
|
||||
order: 9999;
|
||||
@extend .d-flex;
|
||||
.panel-header-button {
|
||||
text-align: center;
|
||||
&:not(:last-child) {
|
||||
@extend .mr-2;
|
||||
}
|
||||
&:hover {
|
||||
color: $brand-info;
|
||||
}
|
||||
}
|
||||
.panel-header-button-toolbox {
|
||||
color: $brand-dark;
|
||||
flex: 1;
|
||||
@extend .p-1;
|
||||
text-align: center;
|
||||
font-size: $h4-font-size;
|
||||
align-items: center;
|
||||
&:hover {
|
||||
color: $brand-info;
|
||||
background-color: $brand-light;
|
||||
text-decoration: none !important;
|
||||
border-color: $brand-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.unified-panel-controls {
|
||||
@extend .px-3;
|
||||
}
|
||||
.unified-panel-body {
|
||||
@extend .p-0;
|
||||
@extend .w-100;
|
||||
@extend .h-100;
|
||||
@extend .overflow-auto;
|
||||
flex: 1;
|
||||
}
|
||||
@@ -40,6 +40,10 @@
|
||||
overflow: auto !important;
|
||||
}
|
||||
|
||||
.overflow-y {
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
// utility class to set word wrap to normal
|
||||
.word-wrap-normal {
|
||||
word-wrap: normal;
|
||||
|
||||
@@ -5,7 +5,7 @@ import { rethrowSimple } from "@/utils/simple-error";
|
||||
|
||||
export interface UrlDataOptions {
|
||||
url: string;
|
||||
headers: Record<string, string>;
|
||||
headers?: Record<string, string>;
|
||||
params?: Record<string, string>;
|
||||
errorSimplify?: boolean;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user