mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-04-05 02:49:32 +00:00
Change "empty trash" settings for a collective and submit the job
This commit is contained in:
parent
828e5cf703
commit
4901276c66
@ -62,6 +62,8 @@ trait OCollective[F[_]] {
|
|||||||
|
|
||||||
def startLearnClassifier(collective: Ident): F[Unit]
|
def startLearnClassifier(collective: Ident): F[Unit]
|
||||||
|
|
||||||
|
def startEmptyTrash(collective: Ident): F[Unit]
|
||||||
|
|
||||||
/** Submits a task that (re)generates the preview images for all
|
/** Submits a task that (re)generates the preview images for all
|
||||||
* attachments of the given collective.
|
* attachments of the given collective.
|
||||||
*/
|
*/
|
||||||
@ -147,9 +149,14 @@ object OCollective {
|
|||||||
.transact(RCollective.updateSettings(collective, sett))
|
.transact(RCollective.updateSettings(collective, sett))
|
||||||
.attempt
|
.attempt
|
||||||
.map(AddResult.fromUpdate)
|
.map(AddResult.fromUpdate)
|
||||||
.flatMap(res => updateLearnClassifierTask(collective, sett) *> res.pure[F])
|
.flatMap(res =>
|
||||||
|
updateLearnClassifierTask(collective, sett) *> updateEmptyTrashTask(
|
||||||
|
collective,
|
||||||
|
sett
|
||||||
|
) *> res.pure[F]
|
||||||
|
)
|
||||||
|
|
||||||
def updateLearnClassifierTask(coll: Ident, sett: Settings) =
|
private def updateLearnClassifierTask(coll: Ident, sett: Settings): F[Unit] =
|
||||||
for {
|
for {
|
||||||
id <- Ident.randomId[F]
|
id <- Ident.randomId[F]
|
||||||
on = sett.classifier.map(_.enabled).getOrElse(false)
|
on = sett.classifier.map(_.enabled).getOrElse(false)
|
||||||
@ -166,6 +173,22 @@ object OCollective {
|
|||||||
_ <- joex.notifyAllNodes
|
_ <- joex.notifyAllNodes
|
||||||
} yield ()
|
} yield ()
|
||||||
|
|
||||||
|
private def updateEmptyTrashTask(coll: Ident, sett: Settings): F[Unit] =
|
||||||
|
for {
|
||||||
|
id <- Ident.randomId[F]
|
||||||
|
timer = sett.emptyTrash.getOrElse(CalEvent.unsafe(""))
|
||||||
|
ut = UserTask(
|
||||||
|
id,
|
||||||
|
EmptyTrashArgs.taskName,
|
||||||
|
true,
|
||||||
|
timer,
|
||||||
|
None,
|
||||||
|
EmptyTrashArgs(coll)
|
||||||
|
)
|
||||||
|
_ <- uts.updateOneTask(AccountId(coll, EmptyTrashArgs.taskName), ut)
|
||||||
|
_ <- joex.notifyAllNodes
|
||||||
|
} yield ()
|
||||||
|
|
||||||
def startLearnClassifier(collective: Ident): F[Unit] =
|
def startLearnClassifier(collective: Ident): F[Unit] =
|
||||||
for {
|
for {
|
||||||
id <- Ident.randomId[F]
|
id <- Ident.randomId[F]
|
||||||
@ -182,6 +205,22 @@ object OCollective {
|
|||||||
_ <- joex.notifyAllNodes
|
_ <- joex.notifyAllNodes
|
||||||
} yield ()
|
} yield ()
|
||||||
|
|
||||||
|
def startEmptyTrash(collective: Ident): F[Unit] =
|
||||||
|
for {
|
||||||
|
id <- Ident.randomId[F]
|
||||||
|
ut <- UserTask(
|
||||||
|
id,
|
||||||
|
EmptyTrashArgs.taskName,
|
||||||
|
true,
|
||||||
|
CalEvent(WeekdayComponent.All, DateEvent.All, TimeEvent.All),
|
||||||
|
None,
|
||||||
|
EmptyTrashArgs(collective)
|
||||||
|
).encode.toPeriodicTask(AccountId(collective, EmptyTrashArgs.taskName))
|
||||||
|
job <- ut.toJob
|
||||||
|
_ <- queue.insert(job)
|
||||||
|
_ <- joex.notifyAllNodes
|
||||||
|
} yield ()
|
||||||
|
|
||||||
def findSettings(collective: Ident): F[Option[OCollective.Settings]] =
|
def findSettings(collective: Ident): F[Option[OCollective.Settings]] =
|
||||||
store.transact(RCollective.getSettings(collective))
|
store.transact(RCollective.getSettings(collective))
|
||||||
|
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 Docspell Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package docspell.common
|
||||||
|
|
||||||
|
import docspell.common.syntax.all._
|
||||||
|
|
||||||
|
import io.circe._
|
||||||
|
import io.circe.generic.semiauto._
|
||||||
|
|
||||||
|
/** Arguments to the empty-trash task.
|
||||||
|
*
|
||||||
|
* This task is run periodically to really delete all soft-deleted
|
||||||
|
* items. These are items with state `ItemState.Deleted`.
|
||||||
|
*/
|
||||||
|
case class EmptyTrashArgs(
|
||||||
|
collective: Ident
|
||||||
|
) {
|
||||||
|
|
||||||
|
def makeSubject: String =
|
||||||
|
"Empty trash "
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object EmptyTrashArgs {
|
||||||
|
|
||||||
|
val taskName = Ident.unsafe("empty-trash")
|
||||||
|
|
||||||
|
implicit val jsonEncoder: Encoder[EmptyTrashArgs] =
|
||||||
|
deriveEncoder[EmptyTrashArgs]
|
||||||
|
implicit val jsonDecoder: Decoder[EmptyTrashArgs] =
|
||||||
|
deriveDecoder[EmptyTrashArgs]
|
||||||
|
|
||||||
|
def parse(str: String): Either[Throwable, EmptyTrashArgs] =
|
||||||
|
str.parseJsonAs[EmptyTrashArgs]
|
||||||
|
|
||||||
|
}
|
@ -1136,6 +1136,27 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/BasicResult"
|
$ref: "#/components/schemas/BasicResult"
|
||||||
|
|
||||||
|
/sec/collective/emptytrash/startonce:
|
||||||
|
post:
|
||||||
|
operationId: "sec-collective-emptytrash-start-now"
|
||||||
|
tags: [ Collective ]
|
||||||
|
summary: Starts the empty trash task
|
||||||
|
description: |
|
||||||
|
Submits a task to remove all items from the database that have
|
||||||
|
been "soft-deleted". This task is also run periodically and
|
||||||
|
can be triggered here to be immediatly submitted.
|
||||||
|
|
||||||
|
The request is empty, settings are used from the collective.
|
||||||
|
security:
|
||||||
|
- authTokenHeader: []
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Ok
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/BasicResult"
|
||||||
|
|
||||||
/sec/user:
|
/sec/user:
|
||||||
get:
|
get:
|
||||||
operationId: "sec-user-get-all"
|
operationId: "sec-user-get-all"
|
||||||
@ -5246,6 +5267,7 @@ components:
|
|||||||
- language
|
- language
|
||||||
- integrationEnabled
|
- integrationEnabled
|
||||||
- classifier
|
- classifier
|
||||||
|
- emptyTrashSchedule
|
||||||
properties:
|
properties:
|
||||||
language:
|
language:
|
||||||
type: string
|
type: string
|
||||||
@ -5255,6 +5277,9 @@ components:
|
|||||||
description: |
|
description: |
|
||||||
Whether the collective has the integration endpoint
|
Whether the collective has the integration endpoint
|
||||||
enabled.
|
enabled.
|
||||||
|
emptyTrashSchedule:
|
||||||
|
type: string
|
||||||
|
format: calevent
|
||||||
classifier:
|
classifier:
|
||||||
$ref: "#/components/schemas/ClassifierSetting"
|
$ref: "#/components/schemas/ClassifierSetting"
|
||||||
|
|
||||||
|
@ -55,7 +55,8 @@ object CollectiveRoutes {
|
|||||||
settings.classifier.categoryList,
|
settings.classifier.categoryList,
|
||||||
settings.classifier.listType
|
settings.classifier.listType
|
||||||
)
|
)
|
||||||
)
|
),
|
||||||
|
Some(settings.emptyTrashSchedule)
|
||||||
)
|
)
|
||||||
res <-
|
res <-
|
||||||
backend.collective
|
backend.collective
|
||||||
@ -70,6 +71,7 @@ object CollectiveRoutes {
|
|||||||
CollectiveSettings(
|
CollectiveSettings(
|
||||||
c.language,
|
c.language,
|
||||||
c.integrationEnabled,
|
c.integrationEnabled,
|
||||||
|
c.emptyTrash.getOrElse(CalEvent.unsafe("*-*-1/7 03:00:00")),
|
||||||
ClassifierSetting(
|
ClassifierSetting(
|
||||||
c.classifier.map(_.itemCount).getOrElse(0),
|
c.classifier.map(_.itemCount).getOrElse(0),
|
||||||
c.classifier
|
c.classifier
|
||||||
@ -101,6 +103,12 @@ object CollectiveRoutes {
|
|||||||
resp <- Ok(BasicResult(true, "Task submitted"))
|
resp <- Ok(BasicResult(true, "Task submitted"))
|
||||||
} yield resp
|
} yield resp
|
||||||
|
|
||||||
|
case POST -> Root / "emptytrash" / "startonce" =>
|
||||||
|
for {
|
||||||
|
_ <- backend.collective.startEmptyTrash(user.account.collective)
|
||||||
|
resp <- Ok(BasicResult(true, "Task submitted"))
|
||||||
|
} yield resp
|
||||||
|
|
||||||
case GET -> Root =>
|
case GET -> Root =>
|
||||||
for {
|
for {
|
||||||
collDb <- backend.collective.find(user.account.collective)
|
collDb <- backend.collective.find(user.account.collective)
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
CREATE TABLE "empty_trash_setting" (
|
||||||
|
"cid" varchar(254) not null primary key,
|
||||||
|
"schedule" varchar(254) not null,
|
||||||
|
"created" timestamp not null,
|
||||||
|
foreign key ("cid") references "collective"("cid")
|
||||||
|
);
|
@ -0,0 +1,6 @@
|
|||||||
|
CREATE TABLE `empty_trash_setting` (
|
||||||
|
`cid` varchar(254) not null primary key,
|
||||||
|
`schedule` varchar(254) not null,
|
||||||
|
`created` timestamp not null,
|
||||||
|
foreign key (`cid`) references `collective`(`cid`)
|
||||||
|
);
|
@ -0,0 +1,6 @@
|
|||||||
|
CREATE TABLE "empty_trash_setting" (
|
||||||
|
"cid" varchar(254) not null primary key,
|
||||||
|
"schedule" varchar(254) not null,
|
||||||
|
"created" timestamp not null,
|
||||||
|
foreign key ("cid") references "collective"("cid")
|
||||||
|
);
|
@ -13,6 +13,7 @@ import docspell.common._
|
|||||||
import docspell.store.qb.DSL._
|
import docspell.store.qb.DSL._
|
||||||
import docspell.store.qb._
|
import docspell.store.qb._
|
||||||
|
|
||||||
|
import com.github.eikek.calev._
|
||||||
import doobie._
|
import doobie._
|
||||||
import doobie.implicits._
|
import doobie.implicits._
|
||||||
|
|
||||||
@ -73,17 +74,21 @@ object RCollective {
|
|||||||
T.integration.setTo(settings.integrationEnabled)
|
T.integration.setTo(settings.integrationEnabled)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
cls <-
|
now <- Timestamp.current[ConnectionIO]
|
||||||
Timestamp
|
cls = settings.classifier.map(_.toRecord(cid, now))
|
||||||
.current[ConnectionIO]
|
|
||||||
.map(now => settings.classifier.map(_.toRecord(cid, now)))
|
|
||||||
n2 <- cls match {
|
n2 <- cls match {
|
||||||
case Some(cr) =>
|
case Some(cr) =>
|
||||||
RClassifierSetting.update(cr)
|
RClassifierSetting.update(cr)
|
||||||
case None =>
|
case None =>
|
||||||
RClassifierSetting.delete(cid)
|
RClassifierSetting.delete(cid)
|
||||||
}
|
}
|
||||||
} yield n1 + n2
|
n3 <- settings.emptyTrash match {
|
||||||
|
case Some(trashSchedule) =>
|
||||||
|
REmptyTrashSetting.update(REmptyTrashSetting(cid, trashSchedule, now))
|
||||||
|
case None =>
|
||||||
|
REmptyTrashSetting.delete(cid)
|
||||||
|
}
|
||||||
|
} yield n1 + n2 + n3
|
||||||
|
|
||||||
// this hides categories that have been deleted in the meantime
|
// this hides categories that have been deleted in the meantime
|
||||||
// they are finally removed from the json array once the learn classifier task is run
|
// they are finally removed from the json array once the learn classifier task is run
|
||||||
@ -99,6 +104,7 @@ object RCollective {
|
|||||||
import RClassifierSetting.stringListMeta
|
import RClassifierSetting.stringListMeta
|
||||||
val c = RCollective.as("c")
|
val c = RCollective.as("c")
|
||||||
val cs = RClassifierSetting.as("cs")
|
val cs = RClassifierSetting.as("cs")
|
||||||
|
val es = REmptyTrashSetting.as("es")
|
||||||
|
|
||||||
Select(
|
Select(
|
||||||
select(
|
select(
|
||||||
@ -107,9 +113,10 @@ object RCollective {
|
|||||||
cs.schedule.s,
|
cs.schedule.s,
|
||||||
cs.itemCount.s,
|
cs.itemCount.s,
|
||||||
cs.categories.s,
|
cs.categories.s,
|
||||||
cs.listType.s
|
cs.listType.s,
|
||||||
|
es.schedule.s
|
||||||
),
|
),
|
||||||
from(c).leftJoin(cs, cs.cid === c.id),
|
from(c).leftJoin(cs, cs.cid === c.id).leftJoin(es, es.cid === c.id),
|
||||||
c.id === coll
|
c.id === coll
|
||||||
).build.query[Settings].option
|
).build.query[Settings].option
|
||||||
}
|
}
|
||||||
@ -160,7 +167,8 @@ object RCollective {
|
|||||||
case class Settings(
|
case class Settings(
|
||||||
language: Language,
|
language: Language,
|
||||||
integrationEnabled: Boolean,
|
integrationEnabled: Boolean,
|
||||||
classifier: Option[RClassifierSetting.Classifier]
|
classifier: Option[RClassifierSetting.Classifier],
|
||||||
|
emptyTrash: Option[CalEvent]
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 Docspell Contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package docspell.store.records
|
||||||
|
|
||||||
|
import cats.data.NonEmptyList
|
||||||
|
import cats.implicits._
|
||||||
|
|
||||||
|
import docspell.common._
|
||||||
|
import docspell.store.qb.DSL._
|
||||||
|
import docspell.store.qb._
|
||||||
|
|
||||||
|
import com.github.eikek.calev._
|
||||||
|
import doobie._
|
||||||
|
import doobie.implicits._
|
||||||
|
|
||||||
|
final case class REmptyTrashSetting(
|
||||||
|
cid: Ident,
|
||||||
|
schedule: CalEvent,
|
||||||
|
created: Timestamp
|
||||||
|
)
|
||||||
|
|
||||||
|
object REmptyTrashSetting {
|
||||||
|
|
||||||
|
final case class Table(alias: Option[String]) extends TableDef {
|
||||||
|
val tableName = "empty_trash_setting"
|
||||||
|
|
||||||
|
val cid = Column[Ident]("cid", this)
|
||||||
|
val schedule = Column[CalEvent]("schedule", this)
|
||||||
|
val created = Column[Timestamp]("created", this)
|
||||||
|
val all = NonEmptyList.of[Column[_]](cid, schedule, created)
|
||||||
|
}
|
||||||
|
|
||||||
|
val T = Table(None)
|
||||||
|
def as(alias: String): Table =
|
||||||
|
Table(Some(alias))
|
||||||
|
|
||||||
|
def insert(v: REmptyTrashSetting): ConnectionIO[Int] =
|
||||||
|
DML.insert(
|
||||||
|
T,
|
||||||
|
T.all,
|
||||||
|
fr"${v.cid},${v.schedule},${v.created}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def update(v: REmptyTrashSetting): ConnectionIO[Int] =
|
||||||
|
for {
|
||||||
|
n1 <- DML.update(
|
||||||
|
T,
|
||||||
|
T.cid === v.cid,
|
||||||
|
DML.set(
|
||||||
|
T.schedule.setTo(v.schedule)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
n2 <- if (n1 <= 0) insert(v) else 0.pure[ConnectionIO]
|
||||||
|
} yield n1 + n2
|
||||||
|
|
||||||
|
def findById(id: Ident): ConnectionIO[Option[REmptyTrashSetting]] = {
|
||||||
|
val sql = run(select(T.all), from(T), T.cid === id)
|
||||||
|
sql.query[REmptyTrashSetting].option
|
||||||
|
}
|
||||||
|
|
||||||
|
def delete(coll: Ident): ConnectionIO[Int] =
|
||||||
|
DML.delete(T, T.cid === coll)
|
||||||
|
|
||||||
|
}
|
@ -130,6 +130,7 @@ module Api exposing
|
|||||||
, setTagsMultiple
|
, setTagsMultiple
|
||||||
, setUnconfirmed
|
, setUnconfirmed
|
||||||
, startClassifier
|
, startClassifier
|
||||||
|
, startEmptyTrash
|
||||||
, startOnceNotifyDueItems
|
, startOnceNotifyDueItems
|
||||||
, startOnceScanMailbox
|
, startOnceScanMailbox
|
||||||
, startReIndex
|
, startReIndex
|
||||||
@ -996,6 +997,19 @@ startClassifier flags receive =
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
startEmptyTrash :
|
||||||
|
Flags
|
||||||
|
-> (Result Http.Error BasicResult -> msg)
|
||||||
|
-> Cmd msg
|
||||||
|
startEmptyTrash flags receive =
|
||||||
|
Http2.authPost
|
||||||
|
{ url = flags.config.baseUrl ++ "/api/v1/sec/collective/emptytrash/startonce"
|
||||||
|
, account = getAccount flags
|
||||||
|
, body = Http.emptyBody
|
||||||
|
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
getTagCloud : Flags -> (Result Http.Error TagCloud -> msg) -> Cmd msg
|
getTagCloud : Flags -> (Result Http.Error TagCloud -> msg) -> Cmd msg
|
||||||
getTagCloud flags receive =
|
getTagCloud flags receive =
|
||||||
Http2.authGet
|
Http2.authGet
|
||||||
|
@ -20,7 +20,9 @@ import Api.Model.CollectiveSettings exposing (CollectiveSettings)
|
|||||||
import Comp.Basic as B
|
import Comp.Basic as B
|
||||||
import Comp.ClassifierSettingsForm
|
import Comp.ClassifierSettingsForm
|
||||||
import Comp.Dropdown
|
import Comp.Dropdown
|
||||||
|
import Comp.EmptyTrashForm
|
||||||
import Comp.MenuBar as MB
|
import Comp.MenuBar as MB
|
||||||
|
import Data.CalEvent
|
||||||
import Data.DropdownStyle as DS
|
import Data.DropdownStyle as DS
|
||||||
import Data.Flags exposing (Flags)
|
import Data.Flags exposing (Flags)
|
||||||
import Data.Language exposing (Language)
|
import Data.Language exposing (Language)
|
||||||
@ -41,6 +43,8 @@ type alias Model =
|
|||||||
, fullTextReIndexResult : FulltextReindexResult
|
, fullTextReIndexResult : FulltextReindexResult
|
||||||
, classifierModel : Comp.ClassifierSettingsForm.Model
|
, classifierModel : Comp.ClassifierSettingsForm.Model
|
||||||
, startClassifierResult : ClassifierResult
|
, startClassifierResult : ClassifierResult
|
||||||
|
, emptyTrashModel : Comp.EmptyTrashForm.Model
|
||||||
|
, startEmptyTrashResult : EmptyTrashResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -50,6 +54,11 @@ type ClassifierResult
|
|||||||
| ClassifierResultSubmitError String
|
| ClassifierResultSubmitError String
|
||||||
| ClassifierResultOk
|
| ClassifierResultOk
|
||||||
|
|
||||||
|
type EmptyTrashResult
|
||||||
|
= EmptyTrashResultInitial
|
||||||
|
| EmptyTrashResultHttpError Http.Error
|
||||||
|
| EmptyTrashResultSubmitError String
|
||||||
|
| EmptyTrashResultOk
|
||||||
|
|
||||||
type FulltextReindexResult
|
type FulltextReindexResult
|
||||||
= FulltextReindexInitial
|
= FulltextReindexInitial
|
||||||
@ -68,6 +77,9 @@ init flags settings =
|
|||||||
|
|
||||||
( cm, cc ) =
|
( cm, cc ) =
|
||||||
Comp.ClassifierSettingsForm.init flags settings.classifier
|
Comp.ClassifierSettingsForm.init flags settings.classifier
|
||||||
|
|
||||||
|
( em, ec ) =
|
||||||
|
Comp.EmptyTrashForm.init flags settings.emptyTrashSchedule
|
||||||
in
|
in
|
||||||
( { langModel =
|
( { langModel =
|
||||||
Comp.Dropdown.makeSingleList
|
Comp.Dropdown.makeSingleList
|
||||||
@ -80,8 +92,10 @@ init flags settings =
|
|||||||
, fullTextReIndexResult = FulltextReindexInitial
|
, fullTextReIndexResult = FulltextReindexInitial
|
||||||
, classifierModel = cm
|
, classifierModel = cm
|
||||||
, startClassifierResult = ClassifierResultInitial
|
, startClassifierResult = ClassifierResultInitial
|
||||||
|
, emptyTrashModel = em
|
||||||
|
, startEmptyTrashResult = EmptyTrashResultInitial
|
||||||
}
|
}
|
||||||
, Cmd.map ClassifierSettingMsg cc
|
, Cmd.batch [ Cmd.map ClassifierSettingMsg cc, Cmd.map EmptyTrashMsg ec ]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -96,6 +110,10 @@ getSettings model =
|
|||||||
|> Maybe.withDefault model.initSettings.language
|
|> Maybe.withDefault model.initSettings.language
|
||||||
, integrationEnabled = model.intEnabled
|
, integrationEnabled = model.intEnabled
|
||||||
, classifier = cls
|
, classifier = cls
|
||||||
|
, emptyTrashSchedule =
|
||||||
|
Comp.EmptyTrashForm.getSettings model.emptyTrashModel
|
||||||
|
|> Maybe.withDefault Data.CalEvent.everyMonth
|
||||||
|
|> Data.CalEvent.makeEvent
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
(Comp.ClassifierSettingsForm.getSettings
|
(Comp.ClassifierSettingsForm.getSettings
|
||||||
@ -110,9 +128,12 @@ type Msg
|
|||||||
| TriggerReIndex
|
| TriggerReIndex
|
||||||
| TriggerReIndexResult (Result Http.Error BasicResult)
|
| TriggerReIndexResult (Result Http.Error BasicResult)
|
||||||
| ClassifierSettingMsg Comp.ClassifierSettingsForm.Msg
|
| ClassifierSettingMsg Comp.ClassifierSettingsForm.Msg
|
||||||
|
| EmptyTrashMsg Comp.EmptyTrashForm.Msg
|
||||||
| SaveSettings
|
| SaveSettings
|
||||||
| StartClassifierTask
|
| StartClassifierTask
|
||||||
|
| StartEmptyTrashTask
|
||||||
| StartClassifierResp (Result Http.Error BasicResult)
|
| StartClassifierResp (Result Http.Error BasicResult)
|
||||||
|
| StartEmptyTrashResp (Result Http.Error BasicResult)
|
||||||
|
|
||||||
|
|
||||||
update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Maybe CollectiveSettings )
|
update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Maybe CollectiveSettings )
|
||||||
@ -188,6 +209,18 @@ update flags msg model =
|
|||||||
, Nothing
|
, Nothing
|
||||||
)
|
)
|
||||||
|
|
||||||
|
EmptyTrashMsg lmsg ->
|
||||||
|
let
|
||||||
|
( cm, cc ) =
|
||||||
|
Comp.EmptyTrashForm.update flags lmsg model.emptyTrashModel
|
||||||
|
in
|
||||||
|
( { model
|
||||||
|
| emptyTrashModel = cm
|
||||||
|
}
|
||||||
|
, Cmd.map EmptyTrashMsg cc
|
||||||
|
, Nothing
|
||||||
|
)
|
||||||
|
|
||||||
SaveSettings ->
|
SaveSettings ->
|
||||||
case getSettings model of
|
case getSettings model of
|
||||||
Just s ->
|
Just s ->
|
||||||
@ -199,6 +232,10 @@ update flags msg model =
|
|||||||
StartClassifierTask ->
|
StartClassifierTask ->
|
||||||
( model, Api.startClassifier flags StartClassifierResp, Nothing )
|
( model, Api.startClassifier flags StartClassifierResp, Nothing )
|
||||||
|
|
||||||
|
StartEmptyTrashTask ->
|
||||||
|
( model, Api.startEmptyTrash flags StartEmptyTrashResp, Nothing )
|
||||||
|
|
||||||
|
|
||||||
StartClassifierResp (Ok br) ->
|
StartClassifierResp (Ok br) ->
|
||||||
( { model
|
( { model
|
||||||
| startClassifierResult =
|
| startClassifierResult =
|
||||||
@ -218,6 +255,24 @@ update flags msg model =
|
|||||||
, Nothing
|
, Nothing
|
||||||
)
|
)
|
||||||
|
|
||||||
|
StartEmptyTrashResp (Ok br) ->
|
||||||
|
( { model
|
||||||
|
| startEmptyTrashResult =
|
||||||
|
if br.success then
|
||||||
|
EmptyTrashResultOk
|
||||||
|
|
||||||
|
else
|
||||||
|
EmptyTrashResultSubmitError br.message
|
||||||
|
}
|
||||||
|
, Cmd.none
|
||||||
|
, Nothing
|
||||||
|
)
|
||||||
|
|
||||||
|
StartEmptyTrashResp (Err err) ->
|
||||||
|
( { model | startEmptyTrashResult = EmptyTrashResultHttpError err }
|
||||||
|
, Cmd.none
|
||||||
|
, Nothing
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
--- View2
|
--- View2
|
||||||
@ -257,7 +312,7 @@ view2 flags texts settings model =
|
|||||||
, end = []
|
, end = []
|
||||||
, rootClasses = "mb-4"
|
, rootClasses = "mb-4"
|
||||||
}
|
}
|
||||||
, h3 [ class S.header3 ]
|
, h2 [ class S.header2 ]
|
||||||
[ text texts.documentLanguage
|
[ text texts.documentLanguage
|
||||||
]
|
]
|
||||||
, div [ class "mb-4" ]
|
, div [ class "mb-4" ]
|
||||||
@ -279,8 +334,8 @@ view2 flags texts settings model =
|
|||||||
[ ( "hidden", not flags.config.integrationEnabled )
|
[ ( "hidden", not flags.config.integrationEnabled )
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
[ h3
|
[ h2
|
||||||
[ class S.header3
|
[ class S.header2
|
||||||
]
|
]
|
||||||
[ text texts.integrationEndpoint
|
[ text texts.integrationEndpoint
|
||||||
]
|
]
|
||||||
@ -311,8 +366,8 @@ view2 flags texts settings model =
|
|||||||
[ ( "hidden", not flags.config.fullTextSearchEnabled )
|
[ ( "hidden", not flags.config.fullTextSearchEnabled )
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
[ h3
|
[ h2
|
||||||
[ class S.header3 ]
|
[ class S.header2 ]
|
||||||
[ text texts.fulltextSearch ]
|
[ text texts.fulltextSearch ]
|
||||||
, div
|
, div
|
||||||
[ class "mb-4" ]
|
[ class "mb-4" ]
|
||||||
@ -348,8 +403,8 @@ view2 flags texts settings model =
|
|||||||
[ ( " hidden", not flags.config.showClassificationSettings )
|
[ ( " hidden", not flags.config.showClassificationSettings )
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
[ h3
|
[ h2
|
||||||
[ class S.header3 ]
|
[ class S.header2 ]
|
||||||
[ text texts.autoTagging
|
[ text texts.autoTagging
|
||||||
]
|
]
|
||||||
, div
|
, div
|
||||||
@ -371,6 +426,28 @@ view2 flags texts settings model =
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
, div []
|
||||||
|
[ h2 [ class S.header2 ]
|
||||||
|
[ text texts.emptyTrash
|
||||||
|
]
|
||||||
|
, div [ class "mb-4" ]
|
||||||
|
[ Html.map EmptyTrashMsg
|
||||||
|
(Comp.EmptyTrashForm.view texts.emptyTrashForm
|
||||||
|
settings
|
||||||
|
model.emptyTrashModel
|
||||||
|
)
|
||||||
|
, div [ class "flex flex-row justify-end" ]
|
||||||
|
[ B.secondaryBasicButton
|
||||||
|
{ handler = onClick StartEmptyTrashTask
|
||||||
|
, icon = "fa fa-play"
|
||||||
|
, label = texts.startNow
|
||||||
|
, disabled = model.emptyTrashModel.schedule == Nothing
|
||||||
|
, attrs = [ href "#" ]
|
||||||
|
}
|
||||||
|
, renderEmptyTrashResultMessage texts model.startEmptyTrashResult
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -427,3 +504,38 @@ renderFulltextReindexResultMessage texts result =
|
|||||||
|
|
||||||
FulltextReindexSubmitError m ->
|
FulltextReindexSubmitError m ->
|
||||||
text m
|
text m
|
||||||
|
|
||||||
|
renderEmptyTrashResultMessage : Texts -> EmptyTrashResult -> Html msg
|
||||||
|
renderEmptyTrashResultMessage texts result =
|
||||||
|
let
|
||||||
|
isSuccess =
|
||||||
|
case result of
|
||||||
|
EmptyTrashResultOk ->
|
||||||
|
True
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
False
|
||||||
|
|
||||||
|
isError =
|
||||||
|
not isSuccess
|
||||||
|
in
|
||||||
|
div
|
||||||
|
[ classList
|
||||||
|
[ ( S.errorMessage, isError )
|
||||||
|
, ( S.successMessage, isSuccess )
|
||||||
|
, ( "hidden", result == EmptyTrashResultInitial )
|
||||||
|
]
|
||||||
|
]
|
||||||
|
[ case result of
|
||||||
|
EmptyTrashResultInitial ->
|
||||||
|
text ""
|
||||||
|
|
||||||
|
EmptyTrashResultOk ->
|
||||||
|
text texts.emptyTrashTaskStarted
|
||||||
|
|
||||||
|
EmptyTrashResultHttpError err ->
|
||||||
|
text (texts.httpError err)
|
||||||
|
|
||||||
|
EmptyTrashResultSubmitError m ->
|
||||||
|
text m
|
||||||
|
]
|
||||||
|
106
modules/webapp/src/main/elm/Comp/EmptyTrashForm.elm
Normal file
106
modules/webapp/src/main/elm/Comp/EmptyTrashForm.elm
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Docspell Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Comp.EmptyTrashForm exposing
|
||||||
|
( Model
|
||||||
|
, Msg
|
||||||
|
, getSettings
|
||||||
|
, init
|
||||||
|
, update
|
||||||
|
, view
|
||||||
|
)
|
||||||
|
|
||||||
|
import Api
|
||||||
|
import Comp.CalEventInput
|
||||||
|
import Comp.Dropdown
|
||||||
|
import Comp.FixedDropdown
|
||||||
|
import Comp.IntField
|
||||||
|
import Data.CalEvent exposing (CalEvent)
|
||||||
|
import Data.DropdownStyle as DS
|
||||||
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.ListType exposing (ListType)
|
||||||
|
import Data.UiSettings exposing (UiSettings)
|
||||||
|
import Html exposing (..)
|
||||||
|
import Html.Attributes exposing (..)
|
||||||
|
import Http
|
||||||
|
import Markdown
|
||||||
|
import Messages.Comp.EmptyTrashForm exposing (Texts)
|
||||||
|
import Styles as S
|
||||||
|
import Util.Tag
|
||||||
|
|
||||||
|
|
||||||
|
type alias Model =
|
||||||
|
{ scheduleModel : Comp.CalEventInput.Model
|
||||||
|
, schedule : Maybe CalEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= ScheduleMsg Comp.CalEventInput.Msg
|
||||||
|
|
||||||
|
|
||||||
|
init : Flags -> String -> ( Model, Cmd Msg )
|
||||||
|
init flags schedule =
|
||||||
|
let
|
||||||
|
newSchedule =
|
||||||
|
Data.CalEvent.fromEvent schedule
|
||||||
|
|> Maybe.withDefault Data.CalEvent.everyMonth
|
||||||
|
|
||||||
|
( cem, cec ) =
|
||||||
|
Comp.CalEventInput.init flags newSchedule
|
||||||
|
in
|
||||||
|
( { scheduleModel = cem
|
||||||
|
, schedule = Just newSchedule
|
||||||
|
}
|
||||||
|
, Cmd.map ScheduleMsg cec
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
getSettings : Model -> Maybe CalEvent
|
||||||
|
getSettings model =
|
||||||
|
model.schedule
|
||||||
|
|
||||||
|
|
||||||
|
update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
|
||||||
|
update flags msg model =
|
||||||
|
case msg of
|
||||||
|
ScheduleMsg lmsg ->
|
||||||
|
let
|
||||||
|
( cm, cc, ce ) =
|
||||||
|
Comp.CalEventInput.update
|
||||||
|
flags
|
||||||
|
model.schedule
|
||||||
|
lmsg
|
||||||
|
model.scheduleModel
|
||||||
|
in
|
||||||
|
( { model
|
||||||
|
| scheduleModel = cm
|
||||||
|
, schedule = ce
|
||||||
|
}
|
||||||
|
, Cmd.map ScheduleMsg cc
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- View2
|
||||||
|
|
||||||
|
|
||||||
|
view : Texts -> UiSettings -> Model -> Html Msg
|
||||||
|
view texts _ model =
|
||||||
|
div []
|
||||||
|
[ div [ class "mb-4" ]
|
||||||
|
[ label [ class S.inputLabel ]
|
||||||
|
[ text texts.schedule ]
|
||||||
|
, Html.map ScheduleMsg
|
||||||
|
(Comp.CalEventInput.view2
|
||||||
|
texts.calEventInput
|
||||||
|
""
|
||||||
|
model.schedule
|
||||||
|
model.scheduleModel
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
@ -15,6 +15,7 @@ import Data.Language exposing (Language)
|
|||||||
import Http
|
import Http
|
||||||
import Messages.Basics
|
import Messages.Basics
|
||||||
import Messages.Comp.ClassifierSettingsForm
|
import Messages.Comp.ClassifierSettingsForm
|
||||||
|
import Messages.Comp.EmptyTrashForm
|
||||||
import Messages.Comp.HttpError
|
import Messages.Comp.HttpError
|
||||||
import Messages.Data.Language
|
import Messages.Data.Language
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ import Messages.Data.Language
|
|||||||
type alias Texts =
|
type alias Texts =
|
||||||
{ basics : Messages.Basics.Texts
|
{ basics : Messages.Basics.Texts
|
||||||
, classifierSettingsForm : Messages.Comp.ClassifierSettingsForm.Texts
|
, classifierSettingsForm : Messages.Comp.ClassifierSettingsForm.Texts
|
||||||
|
, emptyTrashForm : Messages.Comp.EmptyTrashForm.Texts
|
||||||
, httpError : Http.Error -> String
|
, httpError : Http.Error -> String
|
||||||
, save : String
|
, save : String
|
||||||
, saveSettings : String
|
, saveSettings : String
|
||||||
@ -37,8 +39,10 @@ type alias Texts =
|
|||||||
, startNow : String
|
, startNow : String
|
||||||
, languageLabel : Language -> String
|
, languageLabel : Language -> String
|
||||||
, classifierTaskStarted : String
|
, classifierTaskStarted : String
|
||||||
|
, emptyTrashTaskStarted : String
|
||||||
, fulltextReindexSubmitted : String
|
, fulltextReindexSubmitted : String
|
||||||
, fulltextReindexOkMissing : String
|
, fulltextReindexOkMissing : String
|
||||||
|
, emptyTrash : String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -46,6 +50,7 @@ gb : Texts
|
|||||||
gb =
|
gb =
|
||||||
{ basics = Messages.Basics.gb
|
{ basics = Messages.Basics.gb
|
||||||
, classifierSettingsForm = Messages.Comp.ClassifierSettingsForm.gb
|
, classifierSettingsForm = Messages.Comp.ClassifierSettingsForm.gb
|
||||||
|
, emptyTrashForm = Messages.Comp.EmptyTrashForm.gb
|
||||||
, httpError = Messages.Comp.HttpError.gb
|
, httpError = Messages.Comp.HttpError.gb
|
||||||
, save = "Save"
|
, save = "Save"
|
||||||
, saveSettings = "Save Settings"
|
, saveSettings = "Save Settings"
|
||||||
@ -65,9 +70,11 @@ gb =
|
|||||||
, startNow = "Start now"
|
, startNow = "Start now"
|
||||||
, languageLabel = Messages.Data.Language.gb
|
, languageLabel = Messages.Data.Language.gb
|
||||||
, classifierTaskStarted = "Classifier task started."
|
, classifierTaskStarted = "Classifier task started."
|
||||||
|
, emptyTrashTaskStarted = "Empty trash task started."
|
||||||
, fulltextReindexSubmitted = "Fulltext Re-Index started."
|
, fulltextReindexSubmitted = "Fulltext Re-Index started."
|
||||||
, fulltextReindexOkMissing =
|
, fulltextReindexOkMissing =
|
||||||
"Please type OK in the field if you really want to start re-indexing your data."
|
"Please type OK in the field if you really want to start re-indexing your data."
|
||||||
|
, emptyTrash = "Empty Trash"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -75,6 +82,7 @@ de : Texts
|
|||||||
de =
|
de =
|
||||||
{ basics = Messages.Basics.de
|
{ basics = Messages.Basics.de
|
||||||
, classifierSettingsForm = Messages.Comp.ClassifierSettingsForm.de
|
, classifierSettingsForm = Messages.Comp.ClassifierSettingsForm.de
|
||||||
|
, emptyTrashForm = Messages.Comp.EmptyTrashForm.de
|
||||||
, httpError = Messages.Comp.HttpError.de
|
, httpError = Messages.Comp.HttpError.de
|
||||||
, save = "Speichern"
|
, save = "Speichern"
|
||||||
, saveSettings = "Einstellungen speichern"
|
, saveSettings = "Einstellungen speichern"
|
||||||
@ -94,7 +102,9 @@ de =
|
|||||||
, startNow = "Jetzt starten"
|
, startNow = "Jetzt starten"
|
||||||
, languageLabel = Messages.Data.Language.de
|
, languageLabel = Messages.Data.Language.de
|
||||||
, classifierTaskStarted = "Kategorisierung gestartet."
|
, classifierTaskStarted = "Kategorisierung gestartet."
|
||||||
|
, emptyTrashTaskStarted = "Papierkorb löschen gestartet."
|
||||||
, fulltextReindexSubmitted = "Volltext Neu-Indexierung gestartet."
|
, fulltextReindexSubmitted = "Volltext Neu-Indexierung gestartet."
|
||||||
, fulltextReindexOkMissing =
|
, fulltextReindexOkMissing =
|
||||||
"Bitte tippe OK in das Feld ein, wenn Du wirklich den Index neu erzeugen möchtest."
|
"Bitte tippe OK in das Feld ein, wenn Du wirklich den Index neu erzeugen möchtest."
|
||||||
|
, emptyTrash = "Papierkorb löschen"
|
||||||
}
|
}
|
||||||
|
38
modules/webapp/src/main/elm/Messages/Comp/EmptyTrashForm.elm
Normal file
38
modules/webapp/src/main/elm/Messages/Comp/EmptyTrashForm.elm
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{-
|
||||||
|
Copyright 2020 Docspell Contributors
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module Messages.Comp.EmptyTrashForm exposing
|
||||||
|
( Texts
|
||||||
|
, de
|
||||||
|
, gb
|
||||||
|
)
|
||||||
|
|
||||||
|
import Messages.Basics
|
||||||
|
import Messages.Comp.CalEventInput
|
||||||
|
|
||||||
|
|
||||||
|
type alias Texts =
|
||||||
|
{ basics : Messages.Basics.Texts
|
||||||
|
, calEventInput : Messages.Comp.CalEventInput.Texts
|
||||||
|
, schedule : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gb : Texts
|
||||||
|
gb =
|
||||||
|
{ basics = Messages.Basics.gb
|
||||||
|
, calEventInput = Messages.Comp.CalEventInput.gb
|
||||||
|
, schedule = "Schedule"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
de : Texts
|
||||||
|
de =
|
||||||
|
{ basics = Messages.Basics.de
|
||||||
|
, calEventInput = Messages.Comp.CalEventInput.de
|
||||||
|
, schedule = "Zeitplan"
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user