mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-06 15:15:58 +00:00
Allow person to be correspondent, concerning or both
This commit is contained in:
parent
567bfb3e69
commit
48eee00c0b
@ -198,6 +198,9 @@ val openapiScalaSettings = Seq(
|
|||||||
case "listtype" =>
|
case "listtype" =>
|
||||||
field =>
|
field =>
|
||||||
field.copy(typeDef = TypeDef("ListType", Imports("docspell.common.ListType")))
|
field.copy(typeDef = TypeDef("ListType", Imports("docspell.common.ListType")))
|
||||||
|
case "personuse" =>
|
||||||
|
field =>
|
||||||
|
field.copy(typeDef = TypeDef("PersonUse", Imports("docspell.common.PersonUse")))
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
package docspell.common
|
||||||
|
|
||||||
|
import cats.data.NonEmptyList
|
||||||
|
|
||||||
|
import io.circe.Decoder
|
||||||
|
import io.circe.Encoder
|
||||||
|
|
||||||
|
sealed trait PersonUse { self: Product =>
|
||||||
|
|
||||||
|
final def name: String =
|
||||||
|
self.productPrefix.toLowerCase()
|
||||||
|
}
|
||||||
|
|
||||||
|
object PersonUse {
|
||||||
|
|
||||||
|
case object Correspondent extends PersonUse
|
||||||
|
case object Concerning extends PersonUse
|
||||||
|
case object Both extends PersonUse
|
||||||
|
|
||||||
|
def concerning: PersonUse = Concerning
|
||||||
|
def correspondent: PersonUse = Correspondent
|
||||||
|
def both: PersonUse = Both
|
||||||
|
|
||||||
|
val concerningAndBoth: NonEmptyList[PersonUse] =
|
||||||
|
NonEmptyList.of(Concerning, Both)
|
||||||
|
|
||||||
|
val correspondentAndBoth: NonEmptyList[PersonUse] =
|
||||||
|
NonEmptyList.of(Correspondent, Both)
|
||||||
|
|
||||||
|
def fromString(str: String): Either[String, PersonUse] =
|
||||||
|
str.toLowerCase() match {
|
||||||
|
case "correspondent" =>
|
||||||
|
Right(Correspondent)
|
||||||
|
case "concerning" =>
|
||||||
|
Right(Concerning)
|
||||||
|
case "both" =>
|
||||||
|
Right(Both)
|
||||||
|
case _ =>
|
||||||
|
Left(s"Unknown person-use: $str")
|
||||||
|
}
|
||||||
|
|
||||||
|
def unsafeFromString(str: String): PersonUse =
|
||||||
|
fromString(str).fold(sys.error, identity)
|
||||||
|
|
||||||
|
implicit val jsonDecoder: Decoder[PersonUse] =
|
||||||
|
Decoder.decodeString.emap(fromString)
|
||||||
|
|
||||||
|
implicit val jsonEncoder: Encoder[PersonUse] =
|
||||||
|
Encoder.encodeString.contramap(_.name)
|
||||||
|
}
|
@ -57,7 +57,11 @@ object FindProposal {
|
|||||||
ctx.store
|
ctx.store
|
||||||
.transact(
|
.transact(
|
||||||
RPerson
|
RPerson
|
||||||
.findLike(coll, mp.values.head.ref.name.toLowerCase, false)
|
.findLike(
|
||||||
|
coll,
|
||||||
|
mp.values.head.ref.name.toLowerCase,
|
||||||
|
PersonUse.correspondentAndBoth
|
||||||
|
)
|
||||||
.map(_.headOption)
|
.map(_.headOption)
|
||||||
)
|
)
|
||||||
.flatTap(oref =>
|
.flatTap(oref =>
|
||||||
@ -67,7 +71,11 @@ object FindProposal {
|
|||||||
ctx.store
|
ctx.store
|
||||||
.transact(
|
.transact(
|
||||||
RPerson
|
RPerson
|
||||||
.findLike(coll, mp.values.head.ref.name.toLowerCase, true)
|
.findLike(
|
||||||
|
coll,
|
||||||
|
mp.values.head.ref.name.toLowerCase,
|
||||||
|
PersonUse.concerningAndBoth
|
||||||
|
)
|
||||||
.map(_.headOption)
|
.map(_.headOption)
|
||||||
)
|
)
|
||||||
.flatTap(oref =>
|
.flatTap(oref =>
|
||||||
@ -231,10 +239,16 @@ object FindProposal {
|
|||||||
|
|
||||||
case NerTag.Person =>
|
case NerTag.Person =>
|
||||||
val s1 = ctx.store
|
val s1 = ctx.store
|
||||||
.transact(RPerson.findLike(ctx.args.meta.collective, value, true))
|
.transact(
|
||||||
|
RPerson
|
||||||
|
.findLike(ctx.args.meta.collective, value, PersonUse.concerningAndBoth)
|
||||||
|
)
|
||||||
.map(MetaProposalList.from(MetaProposalType.ConcPerson, nt))
|
.map(MetaProposalList.from(MetaProposalType.ConcPerson, nt))
|
||||||
val s2 = ctx.store
|
val s2 = ctx.store
|
||||||
.transact(RPerson.findLike(ctx.args.meta.collective, value, false))
|
.transact(
|
||||||
|
RPerson
|
||||||
|
.findLike(ctx.args.meta.collective, value, PersonUse.correspondentAndBoth)
|
||||||
|
)
|
||||||
.map(MetaProposalList.from(MetaProposalType.CorrPerson, nt))
|
.map(MetaProposalList.from(MetaProposalType.CorrPerson, nt))
|
||||||
val s3 =
|
val s3 =
|
||||||
ctx.store
|
ctx.store
|
||||||
@ -288,10 +302,16 @@ object FindProposal {
|
|||||||
.transact(ROrganization.findLike(ctx.args.meta.collective, kind, value))
|
.transact(ROrganization.findLike(ctx.args.meta.collective, kind, value))
|
||||||
.map(MetaProposalList.from(MetaProposalType.CorrOrg, nt))
|
.map(MetaProposalList.from(MetaProposalType.CorrOrg, nt))
|
||||||
val corrP = ctx.store
|
val corrP = ctx.store
|
||||||
.transact(RPerson.findLike(ctx.args.meta.collective, kind, value, false))
|
.transact(
|
||||||
|
RPerson
|
||||||
|
.findLike(ctx.args.meta.collective, kind, value, PersonUse.correspondentAndBoth)
|
||||||
|
)
|
||||||
.map(MetaProposalList.from(MetaProposalType.CorrPerson, nt))
|
.map(MetaProposalList.from(MetaProposalType.CorrPerson, nt))
|
||||||
val concP = ctx.store
|
val concP = ctx.store
|
||||||
.transact(RPerson.findLike(ctx.args.meta.collective, kind, value, true))
|
.transact(
|
||||||
|
RPerson
|
||||||
|
.findLike(ctx.args.meta.collective, kind, value, PersonUse.concerningAndBoth)
|
||||||
|
)
|
||||||
.map(MetaProposalList.from(MetaProposalType.CorrPerson, nt))
|
.map(MetaProposalList.from(MetaProposalType.CorrPerson, nt))
|
||||||
|
|
||||||
ctx.logger.debug(s"Looking with $kind: $value") *>
|
ctx.logger.debug(s"Looking with $kind: $value") *>
|
||||||
|
@ -236,7 +236,7 @@ object ScanMailboxTask {
|
|||||||
ctx.args.account.collective,
|
ctx.args.account.collective,
|
||||||
from.address,
|
from.address,
|
||||||
Some(ContactKind.Email),
|
Some(ContactKind.Email),
|
||||||
Some(true)
|
Some(NonEmptyList.of(PersonUse.concerning))
|
||||||
)
|
)
|
||||||
.take(1)
|
.take(1)
|
||||||
.compile
|
.compile
|
||||||
|
@ -4999,7 +4999,7 @@ components:
|
|||||||
- address
|
- address
|
||||||
- contacts
|
- contacts
|
||||||
- created
|
- created
|
||||||
- concerning
|
- use
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
type: string
|
type: string
|
||||||
@ -5016,11 +5016,16 @@ components:
|
|||||||
$ref: "#/components/schemas/Contact"
|
$ref: "#/components/schemas/Contact"
|
||||||
notes:
|
notes:
|
||||||
type: string
|
type: string
|
||||||
concerning:
|
use:
|
||||||
type: boolean
|
type: string
|
||||||
|
format: personuse
|
||||||
|
enum:
|
||||||
|
- concerning
|
||||||
|
- correspondent
|
||||||
|
- both
|
||||||
description: |
|
description: |
|
||||||
Whether this person should be used to create suggestions
|
Whether this person should be used to create suggestions
|
||||||
for the "concerning person" association.
|
for the "concerning person", "correspondent" or both.
|
||||||
created:
|
created:
|
||||||
description: DateTime
|
description: DateTime
|
||||||
type: integer
|
type: integer
|
||||||
|
@ -445,7 +445,7 @@ trait Conversions {
|
|||||||
Address(rp.street, rp.zip, rp.city, rp.country),
|
Address(rp.street, rp.zip, rp.city, rp.country),
|
||||||
v.contacts.map(mkContact).toList,
|
v.contacts.map(mkContact).toList,
|
||||||
rp.notes,
|
rp.notes,
|
||||||
rp.concerning,
|
rp.use,
|
||||||
rp.created
|
rp.created
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -466,10 +466,10 @@ trait Conversions {
|
|||||||
v.address.city,
|
v.address.city,
|
||||||
v.address.country,
|
v.address.country,
|
||||||
v.notes,
|
v.notes,
|
||||||
v.concerning,
|
|
||||||
now,
|
now,
|
||||||
now,
|
now,
|
||||||
v.organization.map(_.id)
|
v.organization.map(_.id),
|
||||||
|
v.use
|
||||||
)
|
)
|
||||||
} yield OOrganization.PersonAndContacts(pers, None, cont)
|
} yield OOrganization.PersonAndContacts(pers, None, cont)
|
||||||
}
|
}
|
||||||
@ -492,10 +492,10 @@ trait Conversions {
|
|||||||
v.address.city,
|
v.address.city,
|
||||||
v.address.country,
|
v.address.country,
|
||||||
v.notes,
|
v.notes,
|
||||||
v.concerning,
|
|
||||||
v.created,
|
v.created,
|
||||||
now,
|
now,
|
||||||
v.organization.map(_.id)
|
v.organization.map(_.id),
|
||||||
|
v.use
|
||||||
)
|
)
|
||||||
} yield OOrganization.PersonAndContacts(pers, None, cont)
|
} yield OOrganization.PersonAndContacts(pers, None, cont)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
ALTER TABLE "person"
|
||||||
|
ADD COLUMN "person_use" varchar(254);
|
||||||
|
|
||||||
|
UPDATE "person" SET "person_use" = 'concerning' where "concerning" = true;
|
||||||
|
UPDATE "person" SET "person_use" = 'correspondent' where "concerning" = false;
|
||||||
|
UPDATE "person" SET "person_use" = 'both' where "concerning" is null;
|
||||||
|
|
||||||
|
ALTER TABLE "person"
|
||||||
|
DROP COLUMN "concerning";
|
@ -0,0 +1,9 @@
|
|||||||
|
ALTER TABLE `person`
|
||||||
|
ADD COLUMN `person_use` varchar(254);
|
||||||
|
|
||||||
|
UPDATE `person` SET `person_use` = 'concerning' where `concerning` = true;
|
||||||
|
UPDATE `person` SET `person_use` = 'correspondent' where `concerning` = false;
|
||||||
|
UPDATE `person` SET `person_use` = 'both' where `concerning` is null;
|
||||||
|
|
||||||
|
ALTER TABLE `person`
|
||||||
|
DROP COLUMN `concerning`;
|
@ -0,0 +1,9 @@
|
|||||||
|
ALTER TABLE "person"
|
||||||
|
ADD COLUMN "person_use" varchar(254);
|
||||||
|
|
||||||
|
UPDATE "person" SET "person_use" = 'concerning' where "concerning" = true;
|
||||||
|
UPDATE "person" SET "person_use" = 'correspondent' where "concerning" = false;
|
||||||
|
UPDATE "person" SET "person_use" = 'both' where "concerning" is null;
|
||||||
|
|
||||||
|
ALTER TABLE "person"
|
||||||
|
DROP COLUMN "concerning";
|
@ -103,6 +103,9 @@ trait DoobieMeta extends EmilDoobieMeta {
|
|||||||
|
|
||||||
implicit val metaListType: Meta[ListType] =
|
implicit val metaListType: Meta[ListType] =
|
||||||
Meta[String].timap(ListType.unsafeFromString)(_.name)
|
Meta[String].timap(ListType.unsafeFromString)(_.name)
|
||||||
|
|
||||||
|
implicit val metaPersonUse: Meta[PersonUse] =
|
||||||
|
Meta[String].timap(PersonUse.unsafeFromString)(_.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
object DoobieMeta extends DoobieMeta {
|
object DoobieMeta extends DoobieMeta {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package docspell.store.queries
|
package docspell.store.queries
|
||||||
|
|
||||||
|
import cats.data.NonEmptyList
|
||||||
import cats.implicits._
|
import cats.implicits._
|
||||||
import fs2._
|
import fs2._
|
||||||
|
|
||||||
@ -121,13 +122,13 @@ object QOrganization {
|
|||||||
coll: Ident,
|
coll: Ident,
|
||||||
value: String,
|
value: String,
|
||||||
ck: Option[ContactKind],
|
ck: Option[ContactKind],
|
||||||
concerning: Option[Boolean]
|
use: Option[NonEmptyList[PersonUse]]
|
||||||
): Stream[ConnectionIO, RPerson] =
|
): Stream[ConnectionIO, RPerson] =
|
||||||
runDistinct(
|
runDistinct(
|
||||||
select(p.all),
|
select(p.all),
|
||||||
from(p).innerJoin(c, c.personId === p.pid),
|
from(p).innerJoin(c, c.personId === p.pid),
|
||||||
c.value.like(s"%${value.toLowerCase}%") && p.cid === coll &&?
|
c.value.like(s"%${value.toLowerCase}%") && p.cid === coll &&?
|
||||||
concerning.map(c => p.concerning === c) &&?
|
use.map(u => p.use.in(u)) &&?
|
||||||
ck.map(k => c.kind === k)
|
ck.map(k => c.kind === k)
|
||||||
).query[RPerson].stream
|
).query[RPerson].stream
|
||||||
|
|
||||||
|
@ -21,10 +21,10 @@ case class RPerson(
|
|||||||
city: String,
|
city: String,
|
||||||
country: String,
|
country: String,
|
||||||
notes: Option[String],
|
notes: Option[String],
|
||||||
concerning: Boolean,
|
|
||||||
created: Timestamp,
|
created: Timestamp,
|
||||||
updated: Timestamp,
|
updated: Timestamp,
|
||||||
oid: Option[Ident]
|
oid: Option[Ident],
|
||||||
|
use: PersonUse
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
object RPerson {
|
object RPerson {
|
||||||
@ -34,18 +34,18 @@ object RPerson {
|
|||||||
final case class Table(alias: Option[String]) extends TableDef {
|
final case class Table(alias: Option[String]) extends TableDef {
|
||||||
val tableName = "person"
|
val tableName = "person"
|
||||||
|
|
||||||
val pid = Column[Ident]("pid", this)
|
val pid = Column[Ident]("pid", this)
|
||||||
val cid = Column[Ident]("cid", this)
|
val cid = Column[Ident]("cid", this)
|
||||||
val name = Column[String]("name", this)
|
val name = Column[String]("name", this)
|
||||||
val street = Column[String]("street", this)
|
val street = Column[String]("street", this)
|
||||||
val zip = Column[String]("zip", this)
|
val zip = Column[String]("zip", this)
|
||||||
val city = Column[String]("city", this)
|
val city = Column[String]("city", this)
|
||||||
val country = Column[String]("country", this)
|
val country = Column[String]("country", this)
|
||||||
val notes = Column[String]("notes", this)
|
val notes = Column[String]("notes", this)
|
||||||
val concerning = Column[Boolean]("concerning", this)
|
val created = Column[Timestamp]("created", this)
|
||||||
val created = Column[Timestamp]("created", this)
|
val updated = Column[Timestamp]("updated", this)
|
||||||
val updated = Column[Timestamp]("updated", this)
|
val oid = Column[Ident]("oid", this)
|
||||||
val oid = Column[Ident]("oid", this)
|
val use = Column[PersonUse]("person_use", this)
|
||||||
val all = NonEmptyList.of[Column[_]](
|
val all = NonEmptyList.of[Column[_]](
|
||||||
pid,
|
pid,
|
||||||
cid,
|
cid,
|
||||||
@ -55,10 +55,10 @@ object RPerson {
|
|||||||
city,
|
city,
|
||||||
country,
|
country,
|
||||||
notes,
|
notes,
|
||||||
concerning,
|
|
||||||
created,
|
created,
|
||||||
updated,
|
updated,
|
||||||
oid
|
oid,
|
||||||
|
use
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ object RPerson {
|
|||||||
DML.insert(
|
DML.insert(
|
||||||
T,
|
T,
|
||||||
T.all,
|
T.all,
|
||||||
fr"${v.pid},${v.cid},${v.name},${v.street},${v.zip},${v.city},${v.country},${v.notes},${v.concerning},${v.created},${v.updated},${v.oid}"
|
fr"${v.pid},${v.cid},${v.name},${v.street},${v.zip},${v.city},${v.country},${v.notes},${v.created},${v.updated},${v.oid},${v.use}"
|
||||||
)
|
)
|
||||||
|
|
||||||
def update(v: RPerson): ConnectionIO[Int] = {
|
def update(v: RPerson): ConnectionIO[Int] = {
|
||||||
@ -85,7 +85,7 @@ object RPerson {
|
|||||||
T.zip.setTo(v.zip),
|
T.zip.setTo(v.zip),
|
||||||
T.city.setTo(v.city),
|
T.city.setTo(v.city),
|
||||||
T.country.setTo(v.country),
|
T.country.setTo(v.country),
|
||||||
T.concerning.setTo(v.concerning),
|
T.use.setTo(v.use),
|
||||||
T.notes.setTo(v.notes),
|
T.notes.setTo(v.notes),
|
||||||
T.oid.setTo(v.oid),
|
T.oid.setTo(v.oid),
|
||||||
T.updated.setTo(now)
|
T.updated.setTo(now)
|
||||||
@ -116,19 +116,19 @@ object RPerson {
|
|||||||
def findLike(
|
def findLike(
|
||||||
coll: Ident,
|
coll: Ident,
|
||||||
personName: String,
|
personName: String,
|
||||||
concerningOnly: Boolean
|
use: NonEmptyList[PersonUse]
|
||||||
): ConnectionIO[Vector[IdRef]] =
|
): ConnectionIO[Vector[IdRef]] =
|
||||||
run(
|
run(
|
||||||
select(T.pid, T.name),
|
select(T.pid, T.name),
|
||||||
from(T),
|
from(T),
|
||||||
where(T.cid === coll, T.concerning === concerningOnly, T.name.like(personName))
|
where(T.cid === coll, T.use.in(use), T.name.like(personName))
|
||||||
).query[IdRef].to[Vector]
|
).query[IdRef].to[Vector]
|
||||||
|
|
||||||
def findLike(
|
def findLike(
|
||||||
coll: Ident,
|
coll: Ident,
|
||||||
contactKind: ContactKind,
|
contactKind: ContactKind,
|
||||||
value: String,
|
value: String,
|
||||||
concerningOnly: Boolean
|
use: NonEmptyList[PersonUse]
|
||||||
): ConnectionIO[Vector[IdRef]] = {
|
): ConnectionIO[Vector[IdRef]] = {
|
||||||
val p = RPerson.as("p")
|
val p = RPerson.as("p")
|
||||||
val c = RContact.as("c")
|
val c = RContact.as("c")
|
||||||
@ -139,7 +139,7 @@ object RPerson {
|
|||||||
where(
|
where(
|
||||||
p.cid === coll,
|
p.cid === coll,
|
||||||
c.kind === contactKind,
|
c.kind === contactKind,
|
||||||
p.concerning === concerningOnly,
|
p.use.in(use),
|
||||||
c.value.like(value)
|
c.value.like(value)
|
||||||
)
|
)
|
||||||
).query[IdRef].to[Vector]
|
).query[IdRef].to[Vector]
|
||||||
|
4
modules/webapp/src/main/elm/Comp/DateInput.elm
Normal file
4
modules/webapp/src/main/elm/Comp/DateInput.elm
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
module Comp.DateInput exposing (..)
|
||||||
|
|
||||||
|
import Html exposing (..)
|
||||||
|
import Html.Attributes exposing (..)
|
@ -32,6 +32,7 @@ import Data.DropdownStyle
|
|||||||
import Data.Fields
|
import Data.Fields
|
||||||
import Data.Flags exposing (Flags)
|
import Data.Flags exposing (Flags)
|
||||||
import Data.Icons as Icons
|
import Data.Icons as Icons
|
||||||
|
import Data.PersonUse
|
||||||
import Data.UiSettings exposing (UiSettings)
|
import Data.UiSettings exposing (UiSettings)
|
||||||
import DatePicker exposing (DatePicker)
|
import DatePicker exposing (DatePicker)
|
||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
@ -429,14 +430,14 @@ update flags msg model =
|
|||||||
|
|
||||||
GetPersonResp (Ok ps) ->
|
GetPersonResp (Ok ps) ->
|
||||||
let
|
let
|
||||||
( conc, corr ) =
|
{ concerning, correspondent } =
|
||||||
List.partition .concerning ps.items
|
Data.PersonUse.spanPersonList ps.items
|
||||||
|
|
||||||
concRefs =
|
concRefs =
|
||||||
List.map (\e -> IdName e.id e.name) conc
|
List.map (\e -> IdName e.id e.name) concerning
|
||||||
|
|
||||||
corrRefs =
|
corrRefs =
|
||||||
List.map (\e -> IdName e.id e.name) corr
|
List.map (\e -> IdName e.id e.name) correspondent
|
||||||
|
|
||||||
res1 =
|
res1 =
|
||||||
update flags (CorrPersonMsg (Comp.Dropdown.SetOptions corrRefs)) model
|
update flags (CorrPersonMsg (Comp.Dropdown.SetOptions corrRefs)) model
|
||||||
|
@ -49,6 +49,7 @@ import Data.Direction
|
|||||||
import Data.Fields exposing (Field)
|
import Data.Fields exposing (Field)
|
||||||
import Data.Flags exposing (Flags)
|
import Data.Flags exposing (Flags)
|
||||||
import Data.ItemNav exposing (ItemNav)
|
import Data.ItemNav exposing (ItemNav)
|
||||||
|
import Data.PersonUse
|
||||||
import Data.UiSettings exposing (UiSettings)
|
import Data.UiSettings exposing (UiSettings)
|
||||||
import DatePicker
|
import DatePicker
|
||||||
import Dict
|
import Dict
|
||||||
@ -612,8 +613,8 @@ update key flags inav settings msg model =
|
|||||||
|
|
||||||
GetPersonResp (Ok ps) ->
|
GetPersonResp (Ok ps) ->
|
||||||
let
|
let
|
||||||
( conc, corr ) =
|
{ concerning, correspondent } =
|
||||||
List.partition .concerning ps.items
|
Data.PersonUse.spanPersonList ps.items
|
||||||
|
|
||||||
personDict =
|
personDict =
|
||||||
List.map (\p -> ( p.id, p )) ps.items
|
List.map (\p -> ( p.id, p )) ps.items
|
||||||
@ -632,10 +633,10 @@ update key flags inav settings msg model =
|
|||||||
\_ -> True
|
\_ -> True
|
||||||
|
|
||||||
concRefs =
|
concRefs =
|
||||||
List.map (\e -> IdName e.id e.name) conc
|
List.map (\e -> IdName e.id e.name) concerning
|
||||||
|
|
||||||
corrRefs =
|
corrRefs =
|
||||||
List.filter personFilter corr
|
List.filter personFilter correspondent
|
||||||
|> List.map (\e -> IdName e.id e.name)
|
|> List.map (\e -> IdName e.id e.name)
|
||||||
|
|
||||||
mkPersonOption idref =
|
mkPersonOption idref =
|
||||||
|
@ -16,12 +16,14 @@ import Comp.AddressForm
|
|||||||
import Comp.Basic as B
|
import Comp.Basic as B
|
||||||
import Comp.ContactField
|
import Comp.ContactField
|
||||||
import Comp.Dropdown
|
import Comp.Dropdown
|
||||||
|
import Comp.FixedDropdown
|
||||||
import Data.DropdownStyle as DS
|
import Data.DropdownStyle as DS
|
||||||
import Data.Flags exposing (Flags)
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.PersonUse exposing (PersonUse)
|
||||||
import Data.UiSettings exposing (UiSettings)
|
import Data.UiSettings exposing (UiSettings)
|
||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
import Html.Attributes exposing (..)
|
import Html.Attributes exposing (..)
|
||||||
import Html.Events exposing (onCheck, onInput)
|
import Html.Events exposing (onInput)
|
||||||
import Styles as S
|
import Styles as S
|
||||||
|
|
||||||
|
|
||||||
@ -31,7 +33,8 @@ type alias Model =
|
|||||||
, addressModel : Comp.AddressForm.Model
|
, addressModel : Comp.AddressForm.Model
|
||||||
, contactModel : Comp.ContactField.Model
|
, contactModel : Comp.ContactField.Model
|
||||||
, notes : Maybe String
|
, notes : Maybe String
|
||||||
, concerning : Bool
|
, use : PersonUse
|
||||||
|
, useModel : Comp.FixedDropdown.Model PersonUse
|
||||||
, orgModel : Comp.Dropdown.Model IdName
|
, orgModel : Comp.Dropdown.Model IdName
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +46,11 @@ emptyModel =
|
|||||||
, addressModel = Comp.AddressForm.emptyModel
|
, addressModel = Comp.AddressForm.emptyModel
|
||||||
, contactModel = Comp.ContactField.emptyModel
|
, contactModel = Comp.ContactField.emptyModel
|
||||||
, notes = Nothing
|
, notes = Nothing
|
||||||
, concerning = False
|
, use = Data.PersonUse.Both
|
||||||
|
, useModel =
|
||||||
|
Comp.FixedDropdown.initMap
|
||||||
|
Data.PersonUse.label
|
||||||
|
Data.PersonUse.all
|
||||||
, orgModel = Comp.Dropdown.orgDropdown
|
, orgModel = Comp.Dropdown.orgDropdown
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +75,7 @@ getPerson model =
|
|||||||
, address = Comp.AddressForm.getAddress model.addressModel
|
, address = Comp.AddressForm.getAddress model.addressModel
|
||||||
, contacts = Comp.ContactField.getContacts model.contactModel
|
, contacts = Comp.ContactField.getContacts model.contactModel
|
||||||
, notes = model.notes
|
, notes = model.notes
|
||||||
, concerning = model.concerning
|
, use = Data.PersonUse.asString model.use
|
||||||
, organization = org
|
, organization = org
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,9 +86,9 @@ type Msg
|
|||||||
| AddressMsg Comp.AddressForm.Msg
|
| AddressMsg Comp.AddressForm.Msg
|
||||||
| ContactMsg Comp.ContactField.Msg
|
| ContactMsg Comp.ContactField.Msg
|
||||||
| SetNotes String
|
| SetNotes String
|
||||||
| SetConcerning Bool
|
|
||||||
| SetOrgs (List IdName)
|
| SetOrgs (List IdName)
|
||||||
| OrgDropdownMsg (Comp.Dropdown.Msg IdName)
|
| OrgDropdownMsg (Comp.Dropdown.Msg IdName)
|
||||||
|
| UseDropdownMsg (Comp.FixedDropdown.Msg PersonUse)
|
||||||
|
|
||||||
|
|
||||||
update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
|
update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
|
||||||
@ -108,7 +115,9 @@ update flags msg model =
|
|||||||
| person = t
|
| person = t
|
||||||
, name = t.name
|
, name = t.name
|
||||||
, notes = t.notes
|
, notes = t.notes
|
||||||
, concerning = t.concerning
|
, use =
|
||||||
|
Data.PersonUse.fromString t.use
|
||||||
|
|> Maybe.withDefault Data.PersonUse.Both
|
||||||
}
|
}
|
||||||
, Cmd.batch [ c1, c2, c3 ]
|
, Cmd.batch [ c1, c2, c3 ]
|
||||||
)
|
)
|
||||||
@ -149,8 +158,15 @@ update flags msg model =
|
|||||||
, Cmd.none
|
, Cmd.none
|
||||||
)
|
)
|
||||||
|
|
||||||
SetConcerning _ ->
|
UseDropdownMsg lm ->
|
||||||
( { model | concerning = not model.concerning }, Cmd.none )
|
let
|
||||||
|
( nm, mu ) =
|
||||||
|
Comp.FixedDropdown.update lm model.useModel
|
||||||
|
|
||||||
|
newUse =
|
||||||
|
Maybe.withDefault model.use mu
|
||||||
|
in
|
||||||
|
( { model | useModel = nm, use = newUse }, Cmd.none )
|
||||||
|
|
||||||
OrgDropdownMsg lm ->
|
OrgDropdownMsg lm ->
|
||||||
let
|
let
|
||||||
@ -185,16 +201,10 @@ view1 settings compact model =
|
|||||||
]
|
]
|
||||||
[]
|
[]
|
||||||
]
|
]
|
||||||
, div [ class "inline field" ]
|
, div [ class "field" ]
|
||||||
[ div [ class "ui checkbox" ]
|
[ label [] [ text "Use" ]
|
||||||
[ input
|
, Html.map UseDropdownMsg (Comp.FixedDropdown.view (makeUseItem model) model.useModel)
|
||||||
[ type_ "checkbox"
|
, label [] [ text "Use for concerning person suggestion only" ]
|
||||||
, checked model.concerning
|
|
||||||
, onCheck SetConcerning
|
|
||||||
]
|
|
||||||
[]
|
|
||||||
, label [] [ text "Use for concerning person suggestion only" ]
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
, div [ class "field" ]
|
, div [ class "field" ]
|
||||||
[ label [] [ text "Organization" ]
|
[ label [] [ text "Organization" ]
|
||||||
@ -221,6 +231,12 @@ view1 settings compact model =
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
makeUseItem : Model -> Maybe (Comp.FixedDropdown.Item PersonUse)
|
||||||
|
makeUseItem model =
|
||||||
|
Just <|
|
||||||
|
Comp.FixedDropdown.Item model.use (Data.PersonUse.label model.use)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- View2
|
--- View2
|
||||||
|
|
||||||
@ -253,21 +269,21 @@ view2 mobile settings model =
|
|||||||
]
|
]
|
||||||
, div [ class "mb-4" ]
|
, div [ class "mb-4" ]
|
||||||
[ label
|
[ label
|
||||||
[ class "inline-flex items-center"
|
[ class S.inputLabel
|
||||||
, for "concerning"
|
|
||||||
]
|
]
|
||||||
[ input
|
[ text "Use of this person" ]
|
||||||
[ type_ "checkbox"
|
, Html.map UseDropdownMsg
|
||||||
, checked model.concerning
|
(Comp.FixedDropdown.view2 (makeUseItem model) model.useModel)
|
||||||
, onCheck SetConcerning
|
, span [ class "opacity-50 text-sm" ]
|
||||||
, class S.checkboxInput
|
[ case model.use of
|
||||||
, name "concerning"
|
Data.PersonUse.Concerning ->
|
||||||
, id "concerning"
|
text "Use as concerning person only"
|
||||||
]
|
|
||||||
[]
|
Data.PersonUse.Correspondent ->
|
||||||
, span [ class "ml-2" ]
|
text "Use as correspondent person only"
|
||||||
[ text "Use for concerning person suggestion only"
|
|
||||||
]
|
Data.PersonUse.Both ->
|
||||||
|
text "Use as both concerning or correspondent person"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
, div [ class "mb-4" ]
|
, div [ class "mb-4" ]
|
||||||
|
@ -10,6 +10,7 @@ module Comp.PersonTable exposing
|
|||||||
import Api.Model.Person exposing (Person)
|
import Api.Model.Person exposing (Person)
|
||||||
import Comp.Basic as B
|
import Comp.Basic as B
|
||||||
import Data.Flags exposing (Flags)
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.PersonUse
|
||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
import Html.Attributes exposing (..)
|
import Html.Attributes exposing (..)
|
||||||
import Html.Events exposing (onClick)
|
import Html.Events exposing (onClick)
|
||||||
@ -57,7 +58,7 @@ view model =
|
|||||||
[ thead []
|
[ thead []
|
||||||
[ tr []
|
[ tr []
|
||||||
[ th [ class "collapsing" ] []
|
[ th [ class "collapsing" ] []
|
||||||
, th [ class "collapsing center aligned" ] [ text "Concerning" ]
|
, th [ class "collapsing center aligned" ] [ text "Use" ]
|
||||||
, th [] [ text "Name" ]
|
, th [] [ text "Name" ]
|
||||||
, th [] [ text "Organization" ]
|
, th [] [ text "Organization" ]
|
||||||
, th [] [ text "Address" ]
|
, th [] [ text "Address" ]
|
||||||
@ -85,11 +86,10 @@ renderPersonLine model person =
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
, td [ class "center aligned" ]
|
, td [ class "center aligned" ]
|
||||||
[ if person.concerning then
|
[ Data.PersonUse.fromString person.use
|
||||||
i [ class "check square outline icon" ] []
|
|> Maybe.withDefault Data.PersonUse.Both
|
||||||
|
|> Data.PersonUse.label
|
||||||
else
|
|> text
|
||||||
i [ class "minus square outline icon" ] []
|
|
||||||
]
|
]
|
||||||
, td []
|
, td []
|
||||||
[ text person.name
|
[ text person.name
|
||||||
@ -118,8 +118,8 @@ view2 model =
|
|||||||
[ thead []
|
[ thead []
|
||||||
[ tr []
|
[ tr []
|
||||||
[ th [ class "w-px whitespace-nowrap" ] []
|
[ th [ class "w-px whitespace-nowrap" ] []
|
||||||
, th [ class "w-px whitespace-nowrap text-center pr-1 md:px-2" ]
|
, th [ class "text-left pr-1 md:px-2" ]
|
||||||
[ text "Concerning"
|
[ text "Use"
|
||||||
]
|
]
|
||||||
, th [ class "text-left" ] [ text "Name" ]
|
, th [ class "text-left" ] [ text "Name" ]
|
||||||
, th [ class "text-left hidden sm:table-cell" ] [ text "Organization" ]
|
, th [ class "text-left hidden sm:table-cell" ] [ text "Organization" ]
|
||||||
@ -138,8 +138,13 @@ renderPersonLine2 model person =
|
|||||||
, class S.tableRow
|
, class S.tableRow
|
||||||
]
|
]
|
||||||
[ B.editLinkTableCell (Select person)
|
[ B.editLinkTableCell (Select person)
|
||||||
, td [ class "w-px whitespace-nowrap text-center" ]
|
, td [ class "text-left pr-1 md:px-2" ]
|
||||||
[ Util.Html.checkbox2 person.concerning
|
[ div [ class "label inline-flex text-sm" ]
|
||||||
|
[ Data.PersonUse.fromString person.use
|
||||||
|
|> Maybe.withDefault Data.PersonUse.Both
|
||||||
|
|> Data.PersonUse.label
|
||||||
|
|> text
|
||||||
|
]
|
||||||
]
|
]
|
||||||
, td []
|
, td []
|
||||||
[ text person.name
|
[ text person.name
|
||||||
|
@ -38,6 +38,7 @@ import Data.DropdownStyle as DS
|
|||||||
import Data.Fields
|
import Data.Fields
|
||||||
import Data.Flags exposing (Flags)
|
import Data.Flags exposing (Flags)
|
||||||
import Data.Icons as Icons
|
import Data.Icons as Icons
|
||||||
|
import Data.PersonUse
|
||||||
import Data.UiSettings exposing (UiSettings)
|
import Data.UiSettings exposing (UiSettings)
|
||||||
import DatePicker exposing (DatePicker)
|
import DatePicker exposing (DatePicker)
|
||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
@ -561,14 +562,14 @@ updateDrop ddm flags settings msg model =
|
|||||||
|
|
||||||
GetPersonResp (Ok ps) ->
|
GetPersonResp (Ok ps) ->
|
||||||
let
|
let
|
||||||
( conc, corr ) =
|
{ concerning, correspondent } =
|
||||||
List.partition .concerning ps.items
|
Data.PersonUse.spanPersonList ps.items
|
||||||
|
|
||||||
concRefs =
|
concRefs =
|
||||||
List.map (\e -> IdName e.id e.name) conc
|
List.map (\e -> IdName e.id e.name) concerning
|
||||||
|
|
||||||
corrRefs =
|
corrRefs =
|
||||||
List.map (\e -> IdName e.id e.name) corr
|
List.map (\e -> IdName e.id e.name) correspondent
|
||||||
|
|
||||||
next1 =
|
next1 =
|
||||||
updateDrop ddm
|
updateDrop ddm
|
||||||
|
90
modules/webapp/src/main/elm/Data/PersonUse.elm
Normal file
90
modules/webapp/src/main/elm/Data/PersonUse.elm
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
module Data.PersonUse exposing
|
||||||
|
( PersonUse(..)
|
||||||
|
, all
|
||||||
|
, asString
|
||||||
|
, fromString
|
||||||
|
, label
|
||||||
|
, spanPersonList
|
||||||
|
)
|
||||||
|
|
||||||
|
import Api.Model.Person exposing (Person)
|
||||||
|
|
||||||
|
|
||||||
|
type PersonUse
|
||||||
|
= Correspondent
|
||||||
|
| Concerning
|
||||||
|
| Both
|
||||||
|
|
||||||
|
|
||||||
|
fromString : String -> Maybe PersonUse
|
||||||
|
fromString str =
|
||||||
|
case String.toLower str of
|
||||||
|
"concerning" ->
|
||||||
|
Just Concerning
|
||||||
|
|
||||||
|
"correspondent" ->
|
||||||
|
Just Correspondent
|
||||||
|
|
||||||
|
"both" ->
|
||||||
|
Just Both
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
|
||||||
|
asString : PersonUse -> String
|
||||||
|
asString pu =
|
||||||
|
case pu of
|
||||||
|
Correspondent ->
|
||||||
|
"correspondent"
|
||||||
|
|
||||||
|
Concerning ->
|
||||||
|
"concerning"
|
||||||
|
|
||||||
|
Both ->
|
||||||
|
"both"
|
||||||
|
|
||||||
|
|
||||||
|
label : PersonUse -> String
|
||||||
|
label pu =
|
||||||
|
case pu of
|
||||||
|
Correspondent ->
|
||||||
|
"Correspondent"
|
||||||
|
|
||||||
|
Concerning ->
|
||||||
|
"Concerning"
|
||||||
|
|
||||||
|
Both ->
|
||||||
|
"Both"
|
||||||
|
|
||||||
|
|
||||||
|
all : List PersonUse
|
||||||
|
all =
|
||||||
|
[ Correspondent, Concerning, Both ]
|
||||||
|
|
||||||
|
|
||||||
|
spanPersonList : List Person -> { concerning : List Person, correspondent : List Person }
|
||||||
|
spanPersonList input =
|
||||||
|
let
|
||||||
|
init =
|
||||||
|
{ concerning = [], correspondent = [] }
|
||||||
|
|
||||||
|
parseUse p =
|
||||||
|
fromString p.use
|
||||||
|
|> Maybe.withDefault Both
|
||||||
|
|
||||||
|
merge p res =
|
||||||
|
case parseUse p of
|
||||||
|
Concerning ->
|
||||||
|
{ res | concerning = p :: res.concerning }
|
||||||
|
|
||||||
|
Correspondent ->
|
||||||
|
{ res | correspondent = p :: res.correspondent }
|
||||||
|
|
||||||
|
Both ->
|
||||||
|
{ res
|
||||||
|
| correspondent = p :: res.correspondent
|
||||||
|
, concerning = p :: res.concerning
|
||||||
|
}
|
||||||
|
in
|
||||||
|
List.foldl merge init input
|
Loading…
x
Reference in New Issue
Block a user