Skip to content

Commit ab20c54

Browse files
committed
chore: restructure preview
1 parent 4044594 commit ab20c54

12 files changed

Lines changed: 1044 additions & 489 deletions

frontend/src/components/inspect-file/file-detail.vue

Lines changed: 35 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
/>
1010

1111
<div v-if="file" class="q-my-lg">
12+
<!-- YAML/Text Preview -->
1213
<div v-if="isYaml" class="q-mb-lg">
1314
<h2 class="text-h4 q-mb-md">Content Preview</h2>
1415
<div
@@ -20,188 +21,136 @@
2021
}}</pre>
2122
</div>
2223
<div v-else class="row items-center q-gutter-sm text-grey-7">
23-
<q-spinner-dots size="1.5em" />
24-
<span>Loading content...</span>
24+
<q-spinner-dots size="1.5em" /> <span>Loading content...</span>
2525
</div>
2626
</div>
2727

28+
<!-- Binary/ROS Preview -->
2829
<div v-else-if="displayTopics && preview.isReaderReady.value">
29-
<FileTopicList
30-
:file="file"
30+
<FileTopicTable
31+
:topics="file.topics"
3132
:is-loading="isLoading"
32-
:reader-ready="preview.isReaderReady.value"
3333
:previews="preview.topicPreviews"
3434
:loading-state="preview.topicLoadingState"
3535
:topic-errors="preview.topicErrors"
36-
:format-payload="preview.formatPayload"
3736
@load-preview="preview.fetchTopicMessages"
38-
@redirect-related="redirectToRelated"
3937
/>
4038
</div>
4139

40+
<!-- Fallback / Unsupported -->
4241
<div
4342
v-else-if="!displayTopics && !isLoading"
4443
class="text-center q-pa-xl bg-grey-1 rounded-borders border-dashed text-grey-7"
4544
>
4645
<q-icon name="sym_o_description" size="4em" class="q-mb-md" />
4746
<div class="text-h6">No Preview Available</div>
4847
<div class="text-caption q-mt-xs">
49-
Preview is not yet ready or currently not supported for
48+
Preview not supported for
5049
<span class="text-weight-bold">.{{ fileExtension }}</span>
51-
files.
5250
</div>
53-
<q-btn
54-
label="Download File"
55-
color="primary"
56-
flat
57-
icon="sym_o_download"
58-
class="q-mt-md"
59-
@click="handleDownload"
60-
/>
6151
</div>
6252

6353
<FileHistory :events="events" />
6454

6555
<div
66-
v-if="preview.readerError.value && displayTopics"
56+
v-if="preview.readerError.value"
6757
class="q-my-md text-negative text-center"
6858
>
69-
<q-icon name="sym_o_warning" />
70-
{{ preview.readerError.value }}
59+
<q-icon name="warning" /> {{ preview.readerError.value }}
7160
</div>
7261
</div>
7362

7463
<div v-else class="text-center q-pa-md">
7564
<q-spinner size="3em" color="primary" />
76-
<div class="text-grey q-mt-sm">Loading file details...</div>
65+
<div class="text-grey q-mt-sm">Loading file...</div>
7766
</div>
7867
</template>
7968

8069
<script setup lang="ts">
8170
import { FileState, FileType } from '@common/enum';
8271
import { copyToClipboard, Notify } from 'quasar';
83-
import { useRosmsgPreview } from 'src/composables/use-rosmsg-preview';
8472
import {
8573
registerNoPermissionErrorHandler,
8674
useFile,
8775
useFileEvents,
8876
} from 'src/hooks/query-hooks';
8977
import { useFileUUID } from 'src/hooks/router-hooks';
90-
import ROUTES from 'src/router/routes';
9178
import { _downloadFile } from 'src/services/generic';
9279
import { downloadFile } from 'src/services/queries/file';
9380
import { computed, ref, watch } from 'vue';
94-
import { useRouter } from 'vue-router';
9581
import FileHeader from './file-header.vue';
9682
import FileHistory from './file-history.vue';
97-
import FileTopicList from './file-topic-list.vue';
9883
99-
const $router = useRouter();
100-
const fileUuid = useFileUUID();
84+
import { useRosmsgPreview } from '../../composables/use-rosmsg-preview';
85+
import FileTopicTable from './file-topic-table.vue';
10186
102-
// --- Data Fetching ---
87+
const fileUuid = useFileUUID();
10388
const { isLoading, data: file, error, isLoadingError } = useFile(fileUuid);
10489
registerNoPermissionErrorHandler(isLoadingError, fileUuid, 'file', error);
10590
const { data: events } = useFileEvents(fileUuid);
10691
10792
const preview = useRosmsgPreview();
10893
const yamlContent = ref<string | undefined>(undefined);
10994
110-
const fileExtension = computed(() => {
111-
const name = file.value?.filename ?? '';
112-
return name.split('.').pop()?.toLowerCase() ?? '';
113-
});
114-
115-
const isYaml = computed(() => {
116-
return ['yml', 'yaml'].includes(fileExtension.value);
117-
});
118-
95+
const fileExtension = computed(
96+
() => file.value?.filename?.split('.').pop()?.toLowerCase() ?? '',
97+
);
98+
const isYaml = computed(() => ['yml', 'yaml'].includes(fileExtension.value));
11999
const isSupportedBinary = computed(() => {
120100
if (!file.value) return false;
121-
const isBagType = file.value.type === FileType.BAG;
122-
const isMcapType = file.value.type === FileType.MCAP;
123-
const isDatabase3 = file.value.type === FileType.DB3;
124-
return (isBagType || isMcapType) && !isDatabase3;
101+
return (
102+
(file.value.type === FileType.BAG ||
103+
file.value.type === FileType.MCAP) &&
104+
file.value.type !== FileType.DB3
105+
);
125106
});
126-
127107
const displayTopics = computed(
128108
() => file.value?.state === FileState.OK && isSupportedBinary.value,
129109
);
130110
131-
// --- Initialization Logic ---
111+
// --- Init ---
132112
watch(
133113
() => file.value,
134114
async (currentFile) => {
135-
// Guard clauses
136115
if (
137116
!currentFile ||
138117
currentFile.state !== FileState.OK ||
139118
preview.isReaderReady.value
140-
) {
119+
)
141120
return;
142-
}
143121
144122
try {
145-
const dynamicUrl = await downloadFile(
146-
currentFile.uuid,
147-
false,
148-
true,
149-
);
123+
const url = await downloadFile(currentFile.uuid, false, true);
150124
151-
// 1. Handle Text Files (YAML)
152125
if (isYaml.value) {
153-
console.log('Loading YAML content...');
154-
const response = await fetch(dynamicUrl);
155-
yamlContent.value = response.ok
156-
? await response.text()
157-
: `Error loading content: ${response.statusText}`;
158-
return;
159-
}
160-
161-
// 2. Handle Supported Binaries
162-
if (isSupportedBinary.value) {
163-
console.log(`Initializing preview for ${currentFile.type}...`);
164-
const strategyType =
126+
const results = await fetch(url);
127+
yamlContent.value = results.ok
128+
? await results.text()
129+
: 'Error loading content';
130+
} else if (isSupportedBinary.value) {
131+
const type =
165132
currentFile.type === FileType.BAG ? 'rosbag' : 'mcap';
166-
await preview.init(dynamicUrl, strategyType);
167-
return;
133+
await preview.init(url, type);
168134
}
169-
170-
// 3. Unsupported files: Do nothing (Template renders placeholder)
171-
console.log(`No preview strategy for .${fileExtension.value}`);
172-
} catch (init_error: unknown) {
173-
console.error('Error setting up preview:', init_error);
135+
} catch (error_) {
136+
console.error(error_);
174137
}
175138
},
176139
{ immediate: true },
177140
);
178141
179142
// --- Actions ---
180-
const handleDownload = (): Promise<void> =>
143+
const handleDownload = (): void =>
181144
_downloadFile(file.value?.uuid ?? '', file.value?.filename ?? '');
182145
const copyHash = (): Promise<void> => copyToClipboard(file.value?.hash ?? '');
183146
const copyUuid = (): Promise<void> => copyToClipboard(file.value?.uuid ?? '');
184-
185147
async function copyPublicLink(): Promise<void> {
186148
if (!fileUuid.value) return;
187149
const link = await downloadFile(fileUuid.value, false);
188150
await copyToClipboard(link);
189151
Notify.create({
190152
message: 'Copied: Link valid for 7 days',
191153
color: 'positive',
192-
timeout: 2000,
193-
});
194-
}
195-
196-
async function redirectToRelated(): Promise<void> {
197-
if (!file.value?.relatedFileUuid) return;
198-
await $router.push({
199-
name: ROUTES.FILE.routeName,
200-
params: {
201-
projectUuid: file.value.mission.project.uuid,
202-
missionUuid: file.value.mission.uuid,
203-
file_uuid: file.value.relatedFileUuid,
204-
},
205154
});
206155
}
207156
</script>
@@ -210,8 +159,6 @@ async function redirectToRelated(): Promise<void> {
210159
.text-code {
211160
font-family: monospace;
212161
font-size: 13px;
213-
line-height: 1.5;
214-
color: #333;
215162
}
216163
.border-solid {
217164
border: 1px solid #e0e0e0;

0 commit comments

Comments
 (0)