Skip to content

Commit 02a0f0c

Browse files
committed
Merge branch 'master' into virtual-remote-datasets
2 parents 2196b2f + bce8432 commit 02a0f0c

File tree

189 files changed

+4594
-2177
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

189 files changed

+4594
-2177
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
------
1414
(Please delete unneeded items, merge only when none are left open)
15-
- [ ] Updated [changelog](../blob/master/CHANGELOG.unreleased.md#unreleased)
16-
- [ ] Updated [migration guide](../blob/master/MIGRATIONS.unreleased.md#unreleased) if applicable
15+
- [ ] Added changelog entry (create a `$PR_NUMBER.md` file in `unreleased_changes` or use `./tools/create-changelog-entry.py`)
16+
- [ ] Added migration guide entry if applicable (edit the same file as for the changelog)
1717
- [ ] Updated [documentation](../blob/master/docs) if applicable
1818
- [ ] Adapted [wk-libs python client](https://github.com/scalableminds/webknossos-libs/tree/master/webknossos/webknossos/client) if relevant API parts change
1919
- [ ] Removed dev-only changes like prints and application.conf edits

CHANGELOG.released.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
77
and this project adheres to [Calendar Versioning](http://calver.org/) `0Y.0M.MICRO`.
88
For upgrade instructions, please check the [migration guide](MIGRATIONS.released.md).
99

10+
## [25.06.2](https://github.com/scalableminds/webknossos/releases/tag/25.06.2) - 2025-06-17
11+
[Commits](https://github.com/scalableminds/webknossos/compare/25.06.1...25.06.2)
12+
13+
### Fixed
14+
- Fixed a regression that led to incorrect behavior when trying to jump to the last branchpoint even though no branchpoint existed. [#8695](https://github.com/scalableminds/webknossos/pull/8695)
15+
1016
## [25.06.1](https://github.com/scalableminds/webknossos/releases/tag/25.06.1) - 2025-06-03
1117
[Commits](https://github.com/scalableminds/webknossos/compare/25.06.0...25.06.1)
1218

CHANGELOG.unreleased.md

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1 @@
1-
# Changelog (Unreleased)
2-
3-
All notable (yet unreleased) user-facing changes to WEBKNOSSOS are documented in this file.
4-
See `CHANGELOG.released.md` for the changes which are part of official releases.
5-
6-
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
7-
and this project adheres to [Calendar Versioning](http://calver.org/) `0Y.0M.MICRO`.
8-
For upgrade instructions, please check the [migration guide](MIGRATIONS.released.md).
9-
10-
## Unreleased
11-
[Commits](https://github.com/scalableminds/webknossos/compare/25.06.1...HEAD)
12-
13-
### Added
14-
- Added the ability to duplicate trees in skeleton annotations. Users can create a copy of any tree (including all nodes, edges, and properties) via the context menu in the skeleton tab. [#8662](https://github.com/scalableminds/webknossos/pull/8662)
15-
- Meshes are now reloaded using their previous opacity value. [#8622](https://github.com/scalableminds/webknossos/pull/8622)
16-
17-
### Changed
18-
19-
### Fixed
20-
- Improved efficiency of saving bounding box related changes. [#8492](https://github.com/scalableminds/webknossos/pull/8492)
21-
- When deleting a dataset, its caches are cleared, so that if a new dataset by the same name is uploaded afterwards, only new data is loaded. [#8638](https://github.com/scalableminds/webknossos/pull/8638)
22-
- Fixed the contrast of the WelcomeToast buttons. Updated `antd` to version `5.22`.[#8688](https://github.com/scalableminds/webknossos/pull/8688)
23-
- Fixed a race condition when starting proofreading with a split action. [#8676](https://github.com/scalableminds/webknossos/pull/8676)
24-
- Fixed that activating a mapping got stuck when a dataset was opened in "view" mode. [#8687](https://github.com/scalableminds/webknossos/pull/8687)
25-
26-
### Removed
27-
28-
### Breaking Changes
1+
WARNING: This file will be deleted in the next release. If you have a merge conflict in this file, please ensure that the file only contains this warning text after the merge. Please execute `./tools/create-changelog-entry.py` and move the changelog for your PR into the file that was created by the script. From now on, this will be the new way of adding changelog and migration guide entries for a PR. The created files will be aggregated when a release is created.

MIGRATIONS.released.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ See `MIGRATIONS.unreleased.md` for the changes which are not yet part of an offi
66
This project adheres to [Calendar Versioning](http://calver.org/) `0Y.0M.MICRO`.
77
User-facing changes are documented in the [changelog](CHANGELOG.released.md).
88

9+
## [25.06.2](https://github.com/scalableminds/webknossos/releases/tag/25.06.2) - 2025-06-17
10+
[Commits](https://github.com/scalableminds/webknossos/compare/25.06.1...25.06.2)
11+
12+
### Postgres Evolutions:
13+
None.
14+
915
## [25.06.1](https://github.com/scalableminds/webknossos/releases/tag/25.06.1) - 2025-06-03
1016
[Commits](https://github.com/scalableminds/webknossos/compare/25.06.0...25.06.1)
1117

MIGRATIONS.unreleased.md

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1 @@
1-
# Migration Guide (Unreleased)
2-
All migrations (for unreleased versions) of WEBKNOSSOS are documented in this file.
3-
See `MIGRATIONS.released.md` for the migrations which are part of official releases.
4-
5-
This project adheres to [Calendar Versioning](http://calver.org/) `0Y.0M.MICRO`.
6-
User-facing changes are documented in the [changelog](CHANGELOG.released.md).
7-
8-
## Unreleased
9-
[Commits](https://github.com/scalableminds/webknossos/compare/25.06.1...HEAD)
10-
11-
- The default thread pool size was increased from 5 to 10 times the number of available CPUs (capped at 1000). Note that wk may need slightly more memory because of this. [#8686](https://github.com/scalableminds/webknossos/pull/8686)
12-
13-
### Postgres Evolutions:
14-
- [134-dataset-layer-attachments.sql](conf/evolutions/134-dataset-layer-attachments.sql)
1+
WARNING: This file will be deleted in the next release. If you have a merge conflict in this file, please ensure that the file only contains this warning text after the merge. Please execute `./tools/create-changelog-entry.py` and move the changelog for your PR into the file that was created by the script. From now on, this will be the new way of adding changelog and migration guide entries for a PR. The created files will be aggregated when a release is created.

app/controllers/AnnotationController.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,8 @@ class AnnotationController @Inject()(
420420
newAnnotationProto <- tracingStoreClient.duplicateAnnotation(
421421
annotation._id,
422422
newAnnotationId,
423+
annotation._user,
424+
user._id,
423425
version = None,
424426
isFromTask = annotation._task.isDefined,
425427
datasetBoundingBox = dataSource.map(_.boundingBox)

app/controllers/AnnotationIOController.scala

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ class AnnotationIOController @Inject()(
413413

414414
private def downloadExplorational(annotationId: ObjectId,
415415
typ: String,
416-
issuingUser: Option[User],
416+
requestingUser: Option[User],
417417
version: Option[Long],
418418
skipVolumeData: Boolean,
419419
volumeDataZipFormat: VolumeDataZipFormat)(implicit ctx: DBAccessContext) = {
@@ -425,10 +425,12 @@ class AnnotationIOController @Inject()(
425425
tracingStoreClient <- tracingStoreService.clientFor(dataset)
426426
fetchedAnnotationLayers <- Fox.serialCombined(annotation.skeletonAnnotationLayers)(
427427
tracingStoreClient.getSkeletonTracing(annotation._id, _, version))
428-
user <- userService.findOneCached(annotation._user)(GlobalAccessContext)
428+
annotationProto <- tracingStoreClient.getAnnotationProto(annotation._id, version)
429+
annotationOwner <- userService.findOneCached(annotation._user)(GlobalAccessContext)
429430
taskOpt <- Fox.runOptional(annotation._task)(taskDAO.findOne)
430431
nmlStream = nmlWriter.toNmlStream(
431432
"temp",
433+
annotationProto,
432434
fetchedAnnotationLayers,
433435
Some(annotation),
434436
dataset.voxelSize,
@@ -437,10 +439,11 @@ class AnnotationIOController @Inject()(
437439
conf.Http.uri,
438440
dataset.name,
439441
dataset._id,
440-
Some(user),
442+
annotationOwner,
441443
taskOpt,
442444
skipVolumeData,
443-
volumeDataZipFormat
445+
volumeDataZipFormat,
446+
requestingUser
444447
)
445448
nmlTemporaryFile = tempFileService.create()
446449
temporaryFileStream = new BufferedOutputStream(new FileOutputStream(new File(nmlTemporaryFile.toString)))
@@ -467,10 +470,12 @@ class AnnotationIOController @Inject()(
467470
skeletonAnnotationLayer =>
468471
tracingStoreClient.getSkeletonTracing(annotation._id, skeletonAnnotationLayer, version)
469472
} ?~> "annotation.download.fetchSkeletonLayer.failed"
470-
user <- userService.findOneCached(annotation._user)(GlobalAccessContext) ?~> "annotation.download.findUser.failed"
473+
annotationOwner <- userService.findOneCached(annotation._user)(GlobalAccessContext) ?~> "annotation.download.findUser.failed"
471474
taskOpt <- Fox.runOptional(annotation._task)(taskDAO.findOne(_)(GlobalAccessContext)) ?~> "task.notFound"
475+
annotationProto <- tracingStoreClient.getAnnotationProto(annotation._id, version)
472476
nmlStream = nmlWriter.toNmlStream(
473477
name,
478+
annotationProto,
474479
fetchedSkeletonLayers ::: fetchedVolumeLayers,
475480
Some(annotation),
476481
dataset.voxelSize,
@@ -479,10 +484,11 @@ class AnnotationIOController @Inject()(
479484
conf.Http.uri,
480485
dataset.name,
481486
dataset._id,
482-
Some(user),
487+
annotationOwner,
483488
taskOpt,
484489
skipVolumeData,
485-
volumeDataZipFormat
490+
volumeDataZipFormat,
491+
requestingUser
486492
)
487493
temporaryFile = tempFileService.create()
488494
zipper = ZipIO.startZip(new BufferedOutputStream(new FileOutputStream(new File(temporaryFile.toString))))
@@ -520,13 +526,13 @@ class AnnotationIOController @Inject()(
520526
zipMimeType
521527

522528
for {
523-
annotation <- provider.provideAnnotation(typ, annotationId, issuingUser) ~> NOT_FOUND
529+
annotation <- provider.provideAnnotation(typ, annotationId, requestingUser) ~> NOT_FOUND
524530
restrictions <- provider.restrictionsFor(typ, annotationId) ?~> "annotation.restrictions.unavailable"
525531
name <- provider.nameFor(annotation) ?~> "annotation.name.impossible"
526532
fileExtension = exportExtensionForAnnotation(annotation)
527533
fileName = name + fileExtension
528534
mimeType = exportMimeTypeForAnnotation(annotation)
529-
_ <- restrictions.allowDownload(issuingUser) ?~> "annotation.download.notAllowed" ~> FORBIDDEN
535+
_ <- restrictions.allowDownload(requestingUser) ?~> "annotation.download.notAllowed" ~> FORBIDDEN
530536
dataset <- datasetDAO.findOne(annotation._dataset)(GlobalAccessContext) ?~> "dataset.notFoundForAnnotation" ~> NOT_FOUND
531537
organization <- organizationDAO.findOne(dataset._organization)(GlobalAccessContext) ?~> "organization.notFound" ~> NOT_FOUND
532538
temporaryFile <- annotationToTemporaryFile(dataset, annotation, name, organization._id) ?~> "annotation.writeTemporaryFile.failed"
@@ -538,13 +544,13 @@ class AnnotationIOController @Inject()(
538544
}
539545
}
540546

541-
private def downloadProject(projectId: ObjectId, userOpt: Option[User], skipVolumeData: Boolean)(
547+
private def downloadProject(projectId: ObjectId, requestingUserOpt: Option[User], skipVolumeData: Boolean)(
542548
implicit ctx: DBAccessContext,
543549
m: MessagesProvider) =
544550
for {
545-
user <- userOpt.toFox ?~> Messages("notAllowed") ~> FORBIDDEN
551+
requestingUser <- requestingUserOpt.toFox ?~> Messages("notAllowed") ~> FORBIDDEN
546552
project <- projectDAO.findOne(projectId) ?~> Messages("project.notFound", projectId) ~> NOT_FOUND
547-
_ <- Fox.assertTrue(userService.isTeamManagerOrAdminOf(user, project._team)) ?~> "notAllowed" ~> FORBIDDEN
553+
_ <- Fox.assertTrue(userService.isTeamManagerOrAdminOf(requestingUser, project._team)) ?~> "notAllowed" ~> FORBIDDEN
548554
annotations <- annotationDAO.findAllFinishedForProject(projectId)
549555
zipTempFilePath <- annotationService.zipAnnotations(annotations,
550556
project.name,
@@ -556,7 +562,7 @@ class AnnotationIOController @Inject()(
556562
fileName = _ => Some(TextUtils.normalize(project.name + "_nmls.zip")))
557563
}
558564

559-
private def downloadTask(taskId: ObjectId, userOpt: Option[User], skipVolumeData: Boolean)(
565+
private def downloadTask(taskId: ObjectId, requestingUserOpt: Option[User], skipVolumeData: Boolean)(
560566
implicit ctx: DBAccessContext,
561567
m: MessagesProvider) = {
562568
def createTaskZip(task: Task): Fox[Path] = annotationService.annotationsFor(task._id).flatMap { annotations =>
@@ -566,10 +572,10 @@ class AnnotationIOController @Inject()(
566572
}
567573

568574
for {
569-
user <- userOpt.toFox ?~> Messages("notAllowed") ~> FORBIDDEN
575+
requestingUser <- requestingUserOpt.toFox ?~> Messages("notAllowed") ~> FORBIDDEN
570576
task <- taskDAO.findOne(taskId) ?~> Messages("task.notFound") ~> NOT_FOUND
571577
project <- projectDAO.findOne(task._project) ?~> Messages("project.notFound") ~> NOT_FOUND
572-
_ <- Fox.assertTrue(userService.isTeamManagerOrAdminOf(user, project._team)) ?~> Messages("notAllowed") ~> FORBIDDEN
578+
_ <- Fox.assertTrue(userService.isTeamManagerOrAdminOf(requestingUser, project._team)) ?~> Messages("notAllowed") ~> FORBIDDEN
573579
zipTempFilePath <- createTaskZip(task)
574580
} yield {
575581
Ok.sendPath(zipTempFilePath,
@@ -578,7 +584,7 @@ class AnnotationIOController @Inject()(
578584
}
579585
}
580586

581-
private def downloadTaskType(taskTypeId: ObjectId, userOpt: Option[User], skipVolumeData: Boolean)(
587+
private def downloadTaskType(taskTypeId: ObjectId, requestingUserOpt: Option[User], skipVolumeData: Boolean)(
582588
implicit ctx: DBAccessContext,
583589
m: MessagesProvider) = {
584590
def createTaskTypeZip(taskType: TaskType) =
@@ -593,9 +599,9 @@ class AnnotationIOController @Inject()(
593599
} yield zip
594600

595601
for {
596-
user <- userOpt.toFox ?~> Messages("notAllowed") ~> FORBIDDEN
602+
requestingUser <- requestingUserOpt.toFox ?~> Messages("notAllowed") ~> FORBIDDEN
597603
taskType <- taskTypeDAO.findOne(taskTypeId) ?~> "taskType.notFound" ~> NOT_FOUND
598-
_ <- Fox.assertTrue(userService.isTeamManagerOrAdminOf(user, taskType._team)) ?~> "notAllowed" ~> FORBIDDEN
604+
_ <- Fox.assertTrue(userService.isTeamManagerOrAdminOf(requestingUser, taskType._team)) ?~> "notAllowed" ~> FORBIDDEN
599605
zipTempFilePath <- createTaskTypeZip(taskType)
600606
} yield {
601607
Ok.sendPath(zipTempFilePath,

app/controllers/AuthenticationController.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ class AuthenticationController @Inject()(
215215
} yield result
216216

217217
def accessibleBySwitching(datasetId: Option[ObjectId],
218-
annotationId: Option[String],
218+
annotationId: Option[ObjectId],
219219
workflowHash: Option[String]): Action[AnyContent] = sil.SecuredAction.async {
220220
implicit request =>
221221
for {

app/controllers/TaskController.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ class TaskController @Inject()(taskCreationService: TaskCreationService,
6767
taskParametersFull <- taskCreationService.createTracingsFromBaseAnnotations(taskParametersWithIds,
6868
taskType,
6969
dataset,
70-
dataSource)
70+
dataSource,
71+
request.identity._id)
7172
skeletonBaseOpts: List[Option[SkeletonTracing]] = taskCreationService.createTaskSkeletonTracingBases(
7273
taskParametersFull)
7374
volumeBaseOpts: List[Option[(VolumeTracing, Option[File])]] <- taskCreationService.createTaskVolumeTracingBases(

app/controllers/WKRemoteTracingStoreController.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,7 @@ class WKRemoteTracingStoreController @Inject()(tracingStoreService: TracingStore
8282
tracingStoreService.validateAccess(name, key) { _ =>
8383
val report = request.body
8484
for {
85-
annotationId <- ObjectId.fromString(report.annotationId)
86-
annotation <- annotationDAO.findOne(annotationId)
85+
annotation <- annotationDAO.findOne(report.annotationId)
8786
_ <- ensureAnnotationNotFinished(annotation)
8887
_ <- annotationDAO.updateModified(annotation._id, Instant.now)
8988
_ = report.statistics.map(statistics => annotationService.updateStatistics(annotation._id, statistics))

0 commit comments

Comments
 (0)