diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 3784c9075c..f069e844ba 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -11,10 +11,12 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released [Commits](https://github.com/scalableminds/webknossos/compare/24.11.1...HEAD) ### Added +- When exploring remote URIs pasted from Neuroglancer, the format prefixes like `precomputed://` are now ignored, so users don’t have to remove them. [#8195](https://github.com/scalableminds/webknossos/pull/8195) ### Changed - Reading image files on datastore filesystem is now done asynchronously. [#8126](https://github.com/scalableminds/webknossos/pull/8126) - Improved error messages for starting jobs on datasets from other organizations. [#8181](https://github.com/scalableminds/webknossos/pull/8181) +- Removed bounding box size restriction for inferral jobs for super users. [#8200](https://github.com/scalableminds/webknossos/pull/8200) ### Fixed - Fix performance bottleneck when deleting a lot of trees at once. [#8176](https://github.com/scalableminds/webknossos/pull/8176) @@ -22,5 +24,6 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released - Fix a bug where trying to delete a non-existing node (via the API, for example) would delete the whole active tree. [#8176](https://github.com/scalableminds/webknossos/pull/8176) ### Removed +- Removed Google Analytics integration. [#8201](https://github.com/scalableminds/webknossos/pull/8201) ### Breaking Changes diff --git a/MIGRATIONS.unreleased.md b/MIGRATIONS.unreleased.md index 20414e596e..de99ce01d1 100644 --- a/MIGRATIONS.unreleased.md +++ b/MIGRATIONS.unreleased.md @@ -8,4 +8,6 @@ User-facing changes are documented in the [changelog](CHANGELOG.released.md). ## Unreleased [Commits](https://github.com/scalableminds/webknossos/compare/24.11.1...HEAD) +- The config option `googleAnalytics.trackingId` is no longer used and can be removed. [#8201](https://github.com/scalableminds/webknossos/pull/8201) + ### Postgres Evolutions: diff --git a/app/controllers/AnnotationController.scala b/app/controllers/AnnotationController.scala index 9279822fa1..7a5b610240 100755 --- a/app/controllers/AnnotationController.scala +++ b/app/controllers/AnnotationController.scala @@ -545,8 +545,7 @@ class AnnotationController @Inject()( annotationInfos <- annotationDAO.findAllListableExplorationals( isFinished, None, - isForOwnDashboard = true, - AnnotationType.Explorational, + filterOwnedOrShared = true, limit.getOrElse(annotationService.DefaultAnnotationListLimit), pageNumber.getOrElse(0) ) diff --git a/app/controllers/InitialDataController.scala b/app/controllers/InitialDataController.scala index d2c736a064..ec928ec179 100644 --- a/app/controllers/InitialDataController.scala +++ b/app/controllers/InitialDataController.scala @@ -5,6 +5,7 @@ import com.scalableminds.util.accesscontext.GlobalAccessContext import com.scalableminds.util.time.Instant import com.scalableminds.util.tools.{Fox, FoxImplicits} import com.typesafe.scalalogging.LazyLogging +import models.aimodels.{AiModel, AiModelCategory, AiModelDAO} import models.annotation.{TracingStore, TracingStoreDAO} import models.dataset._ import models.folder.{Folder, FolderDAO, FolderService} @@ -42,6 +43,7 @@ class InitialDataService @Inject()(userService: UserService, taskTypeDAO: TaskTypeDAO, dataStoreDAO: DataStoreDAO, folderDAO: FolderDAO, + aiModelDAO: AiModelDAO, folderService: FolderService, tracingStoreDAO: TracingStoreDAO, teamDAO: TeamDAO, @@ -139,6 +141,19 @@ Samplecountry Some( "This is a wonderful dummy publication, it has authors, it has a link, it has a doi number, those could go here.\nLorem [ipsum](https://github.com/scalableminds/webknossos) dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.") ) + private val defaultDataStore = + DataStore(conf.Datastore.name, conf.Http.uri, conf.Datastore.publicUri.getOrElse(conf.Http.uri), conf.Datastore.key) + private val defaultAiModel = AiModel( + ObjectId("66544a56d20000af0e42ba0f"), + defaultOrganization._id, + defaultDataStore.name, + defaultUser._id, + None, + List.empty, + "sample_ai_model", + Some("Works if model files are manually placed at binaryData/sample_organization/66544a56d20000af0e42ba0f/"), + Some(AiModelCategory.em_neurons) + ) def insert: Fox[Unit] = for { @@ -158,6 +173,7 @@ Samplecountry _ <- insertTaskType() _ <- insertProject() _ <- insertPublication() + _ <- insertAiModel() } yield () private def assertInitialDataEnabled: Fox[Unit] = @@ -266,16 +282,18 @@ Samplecountry } else Fox.successful(()) } + private def insertAiModel(): Fox[Unit] = aiModelDAO.findAll.flatMap { aiModels => + if (aiModels.isEmpty) { + aiModelDAO.insertOne(defaultAiModel) + } else Fox.successful(()) + } + def insertLocalDataStoreIfEnabled(): Fox[Unit] = if (storeModules.localDataStoreEnabled) { dataStoreDAO.findOneByUrl(conf.Http.uri).futureBox.flatMap { maybeStore => if (maybeStore.isEmpty) { logger.info("Inserting local datastore") - dataStoreDAO.insertOne( - DataStore(conf.Datastore.name, - conf.Http.uri, - conf.Datastore.publicUri.getOrElse(conf.Http.uri), - conf.Datastore.key)) + dataStoreDAO.insertOne(defaultDataStore) } else Fox.successful(()) } } else Fox.successful(()) diff --git a/app/controllers/UserController.scala b/app/controllers/UserController.scala index 6fbd048f64..8e5b92af16 100755 --- a/app/controllers/UserController.scala +++ b/app/controllers/UserController.scala @@ -63,8 +63,7 @@ class UserController @Inject()(userService: UserService, annotations <- annotationDAO.findAllListableExplorationals( isFinished, Some(request.identity._id), - isForOwnDashboard = true, - AnnotationType.Explorational, + filterOwnedOrShared = true, limit.getOrElse(annotationService.DefaultAnnotationListLimit), pageNumber.getOrElse(0) ) @@ -118,8 +117,7 @@ class UserController @Inject()(userService: UserService, annotations <- annotationDAO.findAllListableExplorationals( isFinished, Some(userIdValidated), - isForOwnDashboard = false, - AnnotationType.Explorational, + filterOwnedOrShared = false, limit.getOrElse(annotationService.DefaultAnnotationListLimit), pageNumber.getOrElse(0) ) diff --git a/app/models/annotation/Annotation.scala b/app/models/annotation/Annotation.scala index 887bf7439c..cd0f0e38c2 100755 --- a/app/models/annotation/Annotation.scala +++ b/app/models/annotation/Annotation.scala @@ -359,20 +359,34 @@ class AnnotationDAO @Inject()(sqlClient: SqlClient, annotationLayerDAO: Annotati // format: on } + /** + * Find all annotations which are listable by the user specified in 'forUser' + * + * @param isFinished + * If set to `true`, only finished annotations are returned. If set to `false`, only active annotations are returned. + * If set to `None`, all non-cancelled annotations are returned. + * @param forUser + * If set, only annotations of this user are returned. If not set, all annotations are returned. + * @param filterOwnedOrShared + * If `true`, the function lists only annotations owned by the user or explicitly shared with them (used for the + * user's own dashboard). If `false`, it lists all annotations the viewer is allowed to see. + * @param limit + * The maximum number of annotations to return. + * @param pageNumber + * The page number to return. The first page is 0. + */ def findAllListableExplorationals( isFinished: Option[Boolean], forUser: Option[ObjectId], - // In dashboard, list only own + explicitly shared annotations. When listing those of another user, list all of their annotations the viewer is allowed to see - isForOwnDashboard: Boolean, - typ: AnnotationType, + filterOwnedOrShared: Boolean, limit: Int, pageNumber: Int = 0)(implicit ctx: DBAccessContext): Fox[List[AnnotationCompactInfo]] = for { - accessQuery <- if (isForOwnDashboard) accessQueryFromAccessQWithPrefix(listAccessQ, q"a.") + accessQuery <- if (filterOwnedOrShared) accessQueryFromAccessQWithPrefix(listAccessQ, q"a.") else accessQueryFromAccessQWithPrefix(readAccessQWithPrefix, q"a.") stateQuery = getStateQuery(isFinished) userQuery = forUser.map(u => q"a._user = $u").getOrElse(q"TRUE") - typQuery = q"a.typ = $typ" + typQuery = q"a.typ = ${AnnotationType.Explorational}" query = q"""WITH -- teams_agg is extracted to avoid left-join fanout. diff --git a/app/utils/WkConf.scala b/app/utils/WkConf.scala index c71a644185..0272635bbf 100644 --- a/app/utils/WkConf.scala +++ b/app/utils/WkConf.scala @@ -200,10 +200,6 @@ class WkConf @Inject()(configuration: Configuration) extends ConfigReader with L val environment: String = get[String]("airbrake.environment") } - object GoogleAnalytics { - val trackingId: String = get[String]("googleAnalytics.trackingId") - } - object SlackNotifications { val uri: String = get[String]("slackNotifications.uri") val verboseLoggingEnabled: Boolean = get[Boolean]("slackNotifications.verboseLoggingEnabled") @@ -259,7 +255,6 @@ class WkConf @Inject()(configuration: Configuration) extends ConfigReader with L Silhouette, Jobs, Airbrake, - GoogleAnalytics, BackendAnalytics, Slick, Voxelytics, diff --git a/app/views/main.scala.html b/app/views/main.scala.html index f78be6c1aa..921ea8c5e1 100755 --- a/app/views/main.scala.html +++ b/app/views/main.scala.html @@ -6,9 +6,6 @@ - @if(conf.GoogleAnalytics.trackingId.nonEmpty) { - - }