From eddf94d9ab03794c02c919685ebc877a1a355067 Mon Sep 17 00:00:00 2001 From: Valeriy Gavrilin Date: Tue, 5 Nov 2019 14:07:48 +0300 Subject: [PATCH] Frontend fixes --- .../webapp/components/common/TextEditor.scala | 19 +++-- .../folder/PreviewsFileListItem.scala | 9 ++- .../webapp/components/folder/UploadForm.scala | 70 +++++++++++-------- .../webapp/utils/LocalStorage.scala | 19 +++++ tika-custom.xml | 4 +- 5 files changed, 76 insertions(+), 45 deletions(-) create mode 100644 server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/utils/LocalStorage.scala diff --git a/server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/components/common/TextEditor.scala b/server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/components/common/TextEditor.scala index 8a4c1c23..af2e1811 100644 --- a/server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/components/common/TextEditor.scala +++ b/server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/components/common/TextEditor.scala @@ -1,11 +1,10 @@ package com.karasiq.shadowcloud.webapp.components.common -import rx.Var - import com.karasiq.bootstrap.Bootstrap.default._ -import scalaTags.all._ - import com.karasiq.shadowcloud.webapp.context.AppContext +import com.karasiq.shadowcloud.webapp.utils.LocalStorage +import rx.Var +import scalaTags.all._ object TextEditor { def apply(_onSubmit: TextEditor ⇒ Unit)(implicit context: AppContext): TextEditor = { @@ -13,10 +12,17 @@ object TextEditor { def onSubmit(): Unit = _onSubmit(this) } } + + def memoized(key: String)(_onSubmit: TextEditor ⇒ Unit)(implicit context: AppContext): TextEditor = { + new TextEditor { + override val value: Var[String] = LocalStorage.memoize(key) + def onSubmit(): Unit = _onSubmit(this) + } + } } -abstract class TextEditor(implicit context: AppContext) extends BootstrapHtmlComponent { - val value = Var("") +sealed abstract class TextEditor(implicit context: AppContext) extends BootstrapHtmlComponent { + val value = Var("") val submitting = Var(false) def onSubmit(): Unit @@ -29,4 +35,3 @@ abstract class TextEditor(implicit context: AppContext) extends BootstrapHtmlCom ) } } - diff --git a/server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/components/folder/PreviewsFileListItem.scala b/server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/components/folder/PreviewsFileListItem.scala index 6a5e26a3..cb7dccec 100644 --- a/server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/components/folder/PreviewsFileListItem.scala +++ b/server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/components/folder/PreviewsFileListItem.scala @@ -2,17 +2,14 @@ package com.karasiq.shadowcloud.webapp.components.folder import scala.language.postfixOps import scala.scalajs.concurrent.JSExecutionContext.Implicits.queue - import rx._ import rx.async._ - import com.karasiq.bootstrap.Bootstrap.default._ import scalaTags.all._ - import com.karasiq.common.memory.MemorySize import com.karasiq.shadowcloud.model.File import com.karasiq.shadowcloud.webapp.components.common.AppIcons -import com.karasiq.shadowcloud.webapp.components.file.FilePreview +import com.karasiq.shadowcloud.webapp.components.file.{FileDownloadLink, FilePreview} import com.karasiq.shadowcloud.webapp.components.file.FilePreview.PreviewVariants import com.karasiq.shadowcloud.webapp.context.{AppContext, FolderContext} import com.karasiq.shadowcloud.webapp.utils.Blobs @@ -30,6 +27,8 @@ class PreviewsFileListItem(file: File, selectedFile: Var[Option[File]])(implicit } def renderTag(md: ModifierT*): TagT = { + val fileLink = FileDownloadLink(file)(file.path.name) + GridSystem.row( GridSystem.col(3)( Rx[Frag](previews().image match { @@ -47,7 +46,7 @@ class PreviewsFileListItem(file: File, selectedFile: Var[Option[File]])(implicit ), GridSystem.col(9)( GridSystem.row( - GridSystem.col(9)(Rx[Frag](if (selectedFile().contains(file)) b(file.path.name) else span(file.path.name, cursor.pointer))), + GridSystem.col(9)(Rx[Frag](if (selectedFile().contains(file)) b(fileLink) else span(fileLink, cursor.pointer))), GridSystem.col(3)( GridSystem.mkRow(MemorySize.toString(file.checksum.size)), GridSystem.mkRow(context.timeFormat.timestamp(file.timestamp.lastModified)), diff --git a/server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/components/folder/UploadForm.scala b/server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/components/folder/UploadForm.scala index db90e6b3..d5c3a161 100644 --- a/server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/components/folder/UploadForm.scala +++ b/server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/components/folder/UploadForm.scala @@ -1,33 +1,37 @@ package com.karasiq.shadowcloud.webapp.components.folder -import scala.annotation.tailrec -import scala.concurrent.Future -import org.scalajs.dom -import rx.{Rx, Var} import com.karasiq.bootstrap.Bootstrap.default._ -import scalaTags.all._ import com.karasiq.common.memory.SizeUnit import com.karasiq.shadowcloud.model.{File, Path, RegionId} import com.karasiq.shadowcloud.utils.Utils import com.karasiq.shadowcloud.webapp.components.common.{AppComponents, AppIcons, Dropzone, TextEditor} -import com.karasiq.shadowcloud.webapp.context.{AppContext, FolderContext} import com.karasiq.shadowcloud.webapp.context.AppContext.JsExecutionContext +import com.karasiq.shadowcloud.webapp.context.{AppContext, FolderContext} import com.karasiq.shadowcloud.webapp.controllers.FileController +import org.scalajs.dom +import rx.{Rx, Var} +import scalaTags.all._ + +import scala.annotation.tailrec +import scala.concurrent.Future object UploadForm { def apply()(implicit appContext: AppContext, folderContext: FolderContext, fileController: FileController): UploadForm = { new UploadForm } - private def newNoteName(text: String): String = { - val conciseName = Utils.takeWords(text, 50) - .replaceAll("\\s+", " ") - .trim + private def uploadNoteOrPage(regionId: RegionId, path: Path, text: String)(implicit appContext: AppContext): Future[File] = { + def newNoteName(text: String): String = { + val firstLine = text.lines.toStream.headOption.getOrElse("") - conciseName + ".md" - } + val conciseName = Utils + .takeWords(firstLine, 50) + .replaceAll("\\s+", " ") + .trim + + conciseName + ".md" + } - private def uploadNoteOrPage(regionId: RegionId, path: Path, text: String)(implicit appContext: AppContext): Future[File] = { if (text.matches("https?://[^\\s]+")) { appContext.api.saveWebPage(regionId, path, text) } else { @@ -40,21 +44,16 @@ class UploadForm(implicit appContext: AppContext, folderContext: FolderContext, private[this] final case class UploadRequest(regionId: RegionId, path: Path, file: dom.File) - private[this] val maxUploads = 5 - private[this] val maxUploadsSize = SizeUnit.MB * 8 + private[this] val maxUploads = 5 + private[this] val maxUploadsSize = SizeUnit.MB * 8 private[this] val uploadProgressBars = div().render - private[this] val uploadQueue = Var(List.empty[UploadRequest]) - private[this] val uploading = Var(List.empty[UploadRequest]) + private[this] val uploadQueue = Var(List.empty[UploadRequest]) + private[this] val uploading = Var(List.empty[UploadRequest]) uploadQueue.triggerLater(processQueue()) uploading.triggerLater(processQueue()) def renderTag(md: ModifierT*): TagT = { -// val uploadInput = FormInput.file(appContext.locale.file, multiple, md, onchange := Callback.onInput { input ⇒ -// -// input.form.reset() -// }) - val editor = TextEditor { editor ⇒ editor.submitting() = true val future = UploadForm.uploadNoteOrPage(folderContext.regionId, folderContext.selected.now, editor.value.now) @@ -68,10 +67,19 @@ class UploadForm(implicit appContext: AppContext, folderContext: FolderContext, } val navigation = Navigation.pills( - NavigationTab(appContext.locale.uploadFiles, "upload-files", NoIcon, Form(action := "/", `class` := "dropzone", Dropzone { file => - // Preserve context at click time - uploadQueue() = uploadQueue.now :+ UploadRequest(folderContext.regionId, folderContext.selected.now, file) - })), + NavigationTab( + appContext.locale.uploadFiles, + "upload-files", + NoIcon, + Form( + action := "/", + `class` := "dropzone", + Dropzone { file => + // Preserve context at click time + uploadQueue() = uploadQueue.now :+ UploadRequest(folderContext.regionId, folderContext.selected.now, file) + } + ) + ), NavigationTab(appContext.locale.pasteText, "paste-text", NoIcon, editor) ) @@ -82,7 +90,7 @@ class UploadForm(implicit appContext: AppContext, folderContext: FolderContext, } def renderModal(md: ModifierT*): Modal = { - Modal(appContext.locale.uploadFiles, renderTag(md:_*), AppComponents.modalClose(), dialogStyle = ModalDialogSize.large) + Modal(appContext.locale.uploadFiles, renderTag(md: _*), AppComponents.modalClose(), dialogStyle = ModalDialogSize.large) } def renderButton(md: ModifierT*): TagT = { @@ -95,7 +103,7 @@ class UploadForm(implicit appContext: AppContext, folderContext: FolderContext, val styles = Seq(ProgressBarStyle.success, ProgressBarStyle.striped, ProgressBarStyle.animated) div( div(b(fileName)), - ProgressBar.withLabel(progress).renderTag(styles:_*), + ProgressBar.withLabel(progress).renderTag(styles: _*), hr ) } @@ -105,7 +113,8 @@ class UploadForm(implicit appContext: AppContext, folderContext: FolderContext, @tailrec def limitUploads(list: Seq[UploadRequest], maxSize: Long, currentCount: Int = 0): Seq[UploadRequest] = { val newListSize = list .take(currentCount + 1) - .map(_.file.size.toLong).sum + .map(_.file.size.toLong) + .sum if (newListSize > maxSize || currentCount >= list.length) list.take(currentCount) @@ -127,7 +136,7 @@ class UploadForm(implicit appContext: AppContext, folderContext: FolderContext, if (toUpload.nonEmpty) { toUpload.foreach { request ⇒ val (progressRx, fileFuture) = appContext.api.uploadFile(request.regionId, request.path / request.file.name, request.file) - val progressBar = renderProgressBar(request.file.name, progressRx).render + val progressBar = renderProgressBar(request.file.name, progressRx).render uploadProgressBars.appendChild(progressBar) fileFuture.onComplete { _ ⇒ @@ -144,4 +153,3 @@ class UploadForm(implicit appContext: AppContext, folderContext: FolderContext, } } } - diff --git a/server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/utils/LocalStorage.scala b/server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/utils/LocalStorage.scala new file mode 100644 index 00000000..f48ea6dc --- /dev/null +++ b/server/webapp/src/main/scala/com/karasiq/shadowcloud/webapp/utils/LocalStorage.scala @@ -0,0 +1,19 @@ +package com.karasiq.shadowcloud.webapp.utils + +import org.scalajs.dom +import org.scalajs.dom.window.localStorage +import rx.{Ctx, Var} +import rx.async.Platform.DefaultScheduler +import rx.async._ + +import scala.concurrent.duration._ + +object LocalStorage { + def memoize(key: String)(implicit owner: Ctx.Owner): Var[String] = { + val value = Var(Option(localStorage.getItem(key)).getOrElse("")) + def updateLS(): Unit = localStorage.setItem(key, value.now) + value.debounce(300 millis).triggerLater(updateLS()) + dom.window.addEventListener("unload", (_: dom.Event) => updateLS()) + value + } +} diff --git a/tika-custom.xml b/tika-custom.xml index f8749e24..8d29c92a 100644 --- a/tika-custom.xml +++ b/tika-custom.xml @@ -11,9 +11,9 @@ - 3000 + 1500 512000 - rus + eng