Skip to content
Merged
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
7 changes: 7 additions & 0 deletions client/dive-common/components/Viewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2152,9 +2152,13 @@ export default defineComponent({
errorEl.innerHTML = getResponseError(err);
loadError.value = errorEl.innerText
.concat(". If you don't know how to resolve this, please contact the server administrator.");
emit('load-error', loadError.value);
throw err;
}
};
function forwardLoadError(message: string, largeImage?: boolean) {
emit('load-error', message, largeImage);
}
loadData();

/**
Expand Down Expand Up @@ -2532,6 +2536,7 @@ export default defineComponent({
imageData,
lineChartData,
loadError,
forwardLoadError,
multiSelectActive,
lassoModeActive: lassoMode.lassoModeActive,
lassoDrawing: lassoMode.lassoDrawing,
Expand Down Expand Up @@ -3005,6 +3010,7 @@ export default defineComponent({
filterId: `imageEnhancements-${camera}`,
}"
@large-image-warning="$emit('large-image-warning', true)"
@load-error="forwardLoadError"
>
<LayerManager :camera="camera" />
</component>
Expand Down Expand Up @@ -3103,6 +3109,7 @@ export default defineComponent({
filterId: `imageEnhancements-${camera}`,
}"
@large-image-warning="$emit('large-image-warning', true)"
@load-error="forwardLoadError"
>
<LayerManager :camera="camera" />
</component>
Expand Down
27 changes: 27 additions & 0 deletions client/platform/desktop/backend/native/common.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,30 @@ beforeEach(() => {
},
},
},
projectidMulticamMovedSource: {
'meta.json': JSON.stringify({
version: 1,
id: 'projectidMulticamMovedSource',
name: 'movedStereo',
type: 'multi',
fps: 5,
originalBasePath: '',
multiCam: {
defaultDisplay: 'left',
cameras: {
left: {
type: 'image-sequence',
originalBasePath: '/home/user/data/movedStereo/left',
},
right: {
type: 'image-sequence',
originalBasePath: '/home/user/data/movedStereo/right',
},
},
},
}),
'result_whatever.json': JSON.stringify({}),
},
projectidFrameMetadata: {
'meta.json': JSON.stringify({
version: 1,
Expand Down Expand Up @@ -2816,6 +2840,9 @@ describe('native.common', () => {
await expect(common.checkDataset(settings, 'projectid3Bad')).rejects.toThrow('missing dataset json');
await expect(common.checkDataset(settings, 'projectid5Bad')).rejects.toThrow('missing track json file');
await expect(common.checkDataset(settings, 'missingFolder')).rejects.toThrow('missing project directory');
await expect(common.checkDataset(settings, 'projectidMulticamMovedSource')).rejects.toThrow(
'Dataset movedStereo does not contain source files at /home/user/data/movedStereo/left, /home/user/data/movedStereo/right',
);
});

it('checkDataset does not create directories for missing datasets', async () => {
Expand Down
15 changes: 10 additions & 5 deletions client/platform/desktop/backend/native/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2061,11 +2061,16 @@ async function checkDataset(
): Promise<boolean> {
const projectDirData = await getValidatedProjectDir(settings, datasetId);
const projectMetaData = await loadJsonConfig(projectDirData.datasetFileAbsPath);
if (projectMetaData.originalBasePath !== '') {
const exists = await fs.pathExists(projectMetaData.originalBasePath);
if (!exists) {
throw new Error(`Dataset ${projectMetaData.name} does not contain source files at ${projectMetaData.originalBasePath}`);
}
const sourcePaths = [
...new Set([
projectMetaData.originalBasePath,
...Object.values(projectMetaData.multiCam?.cameras ?? {}).map((camera) => camera.originalBasePath),
].filter((path) => path)),
];
const exists = await Promise.all(sourcePaths.map((path) => fs.pathExists(path)));
const missing = sourcePaths.filter((_, index) => !exists[index]);
if (missing.length) {
throw new Error(`Dataset ${projectMetaData.name} does not contain source files at ${missing.join(', ')}`);
}
if (projectMetaData.error && projectMetaData.error !== '') {
throw new Error(`Dataset ${projectMetaData.name} contains error: ${projectMetaData.error}`);
Expand Down
20 changes: 20 additions & 0 deletions client/platform/desktop/frontend/components/ViewerLoader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,24 @@ export default defineComponent({
return results;
});

let loadFailed = false;
async function handleLoadError(message: string, largeImage?: boolean) {
if (loadFailed) {
return;
}
loadFailed = true;
if (largeImage) {
await largeImageWarning();
} else {
await prompt({
title: 'Error Loading Data',
text: [message],
positiveButton: 'Okay',
});
}
router.push({ name: 'recent' });
}

async function largeImageWarning() {
await prompt({
title: 'Large Image Warning',
Expand Down Expand Up @@ -2565,6 +2583,7 @@ export default defineComponent({
readOnlyMode,
runningPipelines,
largeImageWarning,
handleLoadError,
timeFilter,
handleTextQuerySubmit,
handleTextQueryInit,
Expand Down Expand Up @@ -2620,6 +2639,7 @@ export default defineComponent({
@return-to-current-annotations="returnToCurrentAnnotations"
@change-camera="changeCamera"
@large-image-warning="largeImageWarning()"
@load-error="handleLoadError"
@text-query-submit="handleTextQuerySubmit"
@text-query-init="handleTextQueryInit"
@text-query-all-frames="handleTextQueryAllFrames"
Expand Down
21 changes: 21 additions & 0 deletions client/platform/web-girder/views/ViewerLoader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { parentDatasetId } from 'dive-common/compositeDatasetId';
import { getMultiCamCameraCount } from 'dive-common/pipelineMenuFilters';
import { webExcludedPipelineTerms } from 'dive-common/constants';
import { convertLargeImage } from 'platform/web-girder/api/rpc.service';
import type { RawLocation } from 'vue-router';
import { useRouter, useRoute } from 'vue-router/composables';
import { ANNOTATION_SOURCE_QUERY } from 'dive-common/scoring/viewerNavigation';
import { parseViewerFocus } from 'dive-common/review/viewerNavigation';
Expand Down Expand Up @@ -544,6 +545,24 @@ export default defineComponent({
}
}

let loadFailed = false;
async function handleLoadError(message: string, largeImage?: boolean) {
if (loadFailed) {
return;
}
loadFailed = true;
if (largeImage) {
await largeImageWarning();
} else {
await prompt({
title: 'Error Loading Data',
text: [message],
positiveButton: 'Okay',
});
}
router.push(locationRoute.value as RawLocation);
}

const annotationSourceLabel = computed(() => {
const value = route.query[ANNOTATION_SOURCE_QUERY];
return typeof value === 'string' ? value : '';
Expand Down Expand Up @@ -571,6 +590,7 @@ export default defineComponent({
routeRevision,
routeSet,
largeImageWarning,
handleLoadError,
typeList,
subTypeList,
cameraNumbers,
Expand Down Expand Up @@ -638,6 +658,7 @@ export default defineComponent({
:auto-populate-status="segmentationStatus"
@return-to-current-annotations="returnToCurrentAnnotations"
@large-image-warning="largeImageWarning()"
@load-error="handleLoadError"
@update:set="routeSet"
@change-camera="changeCamera"
@stereo-annotation-complete="handleStereoAnnotationComplete"
Expand Down
35 changes: 28 additions & 7 deletions client/src/components/annotators/ImageAnnotator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,14 @@ export default defineComponent({
}
return imgInternal;
}
function failedToLoad(imgInternal: ImageDataItemInternal, loaded: boolean) {
if (loaded || local.imgs[imgInternal.frame] !== imgInternal) {
return false;
}
loadingImage.value = false;
emit('load-error', `Could not load ${imgInternal.filename}. The file may have been moved or deleted.`);
return true;
}
/**
* Draw image to the GeoJS map, and update the map dimensions if they have changed.
*/
Expand Down Expand Up @@ -277,8 +285,8 @@ export default defineComponent({
if (!imgInternal.cached) {
loadingImage.value = true;
// else wait for it to load
await imgInternal.onloadPromise;
if (imgInternal.frame === data.frame) {
const loaded = await imgInternal.onloadPromise;
if (imgInternal.frame === data.frame && !failedToLoad(imgInternal, loaded)) {
loadingImage.value = false;
// if the seek hasn't changed since the image completed loading, draw it.
drawImage(imgInternal.image);
Expand Down Expand Up @@ -368,11 +376,21 @@ export default defineComponent({

if (local.imgs.length) {
const imgInternal = cacheFrame(0);
imgInternal.onloadPromise.then(async () => {
imgInternal.onloadPromise.then(async (loaded) => {
if (imgInternal.frame !== data.frame || failedToLoad(imgInternal, loaded)) {
return;
}
try {
await imgInternal.image.decode();
} catch (error) {
emit('large-image-warning', true);
if (imgInternal.frame !== data.frame) {
return;
}
loadingImage.value = false;
emit('load-error', `Could not display ${imgInternal.filename}. Its resolution may be too large for this browser or hardware.`, true);
return;
}
if (imgInternal.frame !== data.frame) {
return;
}
initializeViewer(imgInternal.image.naturalWidth, imgInternal.image.naturalHeight);
Expand Down Expand Up @@ -428,8 +446,8 @@ export default defineComponent({
drawImage(imgInternal.image);
if (!imgInternal.cached) {
loadingImage.value = true;
imgInternal.onloadPromise.then(() => {
if (imgInternal.frame === data.frame) {
imgInternal.onloadPromise.then((loaded) => {
if (imgInternal.frame === data.frame && !failedToLoad(imgInternal, loaded)) {
loadingImage.value = false;
drawImage(imgInternal.image);
}
Expand All @@ -440,7 +458,10 @@ export default defineComponent({
return;
}
const imgInternal = cacheFrame(0);
imgInternal.onloadPromise.then(() => {
imgInternal.onloadPromise.then((loaded) => {
if (failedToLoad(imgInternal, loaded)) {
return;
}
initializeViewer(imgInternal.image.naturalWidth, imgInternal.image.naturalHeight);
const quadFeatureLayer = geoViewer.value.createLayer('feature', {
features: ['quad'],
Expand Down
3 changes: 2 additions & 1 deletion client/src/components/annotators/VideoAnnotator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export default defineComponent({
default: 'imageEnhancements',
},
},
setup(props) {
setup(props, { emit }) {
const cameraInitializer = injectCameraInitializer();
const {
state: data,
Expand Down Expand Up @@ -168,6 +168,7 @@ export default defineComponent({
}
function logError(event: ErrorEvent) {
console.error('Media failed to initialize', event);
emit('load-error', 'Could not load the video. The file may have been moved or deleted.');
}
function setVolume(level: number) {
video.volume = level;
Expand Down
Loading