Merge pull request #1318 from opencv/bs/batch_of_fixes

React UI: Batch of fixes
main
Dmitry Kalinin 6 years ago committed by GitHub
commit 76d0c6b599
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1208,11 +1208,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
let shapeSizeElement: ShapeSizeElement | null = null; let shapeSizeElement: ShapeSizeElement | null = null;
let resized = false; let resized = false;
(shape as any).resize().on('resizestart', (e: any): void => { (shape as any).resize().on('resizestart', (): void => {
if (e.detail.event.detail.event.button === 2) {
e.preventDefault();
return;
}
this.mode = Mode.RESIZE; this.mode = Mode.RESIZE;
if (state.shapeType === 'rectangle') { if (state.shapeType === 'rectangle') {
shapeSizeElement = displayShapeSize(this.adoptedContent, this.adoptedText); shapeSizeElement = displayShapeSize(this.adoptedContent, this.adoptedText);

@ -161,6 +161,11 @@ SVG.Element.prototype.resize = function constructor(...args: any): any {
if (!handler) { if (!handler) {
originalResize.call(this, ...args); originalResize.call(this, ...args);
handler = this.remember('_resizeHandler'); handler = this.remember('_resizeHandler');
handler.resize = function(e: any) {
if (e.detail.event.button === 0) {
return handler.constructor.prototype.resize.call(this, e);
}
}
handler.update = function(e: any) { handler.update = function(e: any) {
this.m = this.el.node.getScreenCTM().inverse(); this.m = this.el.node.getScreenCTM().inverse();
return handler.constructor.prototype.update.call(this, e); return handler.constructor.prototype.update.call(this, e);

@ -427,7 +427,10 @@
for (const object of objectsForMerge) { for (const object of objectsForMerge) {
object.removed = true; object.removed = true;
} }
}, [...objectsForMerge.map((object) => object.clientID), trackModel.clientID]); }, [
...objectsForMerge
.map((object) => object.clientID), trackModel.clientID,
], objectStates[0].frame);
} }
split(objectState, frame) { split(objectState, frame) {
@ -522,7 +525,7 @@
object.removed = true; object.removed = true;
prevTrack.removed = false; prevTrack.removed = false;
nextTrack.removed = false; nextTrack.removed = false;
}, [object.clientID, prevTrack.clientID, nextTrack.clientID]); }, [object.clientID, prevTrack.clientID, nextTrack.clientID], frame);
} }
group(objectStates, reset) { group(objectStates, reset) {
@ -554,7 +557,7 @@
objectsForGroup.forEach((object, idx) => { objectsForGroup.forEach((object, idx) => {
object.group = redoGroups[idx]; object.group = redoGroups[idx];
}); });
}, objectsForGroup.map((object) => object.clientID)); }, objectsForGroup.map((object) => object.clientID), objectStates[0].frame);
return groupIdx; return groupIdx;
} }
@ -790,7 +793,7 @@
importedArray.forEach((object) => { importedArray.forEach((object) => {
object.removed = false; object.removed = false;
}); });
}, importedArray.map((object) => object.clientID)); }, importedArray.map((object) => object.clientID), objectStates[0].frame);
} }
select(objectStates, x, y) { select(objectStates, x, y) {

@ -12,17 +12,18 @@ class AnnotationHistory {
get() { get() {
return { return {
undo: this._undo.map((undo) => undo.action), undo: this._undo.map((undo) => [undo.action, undo.frame]),
redo: this._redo.map((redo) => redo.action), redo: this._redo.map((redo) => [redo.action, redo.frame]),
}; };
} }
do(action, undo, redo, clientIDs) { do(action, undo, redo, clientIDs, frame) {
const actionItem = { const actionItem = {
clientIDs, clientIDs,
action, action,
undo, undo,
redo, redo,
frame,
}; };
this._undo = this._undo.slice(-MAX_HISTORY_LENGTH + 1); this._undo = this._undo.slice(-MAX_HISTORY_LENGTH + 1);

@ -178,7 +178,7 @@
injection.groups.max = Math.max(injection.groups.max, this.group); injection.groups.max = Math.max(injection.groups.max, this.group);
} }
_saveLock(lock) { _saveLock(lock, frame) {
const undoLock = this.lock; const undoLock = this.lock;
const redoLock = lock; const redoLock = lock;
@ -186,12 +186,12 @@
this.lock = undoLock; this.lock = undoLock;
}, () => { }, () => {
this.lock = redoLock; this.lock = redoLock;
}, [this.clientID]); }, [this.clientID], frame);
this.lock = lock; this.lock = lock;
} }
_saveColor(color) { _saveColor(color, frame) {
const undoColor = this.color; const undoColor = this.color;
const redoColor = color; const redoColor = color;
@ -199,12 +199,12 @@
this.color = undoColor; this.color = undoColor;
}, () => { }, () => {
this.color = redoColor; this.color = redoColor;
}, [this.clientID]); }, [this.clientID], frame);
this.color = color; this.color = color;
} }
_saveHidden(hidden) { _saveHidden(hidden, frame) {
const undoHidden = this.hidden; const undoHidden = this.hidden;
const redoHidden = hidden; const redoHidden = hidden;
@ -212,12 +212,12 @@
this.hidden = undoHidden; this.hidden = undoHidden;
}, () => { }, () => {
this.hidden = redoHidden; this.hidden = redoHidden;
}, [this.clientID]); }, [this.clientID], frame);
this.hidden = hidden; this.hidden = hidden;
} }
_saveLabel(label) { _saveLabel(label, frame) {
const undoLabel = this.label; const undoLabel = this.label;
const redoLabel = label; const redoLabel = label;
const undoAttributes = { ...this.attributes }; const undoAttributes = { ...this.attributes };
@ -232,10 +232,10 @@
}, () => { }, () => {
this.label = redoLabel; this.label = redoLabel;
this.attributes = redoAttributes; this.attributes = redoAttributes;
}, [this.clientID]); }, [this.clientID], frame);
} }
_saveAttributes(attributes) { _saveAttributes(attributes, frame) {
const undoAttributes = { ...this.attributes }; const undoAttributes = { ...this.attributes };
for (const attrID of Object.keys(attributes)) { for (const attrID of Object.keys(attributes)) {
@ -248,7 +248,7 @@
this.attributes = undoAttributes; this.attributes = undoAttributes;
}, () => { }, () => {
this.attributes = redoAttributes; this.attributes = redoAttributes;
}, [this.clientID]); }, [this.clientID], frame);
} }
_validateStateBeforeSave(frame, data, updated) { _validateStateBeforeSave(frame, data, updated) {
@ -368,7 +368,7 @@
} }
} }
delete(force) { delete(frame, force) {
if (!this.lock || force) { if (!this.lock || force) {
this.removed = true; this.removed = true;
@ -376,7 +376,7 @@
this.removed = false; this.removed = false;
}, () => { }, () => {
this.removed = true; this.removed = true;
}, [this.clientID]); }, [this.clientID], frame);
} }
return this.removed; return this.removed;
@ -392,7 +392,7 @@
this.shapeType = null; this.shapeType = null;
} }
_savePinned(pinned) { _savePinned(pinned, frame) {
const undoPinned = this.pinned; const undoPinned = this.pinned;
const redoPinned = pinned; const redoPinned = pinned;
@ -400,7 +400,7 @@
this.pinned = undoPinned; this.pinned = undoPinned;
}, () => { }, () => {
this.pinned = redoPinned; this.pinned = redoPinned;
}, [this.clientID]); }, [this.clientID], frame);
this.pinned = pinned; this.pinned = pinned;
} }
@ -483,7 +483,7 @@
}; };
} }
_savePoints(points) { _savePoints(points, frame) {
const undoPoints = this.points; const undoPoints = this.points;
const redoPoints = points; const redoPoints = points;
@ -491,12 +491,12 @@
this.points = undoPoints; this.points = undoPoints;
}, () => { }, () => {
this.points = redoPoints; this.points = redoPoints;
}, [this.clientID]); }, [this.clientID], frame);
this.points = points; this.points = points;
} }
_saveOccluded(occluded) { _saveOccluded(occluded, frame) {
const undoOccluded = this.occluded; const undoOccluded = this.occluded;
const redoOccluded = occluded; const redoOccluded = occluded;
@ -504,12 +504,12 @@
this.occluded = undoOccluded; this.occluded = undoOccluded;
}, () => { }, () => {
this.occluded = redoOccluded; this.occluded = redoOccluded;
}, [this.clientID]); }, [this.clientID], frame);
this.occluded = occluded; this.occluded = occluded;
} }
_saveZOrder(zOrder) { _saveZOrder(zOrder, frame) {
const undoZOrder = this.zOrder; const undoZOrder = this.zOrder;
const redoZOrder = zOrder; const redoZOrder = zOrder;
@ -517,7 +517,7 @@
this.zOrder = undoZOrder; this.zOrder = undoZOrder;
}, () => { }, () => {
this.zOrder = redoZOrder; this.zOrder = redoZOrder;
}, [this.clientID]); }, [this.clientID], frame);
this.zOrder = zOrder; this.zOrder = zOrder;
} }
@ -538,39 +538,39 @@
// Now when all fields are validated, we can apply them // Now when all fields are validated, we can apply them
if (updated.label) { if (updated.label) {
this._saveLabel(data.label); this._saveLabel(data.label, frame);
} }
if (updated.attributes) { if (updated.attributes) {
this._saveAttributes(data.attributes); this._saveAttributes(data.attributes, frame);
} }
if (updated.points && fittedPoints.length) { if (updated.points && fittedPoints.length) {
this._savePoints(fittedPoints); this._savePoints(fittedPoints, frame);
} }
if (updated.occluded) { if (updated.occluded) {
this._saveOccluded(data.occluded); this._saveOccluded(data.occluded, frame);
} }
if (updated.zOrder) { if (updated.zOrder) {
this._saveZOrder(data.zOrder); this._saveZOrder(data.zOrder, frame);
} }
if (updated.lock) { if (updated.lock) {
this._saveLock(data.lock); this._saveLock(data.lock, frame);
} }
if (updated.pinned) { if (updated.pinned) {
this._savePinned(data.pinned); this._savePinned(data.pinned, frame);
} }
if (updated.color) { if (updated.color) {
this._saveColor(data.color); this._saveColor(data.color, frame);
} }
if (updated.hidden) { if (updated.hidden) {
this._saveHidden(data.hidden); this._saveHidden(data.hidden, frame);
} }
this.updateTimestamp(updated); this.updateTimestamp(updated);
@ -745,7 +745,7 @@
return result; return result;
} }
_saveLabel(label) { _saveLabel(label, frame) {
const undoLabel = this.label; const undoLabel = this.label;
const redoLabel = label; const redoLabel = label;
const undoAttributes = { const undoAttributes = {
@ -783,10 +783,10 @@
for (const mutable of redoAttributes.mutable) { for (const mutable of redoAttributes.mutable) {
this.shapes[mutable.frame].attributes = mutable.attributes; this.shapes[mutable.frame].attributes = mutable.attributes;
} }
}, [this.clientID]); }, [this.clientID], frame);
} }
_saveAttributes(frame, attributes) { _saveAttributes(attributes, frame) {
const current = this.get(frame); const current = this.get(frame);
const labelAttributes = this.label.attributes const labelAttributes = this.label.attributes
.reduce((accumulator, value) => { .reduce((accumulator, value) => {
@ -858,7 +858,7 @@
if (redoShape) { if (redoShape) {
this.shapes[frame] = redoShape; this.shapes[frame] = redoShape;
} }
}, [this.clientID]); }, [this.clientID], frame);
} }
_appendShapeActionToHistory(actionType, frame, undoShape, redoShape) { _appendShapeActionToHistory(actionType, frame, undoShape, redoShape) {
@ -874,10 +874,10 @@
} else { } else {
this.shapes[frame] = redoShape; this.shapes[frame] = redoShape;
} }
}, [this.clientID]); }, [this.clientID], frame);
} }
_savePoints(frame, points) { _savePoints(points, frame) {
const current = this.get(frame); const current = this.get(frame);
const wasKeyframe = frame in this.shapes; const wasKeyframe = frame in this.shapes;
const undoShape = wasKeyframe ? this.shapes[frame] : undefined; const undoShape = wasKeyframe ? this.shapes[frame] : undefined;
@ -921,7 +921,7 @@
); );
} }
_saveOccluded(frame, occluded) { _saveOccluded(occluded, frame) {
const current = this.get(frame); const current = this.get(frame);
const wasKeyframe = frame in this.shapes; const wasKeyframe = frame in this.shapes;
const undoShape = wasKeyframe ? this.shapes[frame] : undefined; const undoShape = wasKeyframe ? this.shapes[frame] : undefined;
@ -943,7 +943,7 @@
); );
} }
_saveZOrder(frame, zOrder) { _saveZOrder(zOrder, frame) {
const current = this.get(frame); const current = this.get(frame);
const wasKeyframe = frame in this.shapes; const wasKeyframe = frame in this.shapes;
const undoShape = wasKeyframe ? this.shapes[frame] : undefined; const undoShape = wasKeyframe ? this.shapes[frame] : undefined;
@ -1007,27 +1007,27 @@
const fittedPoints = this._validateStateBeforeSave(frame, data, updated); const fittedPoints = this._validateStateBeforeSave(frame, data, updated);
if (updated.label) { if (updated.label) {
this._saveLabel(data.label); this._saveLabel(data.label, frame);
} }
if (updated.lock) { if (updated.lock) {
this._saveLock(data.lock); this._saveLock(data.lock, frame);
} }
if (updated.pinned) { if (updated.pinned) {
this._savePinned(data.pinned); this._savePinned(data.pinned, frame);
} }
if (updated.color) { if (updated.color) {
this._saveColor(data.color); this._saveColor(data.color, frame);
} }
if (updated.hidden) { if (updated.hidden) {
this._saveHidden(data.hidden); this._saveHidden(data.hidden, frame);
} }
if (updated.points && fittedPoints.length) { if (updated.points && fittedPoints.length) {
this._savePoints(frame, fittedPoints); this._savePoints(fittedPoints, frame);
} }
if (updated.outside) { if (updated.outside) {
@ -1035,15 +1035,15 @@
} }
if (updated.occluded) { if (updated.occluded) {
this._saveOccluded(frame, data.occluded); this._saveOccluded(data.occluded, frame);
} }
if (updated.zOrder) { if (updated.zOrder) {
this._saveZOrder(frame, data.zOrder); this._saveZOrder(data.zOrder, frame);
} }
if (updated.attributes) { if (updated.attributes) {
this._saveAttributes(frame, data.attributes); this._saveAttributes(data.attributes, frame);
} }
if (updated.keyframe) { if (updated.keyframe) {
@ -1161,19 +1161,19 @@
// Now when all fields are validated, we can apply them // Now when all fields are validated, we can apply them
if (updated.label) { if (updated.label) {
this._saveLabel(data.label); this._saveLabel(data.label, frame);
} }
if (updated.attributes) { if (updated.attributes) {
this._saveAttributes(data.attributes); this._saveAttributes(data.attributes, frame);
} }
if (updated.lock) { if (updated.lock) {
this._saveLock(data.lock); this._saveLock(data.lock, frame);
} }
if (updated.color) { if (updated.color) {
this._saveColor(data.color); this._saveColor(data.color, frame);
} }
this.updateTimestamp(updated); this.updateTimestamp(updated);

@ -398,14 +398,16 @@
* @memberof module:API.cvat.classes.ObjectState * @memberof module:API.cvat.classes.ObjectState
* @readonly * @readonly
* @instance * @instance
* @param {integer} frame current frame number
* @param {boolean} [force=false] delete object even if it is locked * @param {boolean} [force=false] delete object even if it is locked
* @async * @async
* @returns {boolean} true if object has been deleted * @returns {boolean} true if object has been deleted
* @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.PluginError}
* @throws {module:API.cvat.exceptions.ArgumentError}
*/ */
async delete(force = false) { async delete(frame, force = false) {
const result = await PluginRegistry const result = await PluginRegistry
.apiWrapper.call(this, ObjectState.prototype.delete, force); .apiWrapper.call(this, ObjectState.prototype.delete, frame, force);
return result; return result;
} }
} }
@ -420,9 +422,13 @@
}; };
// Delete element from a collection which contains it // Delete element from a collection which contains it
ObjectState.prototype.delete.implementation = async function (force) { ObjectState.prototype.delete.implementation = async function (frame, force) {
if (this.__internal && this.__internal.delete) { if (this.__internal && this.__internal.delete) {
return this.__internal.delete(force); if (!Number.isInteger(+frame) || +frame < 0) {
throw new ArgumentError('Frame argument must be a non negative integer');
}
return this.__internal.delete(frame, force);
} }
return false; return false;

@ -504,6 +504,7 @@
* @returns {HistoryActions} * @returns {HistoryActions}
* @throws {module:API.cvat.exceptions.PluginError} * @throws {module:API.cvat.exceptions.PluginError}
* @throws {module:API.cvat.exceptions.ArgumentError} * @throws {module:API.cvat.exceptions.ArgumentError}
* @returns {[string, number][]} array of pairs [action name, frame number]
* @instance * @instance
* @async * @async
*/ */

@ -367,7 +367,7 @@ describe('Feature: save annotations', () => {
const annotations = await task.annotations.get(0); const annotations = await task.annotations.get(0);
expect(task.annotations.hasUnsavedChanges()).toBe(false); expect(task.annotations.hasUnsavedChanges()).toBe(false);
await annotations[0].delete(); await annotations[0].delete(0);
expect(task.annotations.hasUnsavedChanges()).toBe(true); expect(task.annotations.hasUnsavedChanges()).toBe(true);
await task.annotations.save(); await task.annotations.save();
expect(task.annotations.hasUnsavedChanges()).toBe(false); expect(task.annotations.hasUnsavedChanges()).toBe(false);
@ -413,7 +413,7 @@ describe('Feature: save annotations', () => {
const annotations = await job.annotations.get(0); const annotations = await job.annotations.get(0);
expect(job.annotations.hasUnsavedChanges()).toBe(false); expect(job.annotations.hasUnsavedChanges()).toBe(false);
await annotations[0].delete(); await annotations[0].delete(0);
expect(job.annotations.hasUnsavedChanges()).toBe(true); expect(job.annotations.hasUnsavedChanges()).toBe(true);
await job.annotations.save(); await job.annotations.save();
expect(job.annotations.hasUnsavedChanges()).toBe(false); expect(job.annotations.hasUnsavedChanges()).toBe(false);
@ -436,7 +436,7 @@ describe('Feature: save annotations', () => {
return result; return result;
}; };
await annotations[0].delete(); await annotations[0].delete(0);
await job.annotations.save(); await job.annotations.save();
serverProxy.annotations.updateAnnotations = oldImplementation; serverProxy.annotations.updateAnnotations = oldImplementation;

@ -289,7 +289,7 @@ describe('Feature: delete object', () => {
const task = (await window.cvat.tasks.get({ id: 100 }))[0]; const task = (await window.cvat.tasks.get({ id: 100 }))[0];
const annotationsBefore = await task.annotations.get(0); const annotationsBefore = await task.annotations.get(0);
const { length } = annotationsBefore; const { length } = annotationsBefore;
await annotationsBefore[0].delete(); await annotationsBefore[0].delete(0);
const annotationsAfter = await task.annotations.get(0); const annotationsAfter = await task.annotations.get(0);
expect(annotationsAfter).toHaveLength(length - 1); expect(annotationsAfter).toHaveLength(length - 1);
}); });
@ -298,7 +298,7 @@ describe('Feature: delete object', () => {
const task = (await window.cvat.tasks.get({ id: 101 }))[0]; const task = (await window.cvat.tasks.get({ id: 101 }))[0];
const annotationsBefore = await task.annotations.get(0); const annotationsBefore = await task.annotations.get(0);
const { length } = annotationsBefore; const { length } = annotationsBefore;
await annotationsBefore[0].delete(); await annotationsBefore[0].delete(0);
const annotationsAfter = await task.annotations.get(0); const annotationsAfter = await task.annotations.get(0);
expect(annotationsAfter).toHaveLength(length - 1); expect(annotationsAfter).toHaveLength(length - 1);
}); });

@ -290,86 +290,6 @@ export function changeAnnotationsFilters(filters: string[]): AnyAction {
}; };
} }
export function undoActionAsync(sessionInstance: any, frame: number):
ThunkAction<Promise<void>, {}, {}, AnyAction> {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
try {
const state = getStore().getState();
const { filters, showAllInterpolationTracks } = receiveAnnotationsParameters();
// TODO: use affected IDs as an optimization
const [undoName] = state.annotation.annotations.history.undo.slice(-1);
const undoLog = await sessionInstance.logger.log(LogType.undoAction, {
name: undoName,
count: 1,
}, true);
await sessionInstance.actions.undo();
const history = await sessionInstance.actions.get();
const states = await sessionInstance.annotations
.get(frame, showAllInterpolationTracks, filters);
const [minZ, maxZ] = computeZRange(states);
await undoLog.close();
dispatch({
type: AnnotationActionTypes.UNDO_ACTION_SUCCESS,
payload: {
history,
states,
minZ,
maxZ,
},
});
} catch (error) {
dispatch({
type: AnnotationActionTypes.UNDO_ACTION_FAILED,
payload: {
error,
},
});
}
};
}
export function redoActionAsync(sessionInstance: any, frame: number):
ThunkAction<Promise<void>, {}, {}, AnyAction> {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
try {
const state = getStore().getState();
const { filters, showAllInterpolationTracks } = receiveAnnotationsParameters();
// TODO: use affected IDs as an optimization
const [redoName] = state.annotation.annotations.history.redo.slice(-1);
const redoLog = await sessionInstance.logger.log(LogType.redoAction, {
name: redoName,
count: 1,
}, true);
await sessionInstance.actions.redo();
const history = await sessionInstance.actions.get();
const states = await sessionInstance.annotations
.get(frame, showAllInterpolationTracks, filters);
const [minZ, maxZ] = computeZRange(states);
await redoLog.close();
dispatch({
type: AnnotationActionTypes.REDO_ACTION_SUCCESS,
payload: {
history,
states,
minZ,
maxZ,
},
});
} catch (error) {
dispatch({
type: AnnotationActionTypes.REDO_ACTION_FAILED,
payload: {
error,
},
});
}
};
}
export function updateCanvasContextMenu( export function updateCanvasContextMenu(
visible: boolean, visible: boolean,
left: number, left: number,
@ -625,7 +545,9 @@ ThunkAction<Promise<void>, {}, {}, AnyAction> {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => { return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
try { try {
await sessionInstance.logger.log(LogType.deleteObject, { count: 1 }); await sessionInstance.logger.log(LogType.deleteObject, { count: 1 });
const removed = await objectState.delete(force); const { frame } = receiveAnnotationsParameters();
const removed = await objectState.delete(frame, force);
const history = await sessionInstance.actions.get(); const history = await sessionInstance.actions.get();
if (removed) { if (removed) {
@ -817,6 +739,90 @@ ThunkAction<Promise<void>, {}, {}, AnyAction> {
}; };
} }
export function undoActionAsync(sessionInstance: any, frame: number):
ThunkAction<Promise<void>, {}, {}, AnyAction> {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
try {
const state = getStore().getState();
const { filters, showAllInterpolationTracks } = receiveAnnotationsParameters();
// TODO: use affected IDs as an optimization
const [undo] = state.annotation.annotations.history.undo.slice(-1);
const undoLog = await sessionInstance.logger.log(LogType.undoAction, {
name: undo[0],
frame: undo[1],
count: 1,
}, true);
dispatch(changeFrameAsync(undo[1]));
await sessionInstance.actions.undo();
const history = await sessionInstance.actions.get();
const states = await sessionInstance.annotations
.get(frame, showAllInterpolationTracks, filters);
const [minZ, maxZ] = computeZRange(states);
await undoLog.close();
dispatch({
type: AnnotationActionTypes.UNDO_ACTION_SUCCESS,
payload: {
history,
states,
minZ,
maxZ,
},
});
} catch (error) {
dispatch({
type: AnnotationActionTypes.UNDO_ACTION_FAILED,
payload: {
error,
},
});
}
};
}
export function redoActionAsync(sessionInstance: any, frame: number):
ThunkAction<Promise<void>, {}, {}, AnyAction> {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
try {
const state = getStore().getState();
const { filters, showAllInterpolationTracks } = receiveAnnotationsParameters();
// TODO: use affected IDs as an optimization
const [redo] = state.annotation.annotations.history.redo.slice(-1);
const redoLog = await sessionInstance.logger.log(LogType.redoAction, {
name: redo[0],
frame: redo[1],
count: 1,
}, true);
dispatch(changeFrameAsync(redo[1]));
await sessionInstance.actions.redo();
const history = await sessionInstance.actions.get();
const states = await sessionInstance.annotations
.get(frame, showAllInterpolationTracks, filters);
const [minZ, maxZ] = computeZRange(states);
await redoLog.close();
dispatch({
type: AnnotationActionTypes.REDO_ACTION_SUCCESS,
payload: {
history,
states,
minZ,
maxZ,
},
});
} catch (error) {
dispatch({
type: AnnotationActionTypes.REDO_ACTION_FAILED,
payload: {
error,
},
});
}
};
}
export function rotateCurrentFrame(rotation: Rotation): AnyAction { export function rotateCurrentFrame(rotation: Rotation): AnyAction {
const state: CombinedState = getStore().getState(); const state: CombinedState = getStore().getState();
@ -973,6 +979,8 @@ export function getJobAsync(
export function saveAnnotationsAsync(sessionInstance: any): export function saveAnnotationsAsync(sessionInstance: any):
ThunkAction<Promise<void>, {}, {}, AnyAction> { ThunkAction<Promise<void>, {}, {}, AnyAction> {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => { return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
const { filters, frame, showAllInterpolationTracks } = receiveAnnotationsParameters();
dispatch({ dispatch({
type: AnnotationActionTypes.SAVE_ANNOTATIONS, type: AnnotationActionTypes.SAVE_ANNOTATIONS,
payload: {}, payload: {},
@ -992,6 +1000,8 @@ ThunkAction<Promise<void>, {}, {}, AnyAction> {
}); });
}); });
const states = await sessionInstance
.annotations.get(frame, showAllInterpolationTracks, filters);
await saveJobEvent.close(); await saveJobEvent.close();
await sessionInstance.logger.log( await sessionInstance.logger.log(
LogType.sendTaskInfo, LogType.sendTaskInfo,
@ -1001,7 +1011,9 @@ ThunkAction<Promise<void>, {}, {}, AnyAction> {
dispatch({ dispatch({
type: AnnotationActionTypes.SAVE_ANNOTATIONS_SUCCESS, type: AnnotationActionTypes.SAVE_ANNOTATIONS_SUCCESS,
payload: {}, payload: {
states,
},
}); });
} catch (error) { } catch (error) {
dispatch({ dispatch({

@ -5,7 +5,7 @@
export interface Attribute { export interface Attribute {
id: number; id: number;
name: string; name: string;
type: string; input_type: string;
mutable: boolean; mutable: boolean;
values: string[]; values: string[];
} }

@ -76,7 +76,7 @@ class LabelForm extends React.PureComponent<Props, {}> {
return { return {
name: formValues.attrName[key], name: formValues.attrName[key],
type: formValues.type[key], input_type: formValues.type[key],
mutable: formValues.mutable[key], mutable: formValues.mutable[key],
id: label && index < label.attributes.length id: label && index < label.attributes.length
? label.attributes[index].id : key, ? label.attributes[index].id : key,
@ -136,7 +136,7 @@ class LabelForm extends React.PureComponent<Props, {}> {
private renderAttributeTypeInput(key: number, attr: Attribute | null): JSX.Element { private renderAttributeTypeInput(key: number, attr: Attribute | null): JSX.Element {
const locked = attr ? attr.id >= 0 : false; const locked = attr ? attr.id >= 0 : false;
const type = attr ? attr.type.toUpperCase() : AttributeType.SELECT; const type = attr ? attr.input_type.toUpperCase() : AttributeType.SELECT;
const { form } = this.props; const { form } = this.props;
return ( return (

@ -73,7 +73,7 @@ export default class LabelsEditor
{ {
id: attr.id || idGenerator(), id: attr.id || idGenerator(),
name: attr.name, name: attr.name,
type: attr.input_type, input_type: attr.input_type,
mutable: attr.mutable, mutable: attr.mutable,
values: [...attr.values], values: [...attr.values],
} }
@ -207,7 +207,7 @@ export default class LabelsEditor
{ {
name: attr.name, name: attr.name,
id: attr.id < 0 ? undefined : attr.id, id: attr.id < 0 ? undefined : attr.id,
input_type: attr.type.toLowerCase(), input_type: attr.input_type.toLowerCase(),
default_value: attr.values[0], default_value: attr.values[0],
mutable: attr.mutable, mutable: attr.mutable,
values: [...attr.values], values: [...attr.values],

@ -63,10 +63,11 @@ function mapDispatchToProps(dispatch: any, own: OwnProps): DispatchToProps {
} }
} }
if (searchParams.has('object')) { if (searchParams.has('serverID') && searchParams.has('type')) {
const searchObject = +(searchParams.get('object') as string); const serverID = searchParams.get('serverID');
if (!Number.isNaN(searchObject)) { const type = searchParams.get('type');
initialFilters.push(`serverID==${searchObject}`); if (serverID && !Number.isNaN(+serverID)) {
initialFilters.push(`serverID==${serverID} & type=="${type}"`);
} }
} }

@ -255,7 +255,7 @@ class ObjectItemContainer extends React.PureComponent<Props> {
pathname, pathname,
} = window.location; } = window.location;
const search = `frame=${frameNumber}&object=${objectState.serverID}`; const search = `frame=${frameNumber}&type=${objectState.objectType}&serverID=${objectState.serverID}`;
const url = `${origin}${pathname}?${search}`; const url = `${origin}${pathname}?${search}`;
copy(url); copy(url);
}; };

@ -104,8 +104,8 @@ function mapStateToProps(state: CombinedState): StateToProps {
savingStatuses, savingStatuses,
frameNumber, frameNumber,
jobInstance, jobInstance,
undoAction: history.undo[history.undo.length - 1], undoAction: history.undo.length ? history.undo[history.undo.length - 1][0] : undefined,
redoAction: history.redo[history.redo.length - 1], redoAction: history.redo.length ? history.redo[history.redo.length - 1][0] : undefined,
autoSave, autoSave,
autoSaveInterval, autoSaveInterval,
workspace, workspace,

@ -267,10 +267,12 @@ export default (state = defaultState, action: AnyAction): AnnotationState => {
}; };
} }
case AnnotationActionTypes.SAVE_ANNOTATIONS_SUCCESS: { case AnnotationActionTypes.SAVE_ANNOTATIONS_SUCCESS: {
const { states } = action.payload;
return { return {
...state, ...state,
annotations: { annotations: {
...state.annotations, ...state.annotations,
states,
saving: { saving: {
...state.annotations.saving, ...state.annotations.saving,
uploading: false, uploading: false,

@ -349,8 +349,8 @@ export interface AnnotationState {
filtersHistory: string[]; filtersHistory: string[];
resetGroupFlag: boolean; resetGroupFlag: boolean;
history: { history: {
undo: string[]; undo: [string, number][];
redo: string[]; redo: [string, number][];
}; };
saving: { saving: {
uploading: boolean; uploading: boolean;

Loading…
Cancel
Save