From 79abd8b2bb39eeeb3dcbe9352c9294dccae9a7ac Mon Sep 17 00:00:00 2001 From: Andrea Minetti Date: Fri, 30 Oct 2026 11:34:20 +0100 Subject: [PATCH 1/2] Fixed popup saving --- .../scala/ch/wsl/box/client/services/Navigate.scala | 11 +++++++++-- .../widget/functions/FunctionLinkWidget.scala | 2 -- .../wsl/box/client/views/helpers/ActionRenderer.scala | 7 +++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/client/src/main/scala/ch/wsl/box/client/services/Navigate.scala b/client/src/main/scala/ch/wsl/box/client/services/Navigate.scala index 2ed471f1..9b6ab9dd 100755 --- a/client/src/main/scala/ch/wsl/box/client/services/Navigate.scala +++ b/client/src/main/scala/ch/wsl/box/client/services/Navigate.scala @@ -7,6 +7,8 @@ import io.udash.{State, Url} import org.scalajs.dom.{BeforeUnloadEvent, window} import scribe.Logging +import scala.concurrent.Future + object Navigate extends Logging { private var enabled:Boolean = true @@ -29,7 +31,7 @@ object Navigate extends Logging { } } - def toUrl(url:String, target:Target = Self):Unit = { + def toUrl(url:String, target:Target = Self):Future[Boolean] = { logger.debug(s"navigate to $url") @@ -44,8 +46,12 @@ object Navigate extends Logging { } else { Context.applicationInstance.goTo(state) } + + } + case NewWindow => { + window.open(url,"_blank") + Future.successful(true) } - case NewWindow => window.open(url,"_blank") case Popup => PopupFrame.open(url) } @@ -64,6 +70,7 @@ object Navigate extends Logging { window.onbeforeunload = { (e:BeforeUnloadEvent) => } //is a new page i don't want to block the user anymore action() } + Future.successful(true) } diff --git a/client/src/main/scala/ch/wsl/box/client/views/components/widget/functions/FunctionLinkWidget.scala b/client/src/main/scala/ch/wsl/box/client/views/components/widget/functions/FunctionLinkWidget.scala index d1d63b30..01039fd2 100644 --- a/client/src/main/scala/ch/wsl/box/client/views/components/widget/functions/FunctionLinkWidget.scala +++ b/client/src/main/scala/ch/wsl/box/client/views/components/widget/functions/FunctionLinkWidget.scala @@ -55,8 +55,6 @@ object FunctionLinkWidget extends ComponentWidgetFactory { val clickHandler = { (e: Event) => - logger.warn("HELLO") - val function = field.function.get val functionParams = function.local_fields.zip(function.function_fields).map{ case (l,f) => diff --git a/client/src/main/scala/ch/wsl/box/client/views/helpers/ActionRenderer.scala b/client/src/main/scala/ch/wsl/box/client/views/helpers/ActionRenderer.scala index 3031226e..28145396 100644 --- a/client/src/main/scala/ch/wsl/box/client/views/helpers/ActionRenderer.scala +++ b/client/src/main/scala/ch/wsl/box/client/views/helpers/ActionRenderer.scala @@ -113,15 +113,18 @@ class ActionRenderer( case SaveLocalAction => handler.beforeSave(action.html5check).flatMap(handler.saveLocally).map(afterSaveAction) case SaveAndClosePopup => handler.beforeSave(action.html5check).flatMap(handler.saveToDb).map{ _ => ModalStack.mainStack.removeLast() } case NoAction => Routes.getUrl(action,handler.data.get,metadata.kind,metadata.name,_id,intent.write).foreach{ url => - executeFunction().map { + executeFunction().flatMap { case Some(true) => { if (Navigate.canGoAway) reset() Navigate.toUrl(url,action.target) } case None => Navigate.toUrl(url,action.target) - case Some(false) => () + case Some(false) => Future.successful() + }.foreach{ _ => + if(action.reload) handler.reload() + else services.clientSession.loading.set(false) } } case CopyAction => handler.duplicate() From 46fe3e5d1f57cc2d5b941f81f702220bdb67fcd3 Mon Sep 17 00:00:00 2001 From: Andrea Minetti Date: Fri, 30 Oct 2026 11:40:22 +0100 Subject: [PATCH 2/2] Sort columns --- .../box/client/views/EntityTableView.scala | 2 +- .../views/components/table/FilterBarDyn.scala | 85 +------------------ 2 files changed, 3 insertions(+), 84 deletions(-) diff --git a/client/src/main/scala/ch/wsl/box/client/views/EntityTableView.scala b/client/src/main/scala/ch/wsl/box/client/views/EntityTableView.scala index fe621da2..a990b0f7 100755 --- a/client/src/main/scala/ch/wsl/box/client/views/EntityTableView.scala +++ b/client/src/main/scala/ch/wsl/box/client/views/EntityTableView.scala @@ -1041,7 +1041,7 @@ case class EntityTableView(model:ModelProperty[EntityTableModel], presenter:Enti headerFactory = Some(_ => div(Labels.table.column_selection).render), bodyFactory = Some { nested => div( - metadata.nativeFields.filterNot(_.`type` == JSONFieldTypes.GEOMETRY).map{ c => + metadata.nativeFields.sortBy(_.title).filterNot(_.`type` == JSONFieldTypes.GEOMETRY).map{ c => div( Checkbox(localModel.bitransform(_.contains(c)){ case true => localModel.get ++ Seq(c) diff --git a/client/src/main/scala/ch/wsl/box/client/views/components/table/FilterBarDyn.scala b/client/src/main/scala/ch/wsl/box/client/views/components/table/FilterBarDyn.scala index adb0b35a..5ac72faf 100644 --- a/client/src/main/scala/ch/wsl/box/client/views/components/table/FilterBarDyn.scala +++ b/client/src/main/scala/ch/wsl/box/client/views/components/table/FilterBarDyn.scala @@ -19,87 +19,6 @@ class FilterBarDyn(val filters:Property[Seq[JSONQueryFilter]],sorts:Property[Seq import scalacss.ScalatagsCss._ import scalatags.JsDom.all._ - //val filterFields:Property[Seq[FieldQuery]] = fieldQueries.bitransform(_.filter(_.filterValue.nonEmpty))(s => fieldQueries.get.map(f => s.find(_.field.name == f.field.name).getOrElse(f))) -// val _filterFields:Property[Seq[JSONField]] = Property(Seq()) -// val _filterFields:SeqProperty[JSONField] = SeqProperty(Seq()) -// -// val _sortFields:SeqProperty[JSONField] = SeqProperty(Seq()) - -// fieldQueries.listen({x => -// val newFilters:Seq[JSONField] = x.filter(y => y.filterValue.nonEmpty && !_filterFields.get.map(_.name).contains(y.field.name)).map(_.field) -// _filterFields.append(newFilters:_*) -// -// val newSorts:Seq[JSONField] = x.filter(y => y.sort.nonEmpty && !_sortFields.get.map(_.name).contains(y.field.name)).map(_.field) -// _sortFields.append(newSorts:_*) -// },initUpdate = true) - -// def _render(columns: Seq[JSONField], metadata: JSONMetadata): HTMLElement = { -// -// div( ClientConf.style.filterDynBar, -// //div(pre(bind(fieldQueries.transform(_.map(x => s"Field: ${x.field.name}, ${x.filterValue} , Sort: ${x.sort} ${x.sortOrder}").mkString("\n"))))), -// div(ClientConf.style.filterBlockTitle,Icons.filter,"Filters"), -// repeat(_filterFields) { (fieldProp) => -// div(ClientConf.style.filterBlock, -// Select(fieldProp,fieldQueries.transformToSeq(_.map(_.field)))(_.title), -// produce(fieldProp) { (field) => -// -// val (filterValue,operator) = filterPropsField(field) -// -// div( -// display.flex,alignItems.center, -// filterOptions(metadata, field.name, operator)(), -// produceWithNested(operator) { (op, nested) => -// div(filterField(filterValue, field, op, nested)()).render -// }, -// button(Icons.x,ClientConf.style.boxButtonIconMini,onclick :+= ((e:Event) => { -// filterValue.set("") -// _filterFields.remove(field) -// })) -// ).render -// }, -// -// ).render -// }, -// -// button(Icons.plus,ClientConf.style.boxButton,onclick :+= ((e:Event) => { -// fieldQueries.get.find(_.filterValue.isEmpty).map(x => _filterFields.append(x.field)) -// })), -// div(Icons.asc,"Sort",ClientConf.style.filterBlockTitle), -// repeatWithIndex(_sortFields) { case (fieldProp,i,nested) => -// div(ClientConf.style.filterBlock, -// Select(fieldProp,fieldQueries.transformToSeq(_.map(_.field)))(_.title), -// produce(fieldProp.combine(i)((x,y) => (x,y))) { case (field, i) => -// -// val sortProp = fieldQueries.bitransform(_.find(_.field == field).map(_.sort))(x => fieldQueries.get.map { fq => if (fq.field == field) { -// x match { -// case Some(value) => fq.copy(sort = value, sortOrder = Some(i+1)) -// case None => fq.copy(sort = "", sortOrder = None) -// } -// -// } else fq }) -// div( -// display.flex,alignItems.center, -// Select.optional(sortProp, SeqProperty(Seq(Sort.ASC,Sort.DESC)),"---")(x => x.toUpperCase), -// button(Icons.x,ClientConf.style.boxButtonIconMini,onclick :+= ((e:Event) => { -// sortProp.set(None) -// _sortFields.remove(field) -// fieldQueries.set(fieldQueries.get.map{fq => -// if(fq.sortOrder.exists(_ > i+1)) { -// fq.copy(sortOrder = fq.sortOrder.map(_ - 1)) -// } else fq -// }) -// -// })) -// ).render -// } -// -// ).render -// }, -// button(Icons.plus,ClientConf.style.boxButton,onclick :+= ((e:Event) => { -// fieldQueries.get.find(_.sort.isEmpty).map(x => _sortFields.append(x.field)) -// })), -// ).render -// } val modalId = UUID.randomUUID() @@ -115,7 +34,7 @@ class FilterBarDyn(val filters:Property[Seq[JSONQueryFilter]],sorts:Property[Seq bodyFactory = Some(n => { div( display.flex,alignItems.center,justifyContent.spaceAround,flexDirection.column,height := 200.px, - Select(sortField,columns.toSeqProperty)(_.title), + Select(sortField,columns.sortBy(_.title).toSeqProperty)(_.title), Select(sortDirection, SeqProperty(Seq(Sort.ASC,Sort.DESC)))(x => x.toUpperCase), ).render }), @@ -163,7 +82,7 @@ class FilterBarDyn(val filters:Property[Seq[JSONQueryFilter]],sorts:Property[Seq bodyFactory = Some(n => { div( display.flex,alignItems.center,justifyContent.spaceAround,flexDirection.column,height := 200.px, - Select(_filterField,columns.toSeqProperty)(_.title), + Select(_filterField,columns.sortBy(_.title).toSeqProperty)(_.title), n(produce(_filterField){ f => val filterValue: Property[String] = filterProp.bitransform[String](_.value.getOrElse(""))(x => { if(x.isEmpty) filterProp.get.copy(value = None) else filterProp.get.copy(value = Some(x)) })