Added handling of the case when a shared files are no longer available

main
Maya 5 years ago
parent ddf22686f6
commit 0835f26e25

@ -180,6 +180,7 @@ Standard JS events are used.
- canvas.dragshape => {id: number}
- canvas.resizeshape => {id: number}
- canvas.contextmenu => { mouseEvent: MouseEvent, objectState: ObjectState, pointID: number }
- canvas.error => { exception: Error }
```
### WEB

@ -130,6 +130,7 @@ export enum UpdateReasons {
DRAG_CANVAS = 'drag_canvas',
ZOOM_CANVAS = 'zoom_canvas',
CONFIG_UPDATED = 'config_updated',
DATA_FAILED = 'data_failed',
}
export enum Mode {
@ -163,6 +164,7 @@ export interface CanvasModel {
readonly selected: any;
geometry: Geometry;
mode: Mode;
exception: Error | null;
zoom(x: number, y: number, direction: number): void;
move(topOffset: number, leftOffset: number): void;
@ -216,6 +218,7 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel {
splitData: SplitData;
selected: any;
mode: Mode;
exception: Error | null;
};
public constructor() {
@ -275,6 +278,7 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel {
},
selected: null,
mode: Mode.IDLE,
exception: null,
};
}
@ -389,6 +393,8 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel {
this.notify(UpdateReasons.OBJECTS_UPDATED);
})
.catch((exception: any): void => {
this.data.exception = exception;
this.notify(UpdateReasons.DATA_FAILED);
throw exception;
});
}
@ -709,4 +715,7 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel {
public get mode(): Mode {
return this.data.mode;
}
public get exception(): Error {
return this.data.exception;
}
}

@ -1172,6 +1172,14 @@ export class CanvasViewImpl implements CanvasView, Listener {
this.mode = Mode.IDLE;
this.canvas.style.cursor = '';
}
else if (reason === UpdateReasons.DATA_FAILED) {
const event: CustomEvent = new CustomEvent('canvas.error', {
detail: {
exception: model.exception,
},
});
this.canvas.dispatchEvent(event);
}
if (model.imageBitmap && [UpdateReasons.IMAGE_CHANGED, UpdateReasons.OBJECTS_UPDATED].includes(reason)) {
this.redrawBitmap();

@ -20,7 +20,9 @@ onmessage = (e) => {
.catch((error) => {
postMessage({
id: e.data.id,
error,
error: error,
status: error.response.status,
responseData: error.response.data,
isSuccess: false,
});
});

@ -31,7 +31,7 @@
if (e.data.isSuccess) {
requests[e.data.id].resolve(e.data.responseData);
} else {
requests[e.data.id].reject(e.data.error);
requests[e.data.id].reject({ error: e.data.error, response: { status: e.data.status, data: e.data.responseData } });
}
delete requests[e.data.id];
@ -566,6 +566,8 @@
},
);
} catch (errorData) {
errorData.message = "";
errorData.response.data = String.fromCharCode.apply(null, new Uint8Array(errorData.response.data));
throw generateError(errorData);
}

@ -185,6 +185,7 @@ export enum AnnotationActionTypes {
SAVE_LOGS_FAILED = 'SAVE_LOGS_FAILED',
INTERACT_WITH_CANVAS = 'INTERACT_WITH_CANVAS',
SET_AI_TOOLS_REF = 'SET_AI_TOOLS_REF',
GET_DATA_FAILED = 'GET_DATA_FAILED',
}
export function saveLogsAsync(): ThunkAction {
@ -215,6 +216,15 @@ export function changeWorkspace(workspace: Workspace): AnyAction {
};
}
export function getDataFailed(error: any): AnyAction {
return {
type: AnnotationActionTypes.GET_DATA_FAILED,
payload: {
error: error,
},
};
}
export function addZLayer(): AnyAction {
return {
type: AnnotationActionTypes.ADD_Z_LAYER,
@ -930,7 +940,16 @@ export function getJobAsync(tid: number, jid: number, initialFrame: number, init
const frameData = await job.frames.get(frameNumber);
// call first getting of frame data before rendering interface
// to load and decode first chunk
await frameData.data();
try{
await frameData.data();
} catch(error){
dispatch({
type: AnnotationActionTypes.GET_DATA_FAILED,
payload: {
error,
},
});
}
const states = await job.annotations.get(frameNumber, showAllInterpolationTracks, filters);
const [minZ, maxZ] = computeZRange(states);
const colors = [...cvat.enums.colors];

@ -87,6 +87,7 @@ interface Props {
onSwitchGrid(enabled: boolean): void;
onSwitchAutomaticBordering(enabled: boolean): void;
onFetchAnnotation(): void;
onGetDataFailed(error: any): void;
}
export default class CanvasWrapperComponent extends React.PureComponent<Props> {
@ -299,10 +300,17 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
canvasInstance.html().removeEventListener('canvas.splitted', this.onCanvasTrackSplitted);
canvasInstance.html().removeEventListener('canvas.contextmenu', this.onCanvasPointContextMenu);
canvasInstance.html().removeEventListener('canvas.error', this.onCanvasErrorOccurrence);
window.removeEventListener('resize', this.fitCanvas);
}
private onCanvasErrorOccurrence = (event: any): void => {
const { exception } = event.detail;
const { onGetDataFailed } = this.props;
onGetDataFailed(exception);
}
private onCanvasShapeDrawn = (event: any): void => {
const { jobInstance, activeLabelID, activeObjectType, frame, onShapeDrawn, onCreateAnnotations } = this.props;
@ -682,6 +690,7 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
canvasInstance.html().addEventListener('canvas.splitted', this.onCanvasTrackSplitted);
canvasInstance.html().addEventListener('canvas.contextmenu', this.onCanvasPointContextMenu);
canvasInstance.html().addEventListener('canvas.error', this.onCanvasErrorOccurrence);
}
public render(): JSX.Element {

@ -27,6 +27,7 @@ import {
addZLayer,
switchZLayer,
fetchAnnotationsAsync,
getDataFailed,
} from 'actions/annotation-actions';
import {
switchGrid,
@ -119,6 +120,7 @@ interface DispatchToProps {
onSwitchGrid(enabled: boolean): void;
onSwitchAutomaticBordering(enabled: boolean): void;
onFetchAnnotation(): void;
onGetDataFailed(error: any): void;
}
function mapStateToProps(state: CombinedState): StateToProps {
@ -298,6 +300,9 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
onFetchAnnotation(): void {
dispatch(fetchAnnotationsAsync());
},
onGetDataFailed(error: any): void {
dispatch(getDataFailed(error));
},
};
}

@ -177,6 +177,18 @@ export default (state = defaultState, action: AnyAction): AnnotationState => {
},
};
}
case AnnotationActionTypes.GET_DATA_FAILED: {
return {
...state,
player: {
...state.player,
frame: {
...state.player.frame,
fetching: false,
},
},
}
}
case AnnotationActionTypes.CHANGE_FRAME: {
return {
...state,

@ -936,6 +936,21 @@ export default function (state = defaultState, action: AnyAction): Notifications
},
};
}
case AnnotationActionTypes.GET_DATA_FAILED: {
return {
...state,
errors: {
...state.errors,
annotation: {
...state.errors.annotation,
jobFetching: {
message: 'Could not fetch frame data from the server',
reason: action.payload.error,
},
},
},
};
}
case BoundariesActionTypes.RESET_AFTER_ERROR:
case AuthActionTypes.LOGOUT_SUCCESS: {
return { ...defaultState };

Loading…
Cancel
Save