Merge pull request #645 from eikek/equipment-description

Equipment description
This commit is contained in:
mergify[bot] 2021-02-17 22:17:03 +00:00 committed by GitHub
commit b16166f1e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 133 additions and 42 deletions

View File

@ -4,9 +4,9 @@ import java.security.SecureRandom
import java.util.UUID import java.util.UUID
import cats.Eq import cats.Eq
import cats.Order
import cats.effect.Sync import cats.effect.Sync
import cats.implicits._ import cats.implicits._
import cats.Order
import io.circe.{Decoder, Encoder} import io.circe.{Decoder, Encoder}
import scodec.bits.ByteVector import scodec.bits.ByteVector

View File

@ -4980,6 +4980,8 @@ components:
description: DateTime description: DateTime
type: integer type: integer
format: date-time format: date-time
notes:
type: string
ReferenceList: ReferenceList:
description: description:
Listing of entities with their id and a name. Listing of entities with their id and a name.
@ -5067,6 +5069,8 @@ components:
description: DateTime description: DateTime
type: integer type: integer
format: date-time format: date-time
shortName:
type: string
OrganizationList: OrganizationList:
description: | description: |
A list of full organization values. A list of full organization values.

View File

@ -386,7 +386,8 @@ trait Conversions {
Address(ro.street, ro.zip, ro.city, ro.country), Address(ro.street, ro.zip, ro.city, ro.country),
v.contacts.map(mkContact).toList, v.contacts.map(mkContact).toList,
ro.notes, ro.notes,
ro.created ro.created,
ro.shortName
) )
} }
@ -407,7 +408,8 @@ trait Conversions {
v.address.country, v.address.country,
v.notes, v.notes,
now, now,
now now,
v.shortName
) )
} yield OOrganization.OrgAndContacts(org, cont) } yield OOrganization.OrgAndContacts(org, cont)
} }
@ -431,7 +433,8 @@ trait Conversions {
v.address.country, v.address.country,
v.notes, v.notes,
v.created, v.created,
now now,
v.shortName
) )
} yield OOrganization.OrgAndContacts(org, cont) } yield OOrganization.OrgAndContacts(org, cont)
} }
@ -617,15 +620,17 @@ trait Conversions {
// equipment // equipment
def mkEquipment(re: REquipment): Equipment = def mkEquipment(re: REquipment): Equipment =
Equipment(re.eid, re.name, re.created) Equipment(re.eid, re.name, re.created, re.notes)
def newEquipment[F[_]: Sync](e: Equipment, cid: Ident): F[REquipment] = def newEquipment[F[_]: Sync](e: Equipment, cid: Ident): F[REquipment] =
timeId.map({ case (id, now) => timeId.map({ case (id, now) =>
REquipment(id, cid, e.name, now, now) REquipment(id, cid, e.name, now, now, e.notes)
}) })
def changeEquipment[F[_]: Sync](e: Equipment, cid: Ident): F[REquipment] = def changeEquipment[F[_]: Sync](e: Equipment, cid: Ident): F[REquipment] =
Timestamp.current[F].map(now => REquipment(e.id, cid, e.name, e.created, now)) Timestamp
.current[F]
.map(now => REquipment(e.id, cid, e.name, e.created, now, e.notes))
// idref // idref

View File

@ -0,0 +1,2 @@
ALTER TABLE "equipment"
ADD COLUMN "notes" text;

View File

@ -0,0 +1,2 @@
ALTER TABLE "organization"
ADD COLUMN "short_name" varchar(254);

View File

@ -0,0 +1,2 @@
ALTER TABLE `equipment`
ADD COLUMN `notes` mediumtext;

View File

@ -0,0 +1,2 @@
ALTER TABLE `organization`
ADD COLUMN `short_name` varchar(254);

View File

@ -0,0 +1,2 @@
ALTER TABLE "equipment"
ADD COLUMN "notes" text;

View File

@ -0,0 +1,2 @@
ALTER TABLE "organization"
ADD COLUMN "short_name" varchar(254);

View File

@ -25,7 +25,7 @@ object QOrganization {
): Stream[ConnectionIO, (ROrganization, Vector[RContact])] = { ): Stream[ConnectionIO, (ROrganization, Vector[RContact])] = {
val valFilter = query.map { q => val valFilter = query.map { q =>
val v = s"%$q%" val v = s"%$q%"
c.value.like(v) || org.name.like(v) || org.notes.like(v) c.value.like(v) || org.name.like(v) || org.shortName.like(v) || org.notes.like(v)
} }
val sql = Select( val sql = Select(
select(org.all, c.all), select(org.all, c.all),

View File

@ -14,7 +14,8 @@ case class REquipment(
cid: Ident, cid: Ident,
name: String, name: String,
created: Timestamp, created: Timestamp,
updated: Timestamp updated: Timestamp,
notes: Option[String]
) {} ) {}
object REquipment { object REquipment {
@ -26,7 +27,8 @@ object REquipment {
val name = Column[String]("name", this) val name = Column[String]("name", 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 all = NonEmptyList.of[Column[_]](eid, cid, name, created, updated) val notes = Column[String]("notes", this)
val all = NonEmptyList.of[Column[_]](eid, cid, name, created, updated, notes)
} }
val T = Table(None) val T = Table(None)
@ -39,7 +41,7 @@ object REquipment {
.insert( .insert(
t, t,
t.all, t.all,
fr"${v.eid},${v.cid},${v.name},${v.created},${v.updated}" fr"${v.eid},${v.cid},${v.name},${v.created},${v.updated},${v.notes}"
) )
} }
@ -54,7 +56,8 @@ object REquipment {
DML.set( DML.set(
t.cid.setTo(v.cid), t.cid.setTo(v.cid),
t.name.setTo(v.name), t.name.setTo(v.name),
t.updated.setTo(now) t.updated.setTo(now),
t.notes.setTo(v.notes)
) )
) )
} yield n } yield n

View File

@ -21,7 +21,8 @@ case class ROrganization(
country: String, country: String,
notes: Option[String], notes: Option[String],
created: Timestamp, created: Timestamp,
updated: Timestamp updated: Timestamp,
shortName: Option[String]
) {} ) {}
object ROrganization { object ROrganization {
@ -31,16 +32,17 @@ object ROrganization {
final case class Table(alias: Option[String]) extends TableDef { final case class Table(alias: Option[String]) extends TableDef {
val tableName = "organization" val tableName = "organization"
val oid = Column[Ident]("oid", this) val oid = Column[Ident]("oid", 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 created = Column[Timestamp]("created", this) val created = Column[Timestamp]("created", this)
val updated = Column[Timestamp]("updated", this) val updated = Column[Timestamp]("updated", this)
val shortName = Column[String]("short_name", this)
val all = val all =
NonEmptyList.of[Column[_]]( NonEmptyList.of[Column[_]](
oid, oid,
@ -52,7 +54,8 @@ object ROrganization {
country, country,
notes, notes,
created, created,
updated updated,
shortName
) )
} }
@ -64,7 +67,7 @@ object ROrganization {
DML.insert( DML.insert(
T, T,
T.all, T.all,
fr"${v.oid},${v.cid},${v.name},${v.street},${v.zip},${v.city},${v.country},${v.notes},${v.created},${v.updated}" fr"${v.oid},${v.cid},${v.name},${v.street},${v.zip},${v.city},${v.country},${v.notes},${v.created},${v.updated},${v.shortName}"
) )
def update(v: ROrganization): ConnectionIO[Int] = { def update(v: ROrganization): ConnectionIO[Int] = {
@ -80,7 +83,8 @@ object ROrganization {
T.city.setTo(v.city), T.city.setTo(v.city),
T.country.setTo(v.country), T.country.setTo(v.country),
T.notes.setTo(v.notes), T.notes.setTo(v.notes),
T.updated.setTo(now) T.updated.setTo(now),
T.shortName.setTo(v.shortName)
) )
) )
for { for {
@ -106,7 +110,11 @@ object ROrganization {
} }
def findLike(coll: Ident, orgName: String): ConnectionIO[Vector[IdRef]] = def findLike(coll: Ident, orgName: String): ConnectionIO[Vector[IdRef]] =
run(select(T.oid, T.name), from(T), T.cid === coll && T.name.like(orgName)) run(
select(T.oid, T.name),
from(T),
T.cid === coll && (T.name.like(orgName) || T.shortName.like(orgName))
)
.query[IdRef] .query[IdRef]
.to[Vector] .to[Vector]
@ -141,7 +149,9 @@ object ROrganization {
nameQ: Option[String], nameQ: Option[String],
order: Table => Column[_] order: Table => Column[_]
): ConnectionIO[Vector[IdRef]] = { ): ConnectionIO[Vector[IdRef]] = {
val nameFilter = nameQ.map(s => T.name.like(s"%${s.toLowerCase}%")) val nameFilter = nameQ.map(s =>
T.name.like(s"%${s.toLowerCase}%") || T.shortName.like(s"%${s.toLowerCase}%")
)
val sql = Select(select(T.oid, T.name), from(T), T.cid === coll &&? nameFilter) val sql = Select(select(T.oid, T.name), from(T), T.cid === coll &&? nameFilter)
.orderBy(order(T)) .orderBy(order(T))
sql.build.query[IdRef].to[Vector] sql.build.query[IdRef].to[Vector]

View File

@ -16,11 +16,13 @@ import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
import Html.Events exposing (onInput) import Html.Events exposing (onInput)
import Styles as S import Styles as S
import Util.Maybe
type alias Model = type alias Model =
{ equipment : Equipment { equipment : Equipment
, name : String , name : String
, notes : Maybe String
} }
@ -28,6 +30,7 @@ emptyModel : Model
emptyModel = emptyModel =
{ equipment = Api.Model.Equipment.empty { equipment = Api.Model.Equipment.empty
, name = "" , name = ""
, notes = Nothing
} }
@ -38,23 +41,37 @@ isValid model =
getEquipment : Model -> Equipment getEquipment : Model -> Equipment
getEquipment model = getEquipment model =
Equipment model.equipment.id model.name model.equipment.created { id = model.equipment.id
, name = model.name
, created = model.equipment.created
, notes = model.notes
}
type Msg type Msg
= SetName String = SetName String
| SetEquipment Equipment | SetEquipment Equipment
| SetNotes String
update : Flags -> Msg -> Model -> ( Model, Cmd Msg ) update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
update _ msg model = update _ msg model =
case msg of case msg of
SetEquipment t -> SetEquipment t ->
( { model | equipment = t, name = t.name }, Cmd.none ) ( { model
| equipment = t
, name = t.name
, notes = t.notes
}
, Cmd.none
)
SetName n -> SetName n ->
( { model | name = n }, Cmd.none ) ( { model | name = n }, Cmd.none )
SetNotes str ->
( { model | notes = Util.Maybe.fromString str }, Cmd.none )
view : Model -> Html Msg view : Model -> Html Msg
view model = view model =
@ -84,9 +101,7 @@ view model =
view2 : Model -> Html Msg view2 : Model -> Html Msg
view2 model = view2 model =
div [ class "flex flex-col" ] div [ class "flex flex-col" ]
[ div [ div [ class "mb-4" ]
[ class "mb-4"
]
[ label [ label
[ for "equipname" [ for "equipname"
, class S.inputLabel , class S.inputLabel
@ -109,4 +124,17 @@ view2 model =
] ]
[] []
] ]
, div [ class "mb-4" ]
[ h3 [ class S.header3 ]
[ text "Notes"
]
, div [ class "" ]
[ textarea
[ onInput SetNotes
, Maybe.withDefault "" model.notes |> value
, class S.textAreaInput
]
[]
]
]
] ]

View File

@ -20,6 +20,7 @@ import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
import Html.Events exposing (onInput) import Html.Events exposing (onInput)
import Styles as S import Styles as S
import Util.Maybe
type alias Model = type alias Model =
@ -28,6 +29,7 @@ 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
, shortName : Maybe String
} }
@ -38,6 +40,7 @@ emptyModel =
, addressModel = Comp.AddressForm.emptyModel , addressModel = Comp.AddressForm.emptyModel
, contactModel = Comp.ContactField.emptyModel , contactModel = Comp.ContactField.emptyModel
, notes = Nothing , notes = Nothing
, shortName = Nothing
} }
@ -57,6 +60,7 @@ getOrg 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
, shortName = model.shortName
} }
@ -66,6 +70,7 @@ type Msg
| AddressMsg Comp.AddressForm.Msg | AddressMsg Comp.AddressForm.Msg
| ContactMsg Comp.ContactField.Msg | ContactMsg Comp.ContactField.Msg
| SetNotes String | SetNotes String
| SetShortName String
update : Flags -> Msg -> Model -> ( Model, Cmd Msg ) update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
@ -79,7 +84,14 @@ update flags msg model =
( m2, c2 ) = ( m2, c2 ) =
update flags (ContactMsg (Comp.ContactField.SetItems t.contacts)) m1 update flags (ContactMsg (Comp.ContactField.SetItems t.contacts)) m1
in in
( { m2 | org = t, name = t.name, notes = t.notes }, Cmd.batch [ c1, c2 ] ) ( { m2
| org = t
, name = t.name
, notes = t.notes
, shortName = t.shortName
}
, Cmd.batch [ c1, c2 ]
)
AddressMsg am -> AddressMsg am ->
let let
@ -99,14 +111,12 @@ update flags msg model =
( { model | name = n }, Cmd.none ) ( { model | name = n }, Cmd.none )
SetNotes str -> SetNotes str ->
( { model ( { model | notes = Util.Maybe.fromString str }
| notes = , Cmd.none
if str == "" then )
Nothing
else SetShortName str ->
Just str ( { model | shortName = Util.Maybe.fromString str }
}
, Cmd.none , Cmd.none
) )
@ -184,6 +194,25 @@ view2 mobile settings model =
] ]
[] []
] ]
, div
[ class "mb-4" ]
[ label
[ for "org-short-name"
, class S.inputLabel
]
[ text "Short Name"
]
, input
[ type_ "text"
, onInput SetShortName
, placeholder "Abbreviation"
, Maybe.withDefault "" model.shortName
|> value
, name "org-short-name"
, class S.textInput
]
[]
]
, div [ class "mb-4" ] , div [ class "mb-4" ]
[ h3 [ class S.header3 ] [ h3 [ class S.header3 ]
[ text "Address" [ text "Address"

View File

@ -479,7 +479,7 @@ updateDrop ddm flags settings msg model =
SetConcEquip id -> SetConcEquip id ->
let let
equip = equip =
Equipment id.id id.name 0 Equipment id.id id.name 0 Nothing
in in
resetAndSet (ConcEquipmentMsg (Comp.Dropdown.SetSelection [ equip ])) resetAndSet (ConcEquipmentMsg (Comp.Dropdown.SetSelection [ equip ]))