Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/src/main/scala/org/scastie/api/CompilerInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ object Problem {

case class Problem(
severity: Severity,
line: Option[Int],
startLine: Option[Int],
endLine: Option[Int],
startColumn: Option[Int],
endColumn: Option[Int],
Expand Down
23 changes: 21 additions & 2 deletions api/src/main/scala/org/scastie/api/ScalaTarget.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.scastie.api
import org.scastie.buildinfo.BuildInfo
import io.circe.generic.semiauto._
import io.circe._
import io.circe.syntax._

sealed trait ScalaTarget {
val targetType: ScalaTargetType
Expand Down Expand Up @@ -296,7 +297,25 @@ case class ScalaCli(scalaVersion: String) extends ScalaTarget {
}

object ScalaTarget {
implicit val scalaTargetEncoder: Encoder[ScalaTarget] = deriveEncoder[ScalaTarget]
implicit val scalaTargetDecoder: Decoder[ScalaTarget] = deriveDecoder[ScalaTarget]
implicit val scalaTargetEncoder: Encoder[ScalaTarget] = Encoder.instance {
case s: Scala2 => Json.obj("Scala2" -> s.asJson)
case s: Scala3 => Json.obj("Scala3" -> s.asJson)
case s: ScalaCli => Json.obj("ScalaCli" -> s.asJson)
case s: Js => Json.obj("Js" -> s.asJson)
case s: Native => Json.obj("Native" -> s.asJson)
case s: Typelevel => Json.obj("Typelevel" -> s.asJson)
}

implicit val scalaTargetDecoder: Decoder[ScalaTarget] = Decoder.instance { cursor =>
cursor.keys.flatMap(_.headOption) match {
case Some("Scala2") => cursor.downField("Scala2").as[Scala2]
case Some("Scala3") => cursor.downField("Scala3").as[Scala3]
case Some("ScalaCli") => cursor.downField("ScalaCli").as[ScalaCli]
case Some("Js") => cursor.downField("Js").as[Js]
case Some("Native") => cursor.downField("Native").as[Native]
case Some("Typelevel") => cursor.downField("Typelevel").as[Typelevel]
case other => Left(DecodingFailure(s"Unknown ScalaTarget type: $other", cursor.history))
}
}
}

11 changes: 11 additions & 0 deletions api/src/main/scala/org/scastie/api/SnippetId.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ case class SnippetUserPart(login: String, update: Int = 0)
object SnippetId {
def empty: SnippetId = SnippetId("", None)

def fromString(s: String): SnippetId = {
s.split('/') match {
case Array(uuid) => SnippetId(uuid, None)
case Array(login, uuid) =>
SnippetId(uuid, Some(SnippetUserPart(login, 0)))
case Array(login, uuid, update) =>
SnippetId(uuid, Some(SnippetUserPart(login, update.toInt)))
case _ => throw new IllegalArgumentException(s"Invalid snippet id: $s")
}
}
Comment thread
warcholjakub marked this conversation as resolved.

implicit val snippetIdEncoder: Encoder[SnippetId] = deriveEncoder[SnippetId]
implicit val snippetIdDecoder: Decoder[SnippetId] = deriveDecoder[SnippetId]
}
Expand Down
30 changes: 4 additions & 26 deletions balancer/src/main/scala/org/scastie/balancer/DispatchActor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.scastie.storage._
import org.scastie.storage.filesystem._
import org.scastie.storage.inmemory._
import org.scastie.storage.mongodb._
import org.scastie.storage.postgres.PostgresContainer
import org.scastie.util._
import com.typesafe.config.ConfigFactory

Expand Down Expand Up @@ -47,15 +48,6 @@ case class FetchUserSnippets(user: User)

case class ReceiveStatus(requester: ActorRef)

@deprecated("Scheduled for removal", "2023-04-30")
case class GetPrivacyPolicy(user: User)
@deprecated("Scheduled for removal", "2023-04-30")
case class SetPrivacyPolicy(user: User, status: Boolean)
@deprecated("Scheduled for removal", "2023-04-30")
case class RemovePrivacyPolicy(user: User)
@deprecated("Scheduled for removal", "2023-04-30")
case class RemoveAllUserSnippets(user: User)

case class Run(inputsWithIpAndUser: InputsWithIpAndUser, snippetId: SnippetId)

case class Done(progress: SnippetProgress, retries: Int)
Expand Down Expand Up @@ -117,7 +109,9 @@ class DispatchActor(progressActor: ActorRef, statusActor: ActorRef)
containerType match {
case "memory" => new InMemoryContainer()
case "mongo" => new MongoDBContainer()(ExecutionContext.fromExecutor(Executors.newWorkStealingPool()))
case "mongo-local" => new MongoDBContainer(defaultConfig = false)(ExecutionContext.fromExecutor(Executors.newWorkStealingPool()))
case "mongo-local" => new MongoDBContainer(defaultConfig = true)(ExecutionContext.fromExecutor(Executors.newWorkStealingPool()))
case "postgres" => new PostgresContainer()(ExecutionContext.fromExecutor(Executors.newWorkStealingPool()))
case "postgres-local" => new PostgresContainer(defaultConfig = true)(ExecutionContext.fromExecutor(Executors.newWorkStealingPool()))
case "files" => new FilesystemContainer(
Paths.get(config.getString("snippets-dir")),
Paths.get(config.getString("old-snippets-dir"))
Expand Down Expand Up @@ -198,10 +192,6 @@ class DispatchActor(progressActor: ActorRef, statusActor: ActorRef)
val sender = this.sender()
logError(container.readLatestSnippet(snippetId).map(sender ! _))

case FetchOldSnippet(id) =>
val sender = this.sender()
logError(container.readOldSnippet(id).map(sender ! _))

case FetchUserSnippets(user) =>
val sender = this.sender()
logError(container.listSnippets(UserLogin(user.login)).map(sender ! _))
Expand All @@ -217,18 +207,6 @@ class DispatchActor(progressActor: ActorRef, statusActor: ActorRef)
case FetchScalaJsSourceMap(snippetId) =>
val sender = this.sender()
logError(container.readScalaJsSourceMap(snippetId).map(sender ! _))
case GetPrivacyPolicy(user) =>
val sender = this.sender()
logError(container.getPrivacyPolicyResponse(UserLogin(user.login)).map(sender ! _))
case SetPrivacyPolicy(user, status) =>
val sender = this.sender()
logError(container.setPrivacyPolicyResponse(UserLogin(user.login), status).map(sender ! _))
case RemovePrivacyPolicy(user) =>
val sender = this.sender()
logError(container.deleteUser(UserLogin(user.login)).map(sender ! _))
case RemoveAllUserSnippets(user) =>
val sender = this.sender()
logError(container.removeUserSnippets(UserLogin(user.login)).map(sender ! _))

case x @ ReceiveStatus(requester) =>
sbtDispatcher.tell(x, sender())
Expand Down
8 changes: 7 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,13 @@ lazy val storage = project
libraryDependencies ++= Seq(
"org.mongodb.scala" %% "mongo-scala-driver" % "4.11.1",
"net.lingala.zip4j" % "zip4j" % "2.11.5",
"io.circe" %% "circe-parser" % "0.14.6"
"io.circe" %% "circe-parser" % "0.14.6",
"com.lihaoyi" %% "scalasql" % "0.2.2",
"io.scalaland" %% "chimney" % "1.8.2",
"org.postgresql" % "postgresql" % "42.7.8",
"org.flywaydb" % "flyway-core" % "11.13.2",
"org.flywaydb" % "flyway-database-postgresql" % "11.13.2",
"com.zaxxer" % "HikariCP" % "7.0.2"
)
)
.dependsOn(api.jvm(ScalaVersions.jvm), utils, instrumentation)
Expand Down
4 changes: 0 additions & 4 deletions client/src/main/scala/org/scastie/client/ModalState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ object ModalState {
def allClosed: ModalState = ModalState(
isHelpModalClosed = true,
isPrivacyPolicyModalClosed = true,
isPrivacyPolicyPromptClosed = true,
shareModalSnippetId = None,
isResetModalClosed = true,
isNewSnippetModalClosed = true,
Expand All @@ -25,7 +24,6 @@ object ModalState {
def default: ModalState = ModalState(
isHelpModalClosed = true,
isPrivacyPolicyModalClosed = true,
isPrivacyPolicyPromptClosed = true,
shareModalSnippetId = None,
isResetModalClosed = true,
isNewSnippetModalClosed = true,
Expand All @@ -38,8 +36,6 @@ object ModalState {
case class ModalState(
isHelpModalClosed: Boolean,
isPrivacyPolicyModalClosed: Boolean,
@deprecated("Scheduled for removal", "2023-04-30")
isPrivacyPolicyPromptClosed: Boolean,
shareModalSnippetId: Option[SnippetId],
isResetModalClosed: Boolean,
isNewSnippetModalClosed: Boolean,
Expand Down
16 changes: 0 additions & 16 deletions client/src/main/scala/org/scastie/client/RestApiClient.scala
Original file line number Diff line number Diff line change
Expand Up @@ -115,22 +115,6 @@ class RestApiClient(serverUrl: Option[String]) extends RestApi {
def changeUser(user: User): Future[Option[UserData]] =
post[UserData].using("/changeUser", user, async=false)

@deprecated("Scheduled for removal", "2023-04-30")
def getPrivacyPolicyStatus(): Future[Boolean] =
post[Boolean].using("/user/privacyPolicyStatus", "").map(_.getOrElse(true))

@deprecated("Scheduled for removal", "2023-04-30")
def acceptPrivacyPolicy(): Future[Boolean] =
post[Boolean].using("/user/acceptPrivacyPolicy", "", async=false).map(_.getOrElse(false))

@deprecated("Scheduled for removal", "2023-04-30")
def removeAllUserSnippets(): Future[Boolean] =
post[Boolean].using("/user/removeAllUserSnippets", "", async=false).map(_.getOrElse(false))

@deprecated("Scheduled for removal", "2023-04-30")
def removeUserFromPolicyStatus(): Future[Boolean] =
post[Boolean].using("/user/removeUserFromPolicyStatus", "", async=false).map(_.getOrElse(false))

def fetchUserSnippets(): Future[List[SnippetSummary]] =
get[List[SnippetSummary]]("/user/snippets").map(_.getOrElse(Nil))
}
41 changes: 0 additions & 41 deletions client/src/main/scala/org/scastie/client/ScastieBackend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,6 @@ case class ScastieBackend(scastieId: UUID, serverUrl: Option[String], scope: Bac
val closePrivacyPolicyModal: Reusable[Callback] =
Reusable.always(scope.modState(_.togglePrivacyPolicyModal))

val closePrivacyPolicyPrompt: Reusable[Callback] =
Reusable.always(scope.modState(_.setPrivacyPolicyPromptClosed(true)))

val openPrivacyPolicyPrompt: Reusable[Callback] =
Reusable.always(scope.modState(_.setPrivacyPolicyPromptClosed(false)))

val openLoginModal: Reusable[Callback] =
Reusable.always(scope.modState(_.setLoginModalClosed(false)))

Expand Down Expand Up @@ -330,37 +324,6 @@ case class ScastieBackend(scastieId: UUID, serverUrl: Option[String], scope: Bac
)
)

val acceptPolicy: Reusable[Callback] =
Reusable.always(
Callback.future {
restApiClient.acceptPrivacyPolicy().map { result =>
scope.modState(_.setPrivacyPolicyPromptClosed(result))
}
}
)

val removeUserFromPolicyStatus: Reusable[Callback] =
Reusable.always(
Callback.future {
restApiClient.removeUserFromPolicyStatus().map { result =>
scope.modState(_.setPrivacyPolicyPromptClosed(result)).map(_ => {
if (result) document.location.reload()
})
}
}
)

val removeAllUserSnippets: Reusable[Callback] =
Reusable.always(
Callback.future {
restApiClient.removeAllUserSnippets().map(Callback(_))
}
)

val refusePrivacyPolicy: Reusable[Callback] = Reusable.always(
removeAllUserSnippets >> removeUserFromPolicyStatus
)

private def saveCallback(sId: SnippetId): Callback = {
val setState = scope.modState(_.setCleanInputs.setSnippetId(sId).setLoadSnippet(false))
val page = Page.fromSnippetId(sId)
Expand Down Expand Up @@ -495,10 +458,6 @@ case class ScastieBackend(scastieId: UUID, serverUrl: Option[String], scope: Bac
restApiClient
.fetchUserData()
.map(result => scope.modState(_.setUserData(result)))
) >> Callback.future(
restApiClient
.getPrivacyPolicyStatus()
.map(result => scope.modState(_.setPrivacyPolicyPromptClosed(result)))
)

def changeUser(user: User): Callback =
Expand Down
4 changes: 0 additions & 4 deletions client/src/main/scala/org/scastie/client/ScastieState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,6 @@ case class ScastieState(
modalState = modalState.copy(isPrivacyPolicyModalClosed = !modalState.isPrivacyPolicyModalClosed)
)

def setPrivacyPolicyPromptClosed(status: Boolean): ScastieState = copyAndSave(
modalState = modalState.copy(isPrivacyPolicyPromptClosed = status)
)

def setLoginModalClosed(status: Boolean): ScastieState = copyAndSave(
modalState = modalState.copy(isLoginModalClosed = status)
)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,6 @@ object Scastie {
close = scope.backend.closeLoginModal,
openPrivacyPolicyModal = scope.backend.openPrivacyPolicyModal
).render,
PrivacyPolicyPrompt(
isDarkTheme = state.isDarkTheme,
isClosed = state.modalState.isPrivacyPolicyPromptClosed,
acceptPrivacyPolicy = scope.backend.acceptPolicy,
refusePrivacyPolicy = scope.backend.refusePrivacyPolicy,
openPrivacyPolicyModal = scope.backend.openPrivacyPolicyModal
).render,
PrivacyPolicyModal(
isDarkTheme = state.isDarkTheme,
isClosed = state.modalState.isPrivacyPolicyModalClosed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ object CodeEditor {

def problemToDiagnostics(problem: Problem, doc: Text): Seq[Diagnostic] = {
val maxLine = doc.lines.toInt
val startLine = problem.line.get.max(1).min(maxLine)
val startLine = problem.startLine.get.max(1).min(maxLine)
val endLine = problem.endLine.getOrElse(startLine).max(1).min(maxLine)

val renderMessage = (_: EditorView) => {
Expand Down Expand Up @@ -156,7 +156,7 @@ object CodeEditor {
}

val to = if (isEndLine) {
if (problem.line.get > maxLine && isStartLine) {
if (problem.startLine.get > maxLine && isStartLine) {
lineInfo.to
} else {
problem.endColumn match {
Expand Down Expand Up @@ -217,7 +217,7 @@ object CodeEditor {

private def getDecorations(props: CodeEditor, doc: Text): js.Array[Diagnostic] = {
val errors = props.compilationInfos
.filter(prob => prob.line.isDefined)
.filter(prob => prob.startLine.isDefined)
.flatMap(problemToDiagnostics(_, doc))

val runtimeErrors = props.runtimeError.map(runtimeError => {
Expand Down
7 changes: 7 additions & 0 deletions deployment/postgres.template.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
org.scastie.postgres {
user=<user>
password=<password>
database=<database>
host=<host>
port=<port>
}
Loading