Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explore remote datasets in datastore #7800

Merged
merged 12 commits into from
May 22, 2024
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
- Non-admin or -manager users can no longer start long-running jobs that create datasets. This includes annotation materialization and AI inferrals. [#7753](https://github.com/scalableminds/webknossos/pull/7753)
- In the time tracking view, all annotations and tasks can be shown for each user by expanding the table. The individual time spans spent with a task or annotating an explorative annotation can be accessed via CSV export. The detail view including a chart for the individual spans has been removed. [#7733](https://github.com/scalableminds/webknossos/pull/7733)
- Slightly refactored the `<FixExpandleTable/>`component to use columns as props. [#7772](https://github.com/scalableminds/webknossos/pull/7772)
- The config value `datastore.localFolderWhitelist` can now be set for each datastore individually. [#7800](https://github.com/scalableminds/webknossos/pull/7800)

### Fixed
- Fixed a bug where a toast that was reopened had a flickering effect during the reopening animation. [#7793](https://github.com/scalableminds/webknossos/pull/7793)
Expand Down
8 changes: 3 additions & 5 deletions app/controllers/AnnotationIOController.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package controllers

import collections.SequenceUtils

import java.io.{BufferedOutputStream, File, FileOutputStream}
import java.util.zip.Deflater
import org.apache.pekko.actor.ActorSystem
Expand Down Expand Up @@ -266,11 +268,7 @@ class AnnotationIOController @Inject()(
}

private def assertAllOnSameDataset(skeletons: List[SkeletonTracing], volumes: List[VolumeTracing]): Fox[String] =
for {
datasetName <- volumes.headOption.map(_.datasetName).orElse(skeletons.headOption.map(_.datasetName)).toFox
_ <- bool2Fox(skeletons.forall(_.datasetName == datasetName))
_ <- bool2Fox(volumes.forall(_.datasetName == datasetName))
} yield datasetName
SequenceUtils.findUniqueElement(volumes.map(_.datasetName) ++ skeletons.map(_.datasetName)).toFox

private def assertAllOnSameOrganization(skeletons: List[SkeletonTracing],
volumes: List[VolumeTracing]): Fox[Option[String]] = {
Expand Down
53 changes: 17 additions & 36 deletions app/controllers/DatasetController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,24 @@ import com.scalableminds.util.accesscontext.{DBAccessContext, GlobalAccessContex
import com.scalableminds.util.geometry.{BoundingBox, Vec3Int}
import com.scalableminds.util.time.Instant
import com.scalableminds.util.tools.{Fox, TristateOptionJsonHelper}
import com.scalableminds.webknossos.datastore.models.datasource.{DataLayer, ElementClass, GenericDataSource}
import com.scalableminds.webknossos.datastore.models.datasource.ElementClass
import models.analytics.{AnalyticsService, ChangeDatasetSettingsEvent, OpenDatasetEvent}
import models.dataset._
import models.dataset.explore.{
ExploreAndAddRemoteDatasetParameters,
ExploreRemoteDatasetParameters,
ExploreRemoteLayerService
WKExploreRemoteLayerParameters,
WKExploreRemoteLayerService
}
import models.organization.OrganizationDAO
import models.team.{TeamDAO, TeamService}
import models.user.{User, UserDAO, UserService}
import net.liftweb.common.{Box, Empty, Failure, Full}
import play.api.i18n.{Messages, MessagesProvider}
import play.api.libs.functional.syntax._
import play.api.libs.json._
import play.api.mvc.{Action, AnyContent, PlayBodyParsers}
import utils.{ObjectId, WkConf}

import javax.inject.Inject
import scala.collection.mutable.ListBuffer
import scala.concurrent.{ExecutionContext, Future}
import com.scalableminds.webknossos.datastore.models.AdditionalCoordinate
import mail.{MailchimpClient, MailchimpTag}
Expand Down Expand Up @@ -71,7 +69,7 @@ class DatasetController @Inject()(userService: UserService,
conf: WkConf,
analyticsService: AnalyticsService,
mailchimpClient: MailchimpClient,
exploreRemoteLayerService: ExploreRemoteLayerService,
wkExploreRemoteLayerService: WKExploreRemoteLayerService,
sil: Silhouette[WkEnv])(implicit ec: ExecutionContext, bodyParsers: PlayBodyParsers)
extends Controller {

Expand Down Expand Up @@ -107,46 +105,29 @@ class DatasetController @Inject()(userService: UserService,
}
}

def exploreRemoteDataset(): Action[List[ExploreRemoteDatasetParameters]] =
sil.SecuredAction.async(validateJson[List[ExploreRemoteDatasetParameters]]) { implicit request =>
val reportMutable = ListBuffer[String]()
def exploreRemoteDataset(): Action[List[WKExploreRemoteLayerParameters]] =
sil.SecuredAction.async(validateJson[List[WKExploreRemoteLayerParameters]]) { implicit request =>
for {
dataSourceBox: Box[GenericDataSource[DataLayer]] <- exploreRemoteLayerService
.exploreRemoteDatasource(request.body, request.identity, reportMutable)
.futureBox
dataSourceOpt = dataSourceBox match {
case Full(dataSource) if dataSource.dataLayers.nonEmpty =>
reportMutable += s"Resulted in dataSource with ${dataSource.dataLayers.length} layers."
Some(dataSource)
case Full(_) =>
reportMutable += "Error when exploring as layer set: Resulted in zero layers."
None
case f: Failure =>
reportMutable += s"Error when exploring as layer set: ${Fox.failureChainAsString(f)}"
None
case Empty =>
reportMutable += "Error when exploring as layer set: Empty"
None
}
} yield Ok(Json.obj("dataSource" -> Json.toJson(dataSourceOpt), "report" -> reportMutable.mkString("\n")))
exploreResponse <- wkExploreRemoteLayerService.exploreRemoteDatasource(request.body, request.identity)
} yield Ok(Json.toJson(exploreResponse))
}

// Note: This route is used by external applications, keep stable
def exploreAndAddRemoteDataset(): Action[ExploreAndAddRemoteDatasetParameters] =
sil.SecuredAction.async(validateJson[ExploreAndAddRemoteDatasetParameters]) { implicit request =>
val reportMutable = ListBuffer[String]()
val adaptedParameters = ExploreRemoteDatasetParameters(request.body.remoteUri, None, None, None)
val adaptedParameters =
WKExploreRemoteLayerParameters(request.body.remoteUri, None, None, None, request.body.dataStoreName)
for {
dataSource <- exploreRemoteLayerService.exploreRemoteDatasource(List(adaptedParameters),
request.identity,
reportMutable)
exploreResponse <- wkExploreRemoteLayerService.exploreRemoteDatasource(List(adaptedParameters),
request.identity)
dataSource <- exploreResponse.dataSource ?~> "dataset.explore.failed"
_ <- bool2Fox(dataSource.dataLayers.nonEmpty) ?~> "dataset.explore.zeroLayers"
folderIdOpt <- Fox.runOptional(request.body.folderPath)(folderPath =>
folderService.getOrCreateFromPathLiteral(folderPath, request.identity._organization)) ?~> "dataset.explore.autoAdd.getFolder.failed"
_ <- exploreRemoteLayerService.addRemoteDatasource(dataSource,
request.body.datasetName,
request.identity,
folderIdOpt) ?~> "dataset.explore.autoAdd.failed"
_ <- wkExploreRemoteLayerService.addRemoteDatasource(dataSource,
request.body.datasetName,
request.identity,
folderIdOpt) ?~> "dataset.explore.autoAdd.failed"
} yield Ok
}

Expand Down
13 changes: 13 additions & 0 deletions app/models/dataset/WKRemoteDataStoreClient.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ package models.dataset
import com.scalableminds.util.cache.AlfuCache
import com.scalableminds.util.geometry.{BoundingBox, Vec3Int}
import com.scalableminds.util.tools.Fox
import com.scalableminds.webknossos.datastore.explore.{
ExploreRemoteDatasetRequest,
ExploreRemoteDatasetResponse,
ExploreRemoteLayerParameters
}
import com.scalableminds.webknossos.datastore.models.{AdditionalCoordinate, RawCuboidRequest}
import com.scalableminds.webknossos.datastore.models.datasource.{DataLayer, GenericDataSource}
import com.scalableminds.webknossos.datastore.rpc.RPC
Expand Down Expand Up @@ -102,4 +107,12 @@ class WKRemoteDataStoreClient(dataStore: DataStore, rpc: RPC) extends LazyLoggin
)
}

def exploreRemoteDataset(layerParameters: List[ExploreRemoteLayerParameters],
organizationName: String,
userToken: String): Fox[ExploreRemoteDatasetResponse] =
rpc(s"${dataStore.url}/data/datasets/exploreRemote")
.addQueryString("token" -> userToken)
.postJsonWithJsonResponse[ExploreRemoteDatasetRequest, ExploreRemoteDatasetResponse](
ExploreRemoteDatasetRequest(layerParameters, organizationName))

}
167 changes: 0 additions & 167 deletions app/models/dataset/explore/ExploreRemoteLayerService.scala

This file was deleted.

Loading