Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into isosurface
Browse files Browse the repository at this point in the history
* origin/master:
  Add debugging methods to visualize wireframe of buckets (#3402)
  fixed bug that selects a just removed layout (#3379)
  Added button to revoke admin rights in frontend (#3378)
  Revert "Add REST API versioning support (#3385)" (#3404)
  Add REST API versioning support (#3385)
  limit number of tasks to be created in one api request (#3386)
  Use correct volume download route in TracingStoreRpcClient (#3403)
  clearer error message when uploading nml for inaccessible dataset (#3390)
  Refactored dropdown item events (#3383)
  Show dataset extent in right menu tab (#3371)
  • Loading branch information
jfrohnhofen committed Oct 26, 2018
2 parents 8f16f9e + 8238820 commit ed670e3
Show file tree
Hide file tree
Showing 21 changed files with 281 additions and 139 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.md).
- Added support for duplicate dataset names for different organizations [#3137](https://github.com/scalableminds/webknossos/pull/3137)
- Extended the version restore view and added a view to restore older versions of a volume tracing. Access it through the dropdown next to the Save button. [#3349](https://github.com/scalableminds/webknossos/pull/3349)
- Added support to watch additional dataset directories, automatically creating symbolic links to the main directory [#3330](https://github.com/scalableminds/webknossos/pull/3330)
- Added a button to the users list view that revokes admin rights from all selected users. [#3378](https://github.com/scalableminds/webknossos/pull/3378)
- A User can now have multiple layouts for tracing views. [#3299](https://github.com/scalableminds/webknossos/pull/3299)
- The info tab in tracing views now displays the extent of the current dataset. [#3371](https://github.com/scalableminds/webknossos/pull/3371).

### Changed

Expand Down
39 changes: 15 additions & 24 deletions app/assets/javascripts/admin/task/task_annotation_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,41 +113,32 @@ class TaskAnnotationView extends React.PureComponent<Props & StateProps, State>
<a href={`/annotations/Task/${annotation.id}`}>{label}</a>
</Item>

<Item key={`${annotation.id}-transfer`}>
<span
onClick={() =>
this.setState({ currentAnnotation: annotation, isTransferModalVisible: true })
}
>
<Icon type="team" />Transfer
</span>
<Item
key={`${annotation.id}-transfer`}
onClick={() =>
this.setState({ currentAnnotation: annotation, isTransferModalVisible: true })
}
>
<Icon type="team" />Transfer
</Item>
<Item key={`${annotation.id}-download`}>
<a href={`/api/annotations/Task/${annotation.id}/download`}>
<Icon type="download" />Download
</a>
</Item>
<Item key={`${annotation.id}-reset`}>
<span onClick={() => this.resetAnnotation(annotation)}>
<Icon type="rollback" />Reset
</span>
<Item key={`${annotation.id}-reset`} onClick={() => this.resetAnnotation(annotation)}>
<Icon type="rollback" />Reset
</Item>
<Item key={`${annotation.id}-delete`}>
<span onClick={() => this.deleteAnnotation(annotation)}>
<Icon type="delete" />Reset and Cancel
</span>
<Item key={`${annotation.id}-delete`} onClick={() => this.deleteAnnotation(annotation)}>
<Icon type="delete" />Reset and Cancel
</Item>
{annotation.state === "Finished" ? (
<Item key={`${annotation.id}-reopen`}>
<span onClick={() => this.reOpenAnnotation(annotation)}>
<Icon type="folder-open" />Reopen
</span>
<Item key={`${annotation.id}-reopen`} onClick={() => this.reOpenAnnotation(annotation)}>
<Icon type="folder-open" />Reopen
</Item>
) : (
<Item key={`${annotation.id}-finish`}>
<span onClick={() => this.finishAnnotation(annotation)}>
<Icon type="check-circle-o" />Finish
</span>
<Item key={`${annotation.id}-finish`} onClick={() => this.finishAnnotation(annotation)}>
<Icon type="check-circle-o" />Finish
</Item>
)}
</Menu>
Expand Down
54 changes: 36 additions & 18 deletions app/assets/javascripts/admin/user/user_list_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,11 @@ class UserListView extends React.PureComponent<Props, State> {
});
};

grantAdminRights = async () => {
setAdminRightsTo = async (isAdmin: boolean) => {
if (this.props.activeUser.isAdmin) {
const newUserPromises = this.state.users.map(user => {
if (this.state.selectedUserIds.includes(user.id)) {
const newUser = Object.assign({}, user, { isAdmin: true });
const newUser = Object.assign({}, user, { isAdmin });

return updateUser(newUser);
}
Expand Down Expand Up @@ -305,22 +305,40 @@ class UserListView extends React.PureComponent<Props, State> {
Change Experience
</Button>
{this.props.activeUser.isAdmin ? (
<Button
onClick={() =>
Modal.confirm({
title: messages["users.grant_admin_rights_title"],
content: messages["users.grant_admin_rights"]({
numUsers: this.state.selectedUserIds.length,
}),
onOk: this.grantAdminRights,
})
}
icon="rocket"
disabled={!hasRowsSelected}
style={marginRight}
>
Grant Admin Rights
</Button>
<React.Fragment>
<Button
onClick={() =>
Modal.confirm({
title: messages["users.grant_admin_rights_title"],
content: messages["users.grant_admin_rights"]({
numUsers: this.state.selectedUserIds.length,
}),
onOk: () => this.setAdminRightsTo(true),
})
}
icon="rocket"
disabled={!hasRowsSelected}
style={marginRight}
>
Grant Admin Rights
</Button>
<Button
onClick={() =>
Modal.confirm({
title: messages["users.revoke_admin_rights_title"],
content: messages["users.revoke_admin_rights"]({
numUsers: this.state.selectedUserIds.length,
}),
onOk: () => this.setAdminRightsTo(false),
})
}
icon="rollback"
disabled={!hasRowsSelected}
style={marginRight}
>
Revoke Admin Rights
</Button>
</React.Fragment>
) : null}
<InviteUsersPopover
organizationName={this.props.activeUser.organization}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,13 @@ class DatasetActionView extends React.PureComponent<Props, State> {
const menu = (
<Menu>
<Menu.Item key="existing">
<a
href="#"
onClick={() => this.createTracing(dataset, "volume", true)}
title="Create volume tracing"
>
<Menu.Item key="existing" onClick={() => this.createTracing(dataset, "volume", true)}>
<a href="#" title="Create volume tracing">
Use Existing Segmentation Layer
</a>
</Menu.Item>
<Menu.Item key="new">
<a
href="#"
onClick={() => this.createTracing(dataset, "volume", false)}
title="Create volume tracing"
>
<Menu.Item key="new" onClick={() => this.createTracing(dataset, "volume", false)}>
<a href="#" title="Create volume tracing">
Use a New Segmentation Layer
</a>
</Menu.Item>
Expand Down
19 changes: 19 additions & 0 deletions app/assets/javascripts/libs/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Maybe from "data.maybe";
import window, { document, location } from "libs/window";
import naturalSort from "javascript-natural-sort";
import type { APIUser } from "admin/api_flow_types";
import type { BoundingBoxObject } from "oxalis/store";

export type Comparator<T> = (T, T) => -1 | 0 | 1;
type UrlParams = { [key: string]: string };
Expand Down Expand Up @@ -129,6 +130,24 @@ export function computeArrayFromBoundingBox(bb: ?BoundingBoxType): ?Vector6 {
: null;
}

export function aggregateBoundingBox(boundingBoxes: Array<BoundingBoxObject>): BoundingBoxType {
const allCoordinates = [0, 1, 2].map(index =>
boundingBoxes.map(box => box.topLeft[index]).concat(
boundingBoxes.map(box => {
const bottomRight = [
box.topLeft[0] + box.width,
box.topLeft[1] + box.height,
box.topLeft[2] + box.depth,
];
return bottomRight[index];
}),
),
);
const min = (([0, 1, 2].map(index => Math.min(...allCoordinates[index])): any): Vector3);
const max = (([0, 1, 2].map(index => Math.max(...allCoordinates[index])): any): Vector3);
return { min, max };
}

export function compareBy<T>(
collectionForTypeInference: Array<T>, // this parameter is only used let flow infer the used type
selector: T => number,
Expand Down
4 changes: 4 additions & 0 deletions app/assets/javascripts/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ In order to restore the current window, a reload is necessary.`,
"users.grant_admin_rights": _.template(
"You are about to grant admin privileges to <%- numUsers %> user(s) giving them access to all teams, datasets and annotations. Do you want to proceed?",
),
"users.revoke_admin_rights_title": "Do you really want to revoke admin rights?",
"users.revoke_admin_rights": _.template(
"You are about to revoke admin privileges from <%- numUsers %> user(s). Do you want to proceed?",
),
"users.change_email_title": "Do you really want to change the email?",
"users.change_email": _.template(
"Do you really want to change the email to '<%- newEmail %>' ? The corresponding user will be logged out and unsaved changes might be lost.",
Expand Down
32 changes: 31 additions & 1 deletion app/assets/javascripts/oxalis/controller/scene_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ import Skeleton from "oxalis/geometries/skeleton";
import Cube from "oxalis/geometries/cube";
import ContourGeometry from "oxalis/geometries/contourgeometry";
import Dimensions from "oxalis/model/dimensions";
import { OrthoViews, OrthoViewValues, OrthoViewValuesWithoutTDView } from "oxalis/constants";
import constants, {
OrthoViews,
OrthoViewValues,
OrthoViewValuesWithoutTDView,
} from "oxalis/constants";
import type { Vector3, OrthoView, OrthoViewMap, BoundingBoxType } from "oxalis/constants";
import { listenToStoreProperty } from "oxalis/model/helpers/listener_helpers";
import { getRenderer } from "oxalis/controller/renderer";
import ArbitraryPlane from "oxalis/geometries/arbitrary_plane";
import { getSomeTracing } from "oxalis/model/accessors/tracing_accessor";
import window from "libs/window";

const CUBE_COLOR = 0x999999;

Expand Down Expand Up @@ -80,6 +85,31 @@ class SceneController {
this.rootGroup.scale.copy(new THREE.Vector3(...Store.getState().dataset.dataSource.scale));
// Add scene to the group, all Geometries are then added to group
this.scene.add(this.rootGroup);

this.setupDebuggingMethods();
}

setupDebuggingMethods() {
// These methods are attached to window, since we would run into circular import errors
// otherwise.
window.addBucketMesh = (position: Vector3, zoomStep: number, optColor?: string) => {
const bucketExtent = constants.BUCKET_WIDTH * 2 ** zoomStep;
const bucketSize = [bucketExtent, bucketExtent, bucketExtent];
const boxGeometry = new THREE.BoxGeometry(...bucketSize);
const edgesGeometry = new THREE.EdgesGeometry(boxGeometry);
const material = new THREE.LineBasicMaterial({
color: optColor || (zoomStep === 0 ? 0xff00ff : 0x00ffff),
linewidth: 1,
});
const cube = new THREE.LineSegments(edgesGeometry, material);
cube.position.x = position[0] + bucketSize[0] / 2;
cube.position.y = position[1] + bucketSize[1] / 2;
cube.position.z = position[2] + bucketSize[2] / 2;
this.rootNode.add(cube);
return cube;
};

window.removeBucketMesh = (mesh: THREE.LineSegments) => this.rootNode.remove(mesh);
}

addSTL(stlBuffer: ArrayBuffer): void {
Expand Down
37 changes: 37 additions & 0 deletions app/assets/javascripts/oxalis/model/bucket_data_handling/bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@
import _ from "lodash";
import BackboneEvents from "backbone-events-standalone";
import type { Vector3, Vector4 } from "oxalis/constants";
import * as THREE from "three";
import constants from "oxalis/constants";
import TemporalBucketManager from "oxalis/model/bucket_data_handling/temporal_bucket_manager";
import * as Utils from "libs/utils";
import window from "libs/window";
import Toast from "libs/toast";
import { getResolutions } from "oxalis/model/accessors/dataset_accessor";
import Store from "oxalis/store";
import { bucketPositionToGlobalAddress } from "oxalis/model/helpers/position_converter";

export const BucketStateEnum = {
UNREQUESTED: "UNREQUESTED",
Expand All @@ -31,6 +35,8 @@ export class DataBucket {
BIT_DEPTH: number;
BUCKET_LENGTH: number;
BYTE_OFFSET: number;
visualizedMesh: ?Object;
visualizationColor: number;

state: BucketStateEnumType;
dirty: boolean;
Expand Down Expand Up @@ -322,6 +328,37 @@ export class DataBucket {
}
}
}

// The following three methods can be used for debugging purposes.
// The bucket will be rendered in the 3D scene as a wireframe geometry.
visualize() {
if (this.visualizedMesh != null) {
return;
}
if (this.zoomedAddress[3] === 0 || this.zoomedAddress[3] === 1) {
const resolutions = getResolutions(Store.getState().dataset);
this.visualizedMesh = window.addBucketMesh(
bucketPositionToGlobalAddress(this.zoomedAddress, resolutions),
this.zoomedAddress[3],
this.visualizationColor,
);
}
}

unvisualize() {
if (this.visualizedMesh != null) {
window.removeBucketMesh(this.visualizedMesh);
this.visualizedMesh = null;
}
}

setVisualizationColor(colorDescriptor: string | number) {
const color = new THREE.Color(colorDescriptor);
this.visualizationColor = color;
if (this.visualizedMesh != null) {
this.visualizedMesh.material.color = color;
}
}
}

export class NullBucket {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ export default class TextureBucketManager {
bucketHeightInTexture,
);
this.committedBucketSet.add(bucket);

window.needsRerender = true;
this.isRefreshBufferOutOfDate = true;
}
Expand Down
Loading

0 comments on commit ed670e3

Please sign in to comment.