Use collective settings for shares

This commit is contained in:
eikek
2022-01-29 14:15:49 +01:00
parent 3710f525d1
commit e1a8b9b121
7 changed files with 60 additions and 55 deletions

View File

@ -6,6 +6,7 @@
package docspell.backend.ops
import cats.Semigroup
import cats.data.OptionT
import cats.effect.{Async, Resource}
import cats.implicits._
@ -32,6 +33,7 @@ trait OClientSettings[F[_]] {
account: AccountId
): F[Option[RClientSettingsCollective]]
def loadMerged(clientId: Ident, account: AccountId): F[Option[Json]]
}
object OClientSettings {
@ -108,5 +110,14 @@ object OClientSettings {
data <- OptionT(store.transact(RClientSettingsUser.find(clientId, userId)))
} yield data).value
def loadMerged(clientId: Ident, account: AccountId) =
for {
collData <- loadCollective(clientId, account)
userData <- loadUser(clientId, account)
mergedData = collData.map(_.settingsData) |+| userData.map(_.settingsData)
} yield mergedData
implicit def jsonSemigroup: Semigroup[Json] =
Semigroup.instance((a1, a2) => a1.deepMerge(a2))
})
}

View File

@ -2356,13 +2356,7 @@ paths:
summary: Return the client settings of current user
description: |
Returns the settings for the share. This is the settings of
the user who created the share. It is created by merging the
client settings for the collective and the user's own client
settings into one json structure.
Null, Array, Boolean, String and Number are treated as values,
and values from the users settings completely replace values
from the collective's settings.
the collective that belongs to the share.
The `clientId` is an identifier to a client application. It
returns a JSON structure. The server doesn't care about the

View File

@ -6,10 +6,9 @@
package docspell.restserver.routes
import cats.data.OptionT
import cats.effect._
import cats.implicits._
import cats.{Monad, Semigroup}
import cats.data.OptionT
import docspell.backend.BackendApp
import docspell.backend.auth.{AuthToken, ShareToken}
@ -33,17 +32,15 @@ object ClientSettingsRoutes {
val dsl = new Http4sDsl[F] {}
import dsl._
HttpRoutes.of {
case GET -> Root / Ident(clientId) =>
(for {
_ <- OptionT.liftF(logger.debug(s"Get client settings for share ${token.id}"))
share <- backend.share.findActiveById(token.id)
merged <- OptionT.liftF(getMergedSettings(backend, share.user.accountId, clientId))
res <- OptionT.liftF(merged match {
case Some(j) => Ok(j)
case None => NotFound()
})
} yield res)
HttpRoutes.of { case GET -> Root / Ident(clientId) =>
(for {
_ <- OptionT.liftF(logger.debug(s"Get client settings for share ${token.id}"))
share <- backend.share.findActiveById(token.id)
sett <- OptionT(
backend.clientSettings.loadCollective(clientId, share.user.accountId)
)
res <- OptionT.liftF(Ok(sett.settingsData))
} yield res)
.getOrElseF(Ok(Map.empty[String, String]))
}
}
@ -55,11 +52,10 @@ object ClientSettingsRoutes {
HttpRoutes.of {
case GET -> Root / Ident(clientId) =>
for {
mergedData <- getMergedSettings(backend, user.account, clientId)
mergedData <- backend.clientSettings.loadMerged(clientId, user.account)
res <- mergedData match {
case Some(j) => Ok(j)
case None => NotFound()
case None => Ok(Map.empty[String, String])
}
} yield res
@ -118,17 +114,4 @@ object ClientSettingsRoutes {
} yield res
}
}
def getMergedSettings[F[_]: Monad](backend:BackendApp[F], account: AccountId, clientId: Ident) =
for {
collData <- backend.clientSettings.loadCollective(clientId, account)
userData <- backend.clientSettings.loadUser(clientId, account)
mergedData = collData.map(_.settingsData) |+| userData.map(_.settingsData)
} yield mergedData
implicit def jsonSemigroup: Semigroup[Json] =
Semigroup.instance((a1, a2) => a1.deepMerge(a2))
}

View File

@ -580,7 +580,6 @@ update flags sett msg model =
TagsTab ->
{ sett | tagCategoryColors = Nothing }
-- no reset here
FieldsTab ->
{ sett | formFields = Nothing }
@ -658,7 +657,7 @@ settingFormTabs texts flags _ model =
, onClick (ResetTab tab)
]
[ i [ class "fa fa-eraser mr-1" ] []
, text "Reset"
, text texts.resetLabel
]
in
[ { name = akkordionTabName GeneralTab

View File

@ -28,7 +28,9 @@ import Html.Attributes exposing (..)
import Http
import Messages.Comp.UiSettingsManage exposing (Texts)
import Page.Search.Data exposing (Msg(..))
import Process
import Styles as S
import Task
type alias Model =
@ -67,6 +69,7 @@ type Msg
| ReceiveServerSettings (Result Http.Error ( StoredUiSettings, StoredUiSettings ))
| ToggleExpandCollapse
| SwitchForm AccountScope
| ResetFormState
init : Flags -> ( Model, Cmd Msg )
@ -134,12 +137,6 @@ update flags settings msg model =
| collSettings = Maybe.withDefault data.collSettings sett
, collModel = m_
}
, formResult =
if sett /= Nothing then
FormInit
else
model.formResult
}
Data.AccountScope.User ->
@ -155,12 +152,6 @@ update flags settings msg model =
| userSettings = Maybe.withDefault data.userSettings sett
, userModel = m_
}
, formResult =
if sett /= Nothing then
FormInit
else
model.formResult
}
Submit ->
@ -198,9 +189,13 @@ update flags settings msg model =
update flags
settings
(ReceiveServerSettings (Ok ( data.collSettings, data.userSettings )))
model
{ model | formResult = FormSaved }
cmd =
Process.sleep 2000
|> Task.perform (\_ -> ResetFormState)
in
{ result | appEvent = AppReloadUiSettings }
{ result | appEvent = AppReloadUiSettings, cmd = Cmd.batch [ cmd, result.cmd ] }
_ ->
unit { model | formResult = FormUnknownError }
@ -231,7 +226,13 @@ update flags settings msg model =
, collSettings = coll
, collModel = cm
}
, formModel = ViewUser
, formModel =
case model.formModel of
ViewLoading ->
ViewUser
_ ->
model.formModel
}
cmds =
@ -262,6 +263,14 @@ update flags settings msg model =
in
Data.AccountScope.fold forUser forColl scope
ResetFormState ->
case model.formResult of
FormSaved ->
unit { model | formResult = FormInit }
_ ->
unit model
isError : Model -> Bool
isError model =
@ -364,6 +373,9 @@ view2 texts flags _ classes model =
[ h2 [ class S.header2 ]
[ text texts.collectiveHeader
]
, div [ class "py-1 opacity-80" ]
[ text texts.collectiveInfo
]
, Html.map (UiFormMsg scope)
(Comp.UiSettingsForm.view2
texts.uiSettingsForm

View File

@ -56,6 +56,7 @@ type alias Texts =
, fieldLabel : Field -> String
, templateHelpMessage : String
, pdfMode : PdfMode -> String
, resetLabel : String
}
@ -131,6 +132,7 @@ and if that is not present the person. If both are absent a dash `-`
is rendered.
"""
, pdfMode = Messages.Data.PdfMode.gb
, resetLabel = "Reset"
}
@ -208,4 +210,5 @@ oder, wenn diese leer ist, die Person. Sind beide leer wird ein `-`
dargestellt.
"""
, pdfMode = Messages.Data.PdfMode.de
, resetLabel = "Zurücksetzen"
}

View File

@ -30,6 +30,7 @@ type alias Texts =
, userHeader : String
, userInfo : String
, collectiveHeader : String
, collectiveInfo : String
, expandCollapse : String
}
@ -45,8 +46,9 @@ gb =
, unknownSaveError = "Unknown error while trying to save settings."
, httpError = Messages.Comp.HttpError.gb
, userHeader = "Personal settings"
, userInfo = "Your personal settings override those of the collective. On reset, settings are set back to those of the collective."
, userInfo = "Your personal settings override those of the collective. On reset, settings are taken from the collective settings."
, collectiveHeader = "Collective settings"
, collectiveInfo = "These settings apply to all users, unless overriden by personal ones. A reset loads the provided default values of the application."
, expandCollapse = "Expand/collapse all"
}
@ -62,7 +64,8 @@ de =
, unknownSaveError = "Unbekannter Fehler beim Speichern der Einstellungen."
, httpError = Messages.Comp.HttpError.de
, userHeader = "Persönliche Einstellungen"
, userInfo = "Die persönlichen Einstellungen überschreiben die des Kollektivs. Wenn Einstellungen zurückgesetzt werden, werden sie auf die Werte des Kollektivs gesetzt."
, userInfo = "Die persönlichen Einstellungen überschreiben die des Kollektivs. Wenn Einstellungen zurückgesetzt werden, gelten automatisch die Werte des Kollektivs."
, collectiveHeader = "Kollektiv Einstellungen"
, collectiveInfo = "Diese Einstellungen sind für alle Benutzer, können aber in den persönlichen Einstellungen überschrieben werden. Durch ein Zurücksetzen erhält man die bereitgestellten Standardwerte der Anwendung."
, expandCollapse = "Alle ein-/ausklappen"
}