Skip to content

Commit 17aa2bc

Browse files
authored
Merge pull request #21106 from guerler/remove_tabular_chunked_mako
Remove tabular chunked, binary and large file mako
2 parents 992d46a + 81000dc commit 17aa2bc

File tree

17 files changed

+196
-254
lines changed

17 files changed

+196
-254
lines changed

client/src/bundleEntries.js

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,9 @@
11
/**
2-
* The list of horrible globals we expose on window.bundleEntries.
3-
*
4-
* Everything that is exposed on this global variable is something that the python templates
5-
* require for their hardcoded initializations. These objects are going to have to continue
6-
* to exist until such time as we replace the overall application with a Vue component which
7-
* will handle initializations for components individually.
8-
*
2+
* The list of globals we expose on window.bundleEntries.
93
*/
10-
import { replaceChildrenWithComponent } from "utils/mountVueComponent";
11-
12-
import TabularChunkedView from "components/Visualizations/Tabular/TabularChunkedView.vue";
134

145
// legacy/grid_base.mako
156
export { default as LegacyGridView } from "legacy/grid/grid-view";
167

178
// webapps/reports/run_stats.mako
189
export { create_chart, create_histogram } from "reports/run_stats";
19-
20-
// webapps/galaxy/dataset/{ display | tabular_chunked }.mako
21-
export const createTabularDatasetChunkedView = (options) => {
22-
return replaceChildrenWithComponent(options.parent_elt, TabularChunkedView, { options });
23-
};
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<script setup lang="ts">
2+
import { BAlert } from "bootstrap-vue";
3+
import { storeToRefs } from "pinia";
4+
import { computed, ref, watch } from "vue";
5+
6+
import { useDatasetStore } from "@/stores/datasetStore";
7+
import { useUserStore } from "@/stores/userStore";
8+
import { withPrefix } from "@/utils/redirect";
9+
import { errorMessageAsString } from "@/utils/simple-error";
10+
import { bytesToString } from "@/utils/utils";
11+
12+
import Alert from "@/components/Alert.vue";
13+
import TabularChunkedView from "@/components/Dataset/Tabular/TabularChunkedView.vue";
14+
import LoadingSpan from "@/components/LoadingSpan.vue";
15+
import CenterFrame from "@/entry/analysis/modules/CenterFrame.vue";
16+
17+
interface Props {
18+
datasetId: string;
19+
isBinary: boolean;
20+
}
21+
22+
const { getDataset, isLoadingDataset } = useDatasetStore();
23+
24+
const emit = defineEmits(["load"]);
25+
26+
const props = defineProps<Props>();
27+
28+
const contentTruncated = ref<number | null>(null);
29+
const contentChunked = ref<boolean>(false);
30+
const errorMessage = ref<string>("");
31+
const sanitizedJobImported = ref<boolean>(false);
32+
const sanitizedToolId = ref<string | null>(null);
33+
34+
const { isAdmin } = storeToRefs(useUserStore());
35+
36+
const dataset = computed(() => getDataset(props.datasetId));
37+
const datasetUrl = computed(() => `/datasets/${props.datasetId}/display`);
38+
const downloadUrl = computed(() => withPrefix(`${datasetUrl.value}?to_ext=${dataset.value?.file_ext}`));
39+
const isLoading = computed(() => isLoadingDataset(props.datasetId));
40+
const previewUrl = computed(() => `${datasetUrl.value}?preview=True`);
41+
42+
const sanitizedMessage = computed(() => {
43+
const plainText = "Contents are shown as plain text.";
44+
if (sanitizedJobImported.value) {
45+
return `Dataset has been imported. ${plainText}`;
46+
} else if (sanitizedToolId.value) {
47+
return `Dataset created by a tool that is not known to create safe HTML. ${plainText}`;
48+
}
49+
return undefined;
50+
});
51+
52+
watch(
53+
() => props.datasetId,
54+
async () => {
55+
try {
56+
const { headers } = await fetch(withPrefix(previewUrl.value), { method: "HEAD" });
57+
contentChunked.value = !!headers.get("x-content-chunked");
58+
contentTruncated.value = headers.get("x-content-truncated")
59+
? Number(headers.get("x-content-truncated"))
60+
: null;
61+
sanitizedJobImported.value = !!headers.get("x-sanitized-job-imported");
62+
sanitizedToolId.value = headers.get("x-sanitized-tool-id");
63+
errorMessage.value = "";
64+
} catch (e) {
65+
errorMessage.value = errorMessageAsString(e);
66+
console.error(e);
67+
}
68+
},
69+
{ immediate: true },
70+
);
71+
</script>
72+
73+
<template>
74+
<BAlert v-if="errorMessage" variant="danger" show>
75+
{{ errorMessage }}
76+
</BAlert>
77+
<LoadingSpan v-else-if="isLoading || !dataset" message="Loading dataset content" />
78+
<div v-else class="dataset-display h-100">
79+
<Alert v-if="sanitizedMessage" :dismissible="true" variant="warning" data-description="sanitization warning">
80+
{{ sanitizedMessage }}
81+
<span v-if="isAdmin && sanitizedToolId">
82+
<br />
83+
<router-link data-description="allowlist link" to="/admin/sanitize_allow">Review Allowlist</router-link>
84+
if outputs of {{ sanitizedToolId }} are trusted and should be shown as HTML.
85+
</span>
86+
</Alert>
87+
<div v-if="dataset.deleted" id="deleted-data-message" class="errormessagelarge">
88+
You are viewing a deleted dataset.
89+
</div>
90+
<TabularChunkedView v-if="contentChunked" :options="dataset" />
91+
<div v-else class="h-100">
92+
<div v-if="isBinary">
93+
This is a binary (or unknown to Galaxy) dataset of size {{ bytesToString(dataset.file_size) }}. Preview
94+
is not implemented for this filetype. Displaying as ASCII text.
95+
</div>
96+
<div v-if="contentTruncated" class="warningmessagelarge">
97+
<div>
98+
This dataset is large and only the first {{ bytesToString(contentTruncated) }} is shown below.
99+
</div>
100+
<a :href="downloadUrl">Download</a>
101+
</div>
102+
<CenterFrame :src="previewUrl" @load="emit('load')" />
103+
</div>
104+
</div>
105+
</template>

client/src/components/Dataset/DatasetView.vue

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ import { bytesToString } from "@/utils/utils";
1414
import DatasetError from "../DatasetInformation/DatasetError.vue";
1515
import LoadingSpan from "../LoadingSpan.vue";
1616
import DatasetAsImage from "./DatasetAsImage/DatasetAsImage.vue";
17+
import DatasetDisplay from "./DatasetDisplay.vue";
1718
import DatasetState from "./DatasetState.vue";
1819
import Heading from "@/components/Common/Heading.vue";
1920
import DatasetAttributes from "@/components/DatasetInformation/DatasetAttributes.vue";
2021
import DatasetDetails from "@/components/DatasetInformation/DatasetDetails.vue";
2122
import VisualizationsList from "@/components/Visualizations/Index.vue";
2223
import VisualizationFrame from "@/components/Visualizations/VisualizationFrame.vue";
23-
import CenterFrame from "@/entry/analysis/modules/CenterFrame.vue";
2424
2525
const datasetStore = useDatasetStore();
2626
const datatypeStore = useDatatypeStore();
@@ -61,6 +61,13 @@ const downloadUrl = computed(() => withPrefix(`/datasets/${props.datasetId}/disp
6161
const preferredVisualization = computed(
6262
() => dataset.value && datatypeStore.getPreferredVisualization(dataset.value.file_ext),
6363
);
64+
const isBinaryDataset = computed(() => {
65+
if (!dataset.value?.file_ext || !datatypesMapperStore.datatypesMapper) {
66+
return false;
67+
}
68+
return datatypesMapperStore.datatypesMapper.isSubTypeOfAny(dataset.value.file_ext, ["galaxy.datatypes.binary"]);
69+
});
70+
6471
const isImageDataset = computed(() => {
6572
if (!dataset.value?.file_ext || !datatypesMapperStore.datatypesMapper) {
6673
return false;
@@ -93,7 +100,7 @@ watch(
93100

94101
<template>
95102
<LoadingSpan v-if="isLoading || !dataset" message="Loading dataset details" />
96-
<div v-else class="dataset-view d-flex flex-column h-100">
103+
<div v-else class="dataset-view d-flex flex-column">
97104
<header v-if="!displayOnly" :key="`dataset-header-${dataset.id}`" class="dataset-header flex-shrink-0">
98105
<div class="d-flex">
99106
<Heading
@@ -181,18 +188,13 @@ watch(
181188
<FontAwesomeIcon :icon="faBug" class="mr-1" /> Error
182189
</BNavItem>
183190
</BNav>
184-
<div v-if="tab === 'preview'" class="h-100">
191+
<div v-if="tab === 'preview'" class="tab-content-panel">
185192
<VisualizationFrame
186193
v-if="preferredVisualization"
187194
:dataset-id="datasetId"
188195
:visualization="preferredVisualization"
189196
@load="iframeLoading = false" />
190-
<CenterFrame
191-
v-else-if="isPdfDataset"
192-
:src="`/datasets/${datasetId}/display/?preview=True`"
193-
:is-preview="true"
194-
@load="iframeLoading = false" />
195-
<div v-else-if="isAutoDownloadType" class="auto-download-message p-4">
197+
<div v-else-if="isAutoDownloadType && !isPdfDataset" class="auto-download-message p-4">
196198
<div class="alert alert-info">
197199
<h4>Download Required</h4>
198200
<p>This file type ({{ dataset.file_ext }}) will download automatically when accessed directly.</p>
@@ -203,23 +205,14 @@ watch(
203205
</div>
204206
</div>
205207
<DatasetAsImage
206-
v-else-if="isImageDataset"
208+
v-else-if="isImageDataset && !isPdfDataset"
207209
:history-dataset-id="datasetId"
208210
:allow-size-toggle="true"
209211
class="p-3" />
210-
<CenterFrame
211-
v-else
212-
:src="`/datasets/${datasetId}/display/?preview=True`"
213-
:is-preview="true"
214-
@load="iframeLoading = false" />
212+
<DatasetDisplay v-else :dataset-id="datasetId" :is-binary="isBinaryDataset" @load="iframeLoading = false" />
215213
</div>
216-
<div v-else-if="tab === 'raw'" class="h-100">
217-
<CenterFrame
218-
v-if="isPdfDataset"
219-
:src="`/datasets/${datasetId}/display/?preview=True`"
220-
:is-preview="true"
221-
@load="iframeLoading = false" />
222-
<div v-else-if="isAutoDownloadType" class="auto-download-message p-4">
214+
<div v-else-if="tab === 'raw'" class="tab-content-panel">
215+
<div v-if="isAutoDownloadType && !isPdfDataset" class="auto-download-message p-4">
223216
<div class="alert alert-info">
224217
<h4>Download Required</h4>
225218
<p>This file type ({{ dataset.file_ext }}) will download automatically when accessed directly.</p>
@@ -229,11 +222,7 @@ watch(
229222
</a>
230223
</div>
231224
</div>
232-
<CenterFrame
233-
v-else
234-
:src="`/datasets/${datasetId}/display/?preview=True`"
235-
:is-preview="true"
236-
@load="iframeLoading = false" />
225+
<DatasetDisplay v-else :dataset-id="datasetId" :is-binary="isBinaryDataset" @load="iframeLoading = false" />
237226
</div>
238227
<div v-else-if="tab === 'visualize'" class="tab-content-panel">
239228
<VisualizationsList :dataset-id="datasetId" />
@@ -318,8 +307,7 @@ watch(
318307
.tab-content-panel {
319308
display: flex;
320309
flex-direction: column;
321-
overflow: hidden;
322-
overflow-y: auto;
310+
overflow: auto;
323311
height: 100%;
324312
}
325313

client/src/components/Visualizations/Tabular/TabularChunkedView.vue renamed to client/src/components/Dataset/Tabular/TabularChunkedView.vue

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import axios from "axios";
44
import { parse } from "csv-parse/sync";
55
import { computed, onMounted, reactive, ref, watch } from "vue";
66
7+
import type { HDADetailed } from "@/api";
78
import { getAppRoot } from "@/onload/loadConfig";
89
910
interface TabularChunk {
@@ -12,17 +13,14 @@ interface TabularChunk {
1213
data_line_offset: number;
1314
}
1415
16+
interface TabularDataset extends HDADetailed {
17+
metadata_columns?: number;
18+
metadata_column_types?: string[];
19+
metadata_column_names?: string[];
20+
}
21+
1522
interface TabularChunkedViewProps {
16-
options: {
17-
dataset_config: {
18-
id: string;
19-
file_ext: string;
20-
first_data_chunk: TabularChunk;
21-
metadata_columns: number;
22-
metadata_column_types: string[];
23-
metadata_column_names: string[];
24-
};
25-
};
23+
options: TabularDataset;
2624
}
2725
2826
const props = defineProps<TabularChunkedViewProps>();
@@ -37,32 +35,32 @@ const tabularData = reactive<{ rows: string[][] }>({
3735
});
3836
3937
const columns = computed(() => {
40-
const columns = Array(props.options.dataset_config.metadata_columns);
38+
const columns = Array(props.options.metadata_columns);
4139
// for each column_name, inject header
42-
if (props.options.dataset_config.metadata_column_names?.length > 0) {
43-
props.options.dataset_config.metadata_column_names.forEach((column_name, index) => {
40+
if (props.options.metadata_column_names && props.options.metadata_column_names?.length > 0) {
41+
props.options.metadata_column_names.forEach((column_name, index) => {
4442
columns[index] = column_name;
4543
});
4644
}
4745
return columns;
4846
});
4947
5048
const columnStyle = computed(() => {
51-
const columnStyle = Array(props.options.dataset_config.metadata_columns);
52-
if (props.options.dataset_config.metadata_column_types?.length > 0) {
53-
props.options.dataset_config.metadata_column_types.forEach((column_type, index) => {
49+
const columnStyle = Array(props.options.metadata_columns);
50+
if (props.options.metadata_column_types && props.options.metadata_column_types?.length > 0) {
51+
props.options.metadata_column_types.forEach((column_type, index) => {
5452
columnStyle[index] = column_type === "str" || column_type === "list" ? "string-align" : "number-align";
5553
});
5654
}
5755
return columnStyle;
5856
});
5957
6058
const delimiter = computed(() => {
61-
return props.options.dataset_config.file_ext === "csv" ? "," : "\t";
59+
return props.options.file_ext === "csv" ? "," : "\t";
6260
});
6361
6462
const chunkUrl = computed(() => {
65-
return `${getAppRoot()}dataset/display?dataset_id=${props.options.dataset_config.id}`;
63+
return `${getAppRoot()}dataset/display?dataset_id=${props.options.id}`;
6664
});
6765
6866
// Loading more data on user scroll to (near) bottom.
@@ -163,11 +161,8 @@ function nextChunk() {
163161
}
164162
165163
onMounted(() => {
166-
// Render first chunk if available.
167-
if (props.options.dataset_config.first_data_chunk) {
168-
processChunk(props.options.dataset_config.first_data_chunk);
169-
loading.value = false;
170-
}
164+
// Fetch and render first chunk
165+
nextChunk();
171166
});
172167
</script>
173168

client/src/components/DatasetInformation/DatasetAttributes.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ onMounted(async () => {
9191
</script>
9292

9393
<template>
94-
<div aria-labelledby="dataset-attributes-heading">
94+
<div class="dataset-attributes" aria-labelledby="dataset-attributes-heading">
9595
<Heading id="dataset-attributes-heading" h1 separator inline size="md">
9696
{{ localize("Edit Dataset Attributes") }}
9797
</Heading>
@@ -230,3 +230,10 @@ onMounted(async () => {
230230
</div>
231231
</div>
232232
</template>
233+
234+
<style>
235+
.dataset-attributes {
236+
overflow-x: hidden;
237+
overflow-y: auto;
238+
}
239+
</style>

client/src/components/DatasetInformation/DatasetDetails.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ onUnmounted(() => {
155155
display: flex;
156156
flex-direction: column;
157157
gap: 1rem;
158-
158+
overflow-x: hidden;
159+
overflow-y: auto;
159160
.dataset-peek {
160161
word-break: break-all;
161162
}

client/src/components/Visualizations/VisualizationFrame.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ onMounted(() => {
9595
</script>
9696

9797
<template>
98-
<div class="position-relative h-100">
98+
<div class="position-relative h-100 overflow-hidden">
9999
<div v-if="isLoading" class="iframe-loading bg-light">
100100
<LoadingSpan message="Loading preview" />
101101
</div>

0 commit comments

Comments
 (0)