mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-02 13:32:51 +00:00
Improve mail template
This commit is contained in:
parent
ffc1cdee51
commit
d52efdfcf0
@ -4,6 +4,7 @@ import java.time.{Instant, LocalDate, ZoneId}
|
||||
|
||||
import cats.effect.Sync
|
||||
import io.circe.{Decoder, Encoder}
|
||||
import java.time.temporal.ChronoUnit
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
@ -59,6 +60,9 @@ object Timestamp {
|
||||
def atUtc(ldt: LocalDateTime): Timestamp =
|
||||
from(ldt.atZone(UTC))
|
||||
|
||||
def daysBetween(ts0: Timestamp, ts1: Timestamp): Long =
|
||||
ChronoUnit.DAYS.between(ts0.toUtcDate, ts1.toUtcDate)
|
||||
|
||||
implicit val encodeTimestamp: Encoder[Timestamp] =
|
||||
BaseJsonCodecs.encodeInstantEpoch.contramap(_.value)
|
||||
|
||||
|
@ -11,6 +11,7 @@ case class MailContext(
|
||||
items: List[MailContext.ItemData],
|
||||
more: Boolean,
|
||||
account: AccountId,
|
||||
username: String,
|
||||
itemUri: Option[LenientUri]
|
||||
)
|
||||
|
||||
@ -20,12 +21,14 @@ object MailContext {
|
||||
items: Vector[QItem.ListItem],
|
||||
max: Int,
|
||||
account: AccountId,
|
||||
itemBaseUri: Option[LenientUri]
|
||||
itemBaseUri: Option[LenientUri],
|
||||
now: Timestamp
|
||||
): MailContext =
|
||||
MailContext(
|
||||
items.take(max - 1).map(ItemData.apply).toList.sortBy(_.dueDate),
|
||||
items.take(max - 1).map(ItemData(now)).toList.sortBy(_.dueDate),
|
||||
items.sizeCompare(max) >= 0,
|
||||
account,
|
||||
account.user.id.capitalize,
|
||||
itemBaseUri
|
||||
)
|
||||
|
||||
@ -34,13 +37,22 @@ object MailContext {
|
||||
name: String,
|
||||
date: Timestamp,
|
||||
dueDate: Option[Timestamp],
|
||||
source: String
|
||||
source: String,
|
||||
overDue: Boolean,
|
||||
dueIn: Option[String]
|
||||
)
|
||||
|
||||
object ItemData {
|
||||
|
||||
def apply(i: QItem.ListItem): ItemData =
|
||||
ItemData(i.id, i.name, i.date, i.dueDate, i.source)
|
||||
def apply(now: Timestamp)(i: QItem.ListItem): ItemData = {
|
||||
val dueIn = i.dueDate.map(dt => Timestamp.daysBetween(now, dt))
|
||||
val dueInLabel = dueIn.map {
|
||||
case 0 => "**today**"
|
||||
case 1 => "**tomorrow**"
|
||||
case n => s"in $n days"
|
||||
}
|
||||
ItemData(i.id, i.name, i.date, i.dueDate, i.source, dueIn.exists(_ < 0), dueInLabel)
|
||||
}
|
||||
|
||||
implicit def yamusca: ValueConverter[ItemData] =
|
||||
ValueConverter.deriveConverter[ItemData]
|
||||
|
@ -5,24 +5,26 @@ import yamusca.implicits._
|
||||
object MailTemplate {
|
||||
|
||||
val text = mustache"""
|
||||
## Hello {{{ account.user }}},
|
||||
## Hello {{{ username }}},
|
||||
|
||||
this is Docspell informing you about due items coming up.
|
||||
this is Docspell informing you about your next due items coming up.
|
||||
|
||||
{{#itemUri}}
|
||||
{{#items}}
|
||||
- [{{name}}]({{itemUri}}/{{id}}), due on *{{dueDate}}*
|
||||
- {{#overDue}}**(OVERDUE)** {{/overDue}}[{{name}}]({{itemUri}}/{{id}}),
|
||||
due {{dueIn}} on *{{dueDate}}*
|
||||
(received on {{date}} via {{source}})
|
||||
{{/items}}
|
||||
{{/itemUri}}
|
||||
{{^itemUri}}
|
||||
{{#items}}
|
||||
- *{{name}}*, due on *{{dueDate}}*
|
||||
- {{#overDue}}**(OVERDUE)** {{/overDue}}*{{name}}*,
|
||||
due {{dueIn}} on *{{dueDate}}*
|
||||
(received on {{date}} via {{source}})
|
||||
{{/items}}
|
||||
{{/itemUri}}
|
||||
{{#more}}
|
||||
- (There are more due items, left out for brevity)
|
||||
- … more have been left out for brevity
|
||||
{{/more}}
|
||||
|
||||
|
||||
|
@ -16,7 +16,7 @@ import docspell.joex.notify.MailContext
|
||||
import docspell.joex.notify.MailTemplate
|
||||
|
||||
object NotifyDueItemsTask {
|
||||
val maxItems: Long = 5
|
||||
val maxItems: Long = 7
|
||||
type Args = NotifyDueItemsArgs
|
||||
|
||||
def apply[F[_]: Sync](emil: Emil[F]): Task[F, Args, Unit] =
|
||||
@ -83,21 +83,23 @@ object NotifyDueItemsTask {
|
||||
cfg: RUserEmail,
|
||||
args: Args,
|
||||
items: Vector[QItem.ListItem]
|
||||
): F[Mail[F]] = Sync[F].delay {
|
||||
val templateCtx =
|
||||
MailContext.from(items, maxItems.toInt, args.account, args.itemDetailUrl)
|
||||
val md = MailTemplate.render(templateCtx)
|
||||
val recp = args.recipients
|
||||
.map(MailAddress.parse)
|
||||
.map {
|
||||
case Right(ma) => ma
|
||||
case Left(err) => throw new Exception(s"Unable to parse recipient address: $err")
|
||||
}
|
||||
MailBuilder.build(
|
||||
From(cfg.mailFrom),
|
||||
Tos(recp),
|
||||
Subject("Next due items"),
|
||||
MarkdownBody[F](md)
|
||||
)
|
||||
}
|
||||
): F[Mail[F]] =
|
||||
Timestamp.current[F].map { now =>
|
||||
val templateCtx =
|
||||
MailContext.from(items, maxItems.toInt, args.account, args.itemDetailUrl, now)
|
||||
val md = MailTemplate.render(templateCtx)
|
||||
val recp = args.recipients
|
||||
.map(MailAddress.parse)
|
||||
.map {
|
||||
case Right(ma) => ma
|
||||
case Left(err) =>
|
||||
throw new Exception(s"Unable to parse recipient address: $err")
|
||||
}
|
||||
MailBuilder.build(
|
||||
From(cfg.mailFrom),
|
||||
Tos(recp),
|
||||
Subject("Next due items"),
|
||||
MarkdownBody[F](md)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user