Skip to content

Commit

Permalink
Merge branch 'master' of github.com:scalableminds/webknossos into wel…
Browse files Browse the repository at this point in the history
…come_header_UI

* 'master' of github.com:scalableminds/webknossos:
  Fix rare crash when viewing shared annotation (#6892)
  • Loading branch information
hotzenklotz committed Mar 9, 2023
2 parents 67f6f4a + c5673b9 commit 76a26f2
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released

### Fixed
- Fixed a bug where N5 datasets reading with end-chunks that have a chunk size differing from the metadata-supplied chunk size would fail for some areas. [#6890](https://github.com/scalableminds/webknossos/pull/6890)
- Fixed potential crash when trying to edit certain annotation properties of a shared annotation. [#6892](https://github.com/scalableminds/webknossos/pull/6892)
- Fixed a bug where merging multiple volume annotations would result in inconsistent segment lists. [#6882](https://github.com/scalableminds/webknossos/pull/6882)
- Fixed a bug where uploading multiple annotations with volume layers at once would fail. [#6882](https://github.com/scalableminds/webknossos/pull/6882)

Expand Down
13 changes: 13 additions & 0 deletions frontend/javascripts/oxalis/model/accessors/annotation_accessor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { OxalisState } from "oxalis/store";

export function mayEditAnnotationProperties(state: OxalisState) {
const { owner, restrictions } = state.tracing;
const activeUser = state.activeUser;

return !!(
restrictions.allowUpdate &&
restrictions.allowSave &&
activeUser &&
owner?.id === activeUser.id
);
}
43 changes: 31 additions & 12 deletions frontend/javascripts/oxalis/model/sagas/annotation_saga.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {
import type { Saga } from "oxalis/model/sagas/effect-generators";
import {
takeLatest,
select,
take,
retry,
delay,
Expand All @@ -31,6 +30,7 @@ import {
cancel,
cancelled,
} from "typed-redux-saga";
import { select } from "oxalis/model/sagas/effect-generators";
import { getMappingInfo } from "oxalis/model/accessors/dataset_accessor";
import { getRequestLogZoomStep } from "oxalis/model/accessors/flycam_accessor";
import { Model } from "oxalis/singletons";
Expand All @@ -40,14 +40,17 @@ import constants, { MappingStatusEnum } from "oxalis/constants";
import messages from "messages";
import { APIUserCompact } from "types/api_flow_types";
import { Button } from "antd";
import ErrorHandling from "libs/error_handling";
import { mayEditAnnotationProperties } from "../accessors/annotation_accessor";

/* Note that this must stay in sync with the back-end constant
compare https://github.com/scalableminds/webknossos/issues/5223 */
const MAX_MAG_FOR_AGGLOMERATE_MAPPING = 16;
export function* pushAnnotationUpdateAsync() {
const tracing = yield* select((state) => state.tracing);

if (!tracing.restrictions.allowUpdate) {
export function* pushAnnotationUpdateAsync(action: Action) {
const tracing = yield* select((state) => state.tracing);
const mayEdit = yield* select((state) => mayEditAnnotationProperties(state));
if (!mayEdit) {
return;
}

Expand All @@ -66,14 +69,30 @@ export function* pushAnnotationUpdateAsync() {
description: tracing.description,
viewConfiguration,
};
yield* retry(
SETTINGS_MAX_RETRY_COUNT,
SETTINGS_RETRY_DELAY,
editAnnotation,
tracing.annotationId,
tracing.annotationType,
editObject,
);
try {
yield* retry(
SETTINGS_MAX_RETRY_COUNT,
SETTINGS_RETRY_DELAY,
editAnnotation,
tracing.annotationId,
tracing.annotationType,
editObject,
);
} catch (error) {
// If the annotation cannot be saved repeatedly (retries will continue for 5 minutes),
// we will only notify the user if the name, visibility or description could not be changed.
// Otherwise, we won't notify the user and won't let the sagas crash as the actual skeleton/volume
// tracings are handled separately.
console.error(error);
ErrorHandling.notify(error as Error);
if (
["SET_ANNOTATION_NAME", "SET_ANNOTATION_VISIBILITY", "SET_ANNOTATION_DESCRIPTION"].includes(
action.type,
)
) {
Toast.error("Could not update annotation property. Please try again.");
}
}
}

function* pushAnnotationLayerUpdateAsync(action: EditAnnotationLayerAction): Saga<void> {
Expand Down
9 changes: 6 additions & 3 deletions frontend/javascripts/oxalis/model/sagas/effect-generators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import { select as _select, take as _take } from "typed-redux-saga";
import type { Channel } from "redux-saga";
import { ActionPattern } from "redux-saga/effects";

export function* select<T>(fn: (state: OxalisState) => T) {
const res: T = yield _select(fn);
return res;
// Ensures that the type of state is known. Otherwise,
// a statement such as
// const tracing = yield* select((state) => state.tracing);
// would result in tracing being any.
export function select<T>(fn: (state: OxalisState) => T) {
return _select(fn);
}

export function* take(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { makeComponentLazy } from "libs/react_helpers";
import { AsyncButton } from "components/async_clickables";
import { PricingEnforcedBlur } from "components/pricing_enforcers";
import { PricingPlanEnum } from "admin/organization/pricing_plan_utils";
import { mayEditAnnotationProperties } from "oxalis/model/accessors/annotation_accessor";

const RadioGroup = Radio.Group;
const sharingActiveNode = true;
Expand Down Expand Up @@ -181,11 +182,10 @@ function _ShareModalView(props: Props) {
const [sharedTeams, setSharedTeams] = useState<APITeam[]>([]);
const sharingToken = useDatasetSharingToken(dataset);

const { owner, othersMayEdit, restrictions } = tracing;
const { othersMayEdit } = tracing;
const [newOthersMayEdit, setNewOthersMayEdit] = useState(othersMayEdit);

const hasUpdatePermissions =
restrictions.allowUpdate && restrictions.allowSave && activeUser && owner?.id === activeUser.id;
const hasUpdatePermissions = useSelector(mayEditAnnotationProperties);
useEffect(() => setVisibility(annotationVisibility), [annotationVisibility]);

const fetchAndSetSharedTeams = async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
} from "oxalis/view/right-border-tabs/starting_job_modals";
import { formatUserName } from "oxalis/model/accessors/user_accessor";
import { mayUserEditDataset } from "libs/utils";
import { mayEditAnnotationProperties } from "oxalis/model/accessors/annotation_accessor";

const enum StartableJobsEnum {
NUCLEI_INFERRAL = "nuclei inferral",
Expand All @@ -40,6 +41,7 @@ type StateProps = {
task: Task | null | undefined;
activeUser: APIUser | null | undefined;
activeResolution: Vector3;
mayEditAnnotation: boolean;
};
type DispatchProps = {
setAnnotationName: (arg0: string) => void;
Expand Down Expand Up @@ -453,7 +455,7 @@ class DatasetInfoTabView extends React.PureComponent<Props, State> {
{annotationType} : {this.props.task.id}
</span>
);
} else if (!this.props.tracing.restrictions.allowUpdate) {
} else if (!this.props.mayEditAnnotation) {
// For readonly tracings display the non-editable explorative tracing name
annotationTypeLabel = <span>Annotation: {tracingName}</span>;
} else {
Expand All @@ -477,7 +479,7 @@ class DatasetInfoTabView extends React.PureComponent<Props, State> {
const tracingDescription = this.props.tracing.description || "[no description]";
let descriptionEditField;

if (this.props.tracing.restrictions.allowUpdate) {
if (this.props.mayEditAnnotation) {
descriptionEditField = (
<span
style={{
Expand Down Expand Up @@ -658,6 +660,7 @@ const mapStateToProps = (state: OxalisState): StateProps => ({
task: state.task,
activeUser: state.activeUser,
activeResolution: getCurrentResolution(state),
mayEditAnnotation: mayEditAnnotationProperties(state),
});

const mapDispatchToProps = (dispatch: Dispatch<any>) => ({
Expand Down

0 comments on commit 76a26f2

Please sign in to comment.