Allow person to be correspondent, concerning or both

This commit is contained in:
Eike Kettner 2021-02-16 22:37:56 +01:00
parent 567bfb3e69
commit 48eee00c0b
19 changed files with 321 additions and 94 deletions

View File

@ -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")))
})) }))
) )

View File

@ -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)
}

View File

@ -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") *>

View File

@ -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

View File

@ -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

View File

@ -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)
} }

View File

@ -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";

View File

@ -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`;

View File

@ -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";

View File

@ -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 {

View File

@ -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

View File

@ -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]

View File

@ -0,0 +1,4 @@
module Comp.DateInput exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)

View File

@ -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

View File

@ -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 =

View File

@ -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" ]

View File

@ -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

View File

@ -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

View 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