mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-02-15 20:33:26 +00:00
Set the folder of an item
This commit is contained in:
parent
5bde78083a
commit
86443e10a6
@ -24,6 +24,8 @@ trait OItem[F[_]] {
|
||||
|
||||
def setDirection(item: Ident, direction: Direction, collective: Ident): F[AddResult]
|
||||
|
||||
def setFolder(item: Ident, folder: Option[Ident], collective: Ident): F[AddResult]
|
||||
|
||||
def setCorrOrg(item: Ident, org: Option[Ident], collective: Ident): F[AddResult]
|
||||
|
||||
def addCorrOrg(item: Ident, org: OOrganization.OrgAndContacts): F[AddResult]
|
||||
@ -131,6 +133,16 @@ object OItem {
|
||||
.attempt
|
||||
.map(AddResult.fromUpdate)
|
||||
|
||||
def setFolder(
|
||||
item: Ident,
|
||||
folder: Option[Ident],
|
||||
collective: Ident
|
||||
): F[AddResult] =
|
||||
store
|
||||
.transact(RItem.updateFolder(item, collective, folder))
|
||||
.attempt
|
||||
.map(AddResult.fromUpdate)
|
||||
|
||||
def setCorrOrg(item: Ident, org: Option[Ident], collective: Ident): F[AddResult] =
|
||||
store
|
||||
.transact(RItem.updateCorrOrg(item, collective, org))
|
||||
|
@ -1365,6 +1365,31 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/BasicResult"
|
||||
/sec/item/{id}/folder:
|
||||
put:
|
||||
tags: [ Item ]
|
||||
summary: Set a folder for this item.
|
||||
description: |
|
||||
Updates the folder property for this item to "place" the item
|
||||
into a folder. If the request contains an empty object or an
|
||||
`id` property of `null`, the item is moved into the "public"
|
||||
or "root" folder.
|
||||
security:
|
||||
- authTokenHeader: []
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/id"
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/OptionalId"
|
||||
responses:
|
||||
200:
|
||||
description: Ok
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/BasicResult"
|
||||
/sec/item/{id}/corrOrg:
|
||||
put:
|
||||
tags: [ Item ]
|
||||
@ -3167,6 +3192,8 @@ components:
|
||||
$ref: "#/components/schemas/IdName"
|
||||
inReplyTo:
|
||||
$ref: "#/components/schemas/IdName"
|
||||
folder:
|
||||
$ref: "#/components/schemas/IdName"
|
||||
dueDate:
|
||||
type: integer
|
||||
format: date-time
|
||||
|
@ -85,6 +85,7 @@ trait Conversions {
|
||||
data.concPerson.map(p => IdName(p.pid, p.name)),
|
||||
data.concEquip.map(e => IdName(e.eid, e.name)),
|
||||
data.inReplyTo.map(mkIdName),
|
||||
data.folder.map(mkIdName),
|
||||
data.item.dueDate,
|
||||
data.item.notes,
|
||||
data.attachments.map((mkAttachment(data) _).tupled).toList,
|
||||
|
@ -149,6 +149,13 @@ object ItemRoutes {
|
||||
resp <- Ok(Conversions.basicResult(res, "Direction updated"))
|
||||
} yield resp
|
||||
|
||||
case req @ PUT -> Root / Ident(id) / "folder" =>
|
||||
for {
|
||||
idref <- req.as[OptionalId]
|
||||
res <- backend.item.setFolder(id, idref.id, user.account.collective)
|
||||
resp <- Ok(Conversions.basicResult(res, "Folder updated"))
|
||||
} yield resp
|
||||
|
||||
case req @ PUT -> Root / Ident(id) / "corrOrg" =>
|
||||
for {
|
||||
idref <- req.as[OptionalId]
|
||||
|
@ -66,6 +66,7 @@ object QItem {
|
||||
concPerson: Option[RPerson],
|
||||
concEquip: Option[REquipment],
|
||||
inReplyTo: Option[IdRef],
|
||||
folder: Option[IdRef],
|
||||
tags: Vector[RTag],
|
||||
attachments: Vector[(RAttachment, FileMeta)],
|
||||
sources: Vector[(RAttachmentSource, FileMeta)],
|
||||
@ -83,10 +84,11 @@ object QItem {
|
||||
val P1C = RPerson.Columns.all.map(_.prefix("p1"))
|
||||
val EC = REquipment.Columns.all.map(_.prefix("e"))
|
||||
val ICC = List(RItem.Columns.id, RItem.Columns.name).map(_.prefix("ref"))
|
||||
val FC = List(RFolder.Columns.id, RFolder.Columns.name).map(_.prefix("f"))
|
||||
|
||||
val cq =
|
||||
selectSimple(
|
||||
IC ++ OC ++ P0C ++ P1C ++ EC ++ ICC,
|
||||
IC ++ OC ++ P0C ++ P1C ++ EC ++ ICC ++ FC,
|
||||
RItem.table ++ fr"i",
|
||||
Fragment.empty
|
||||
) ++
|
||||
@ -105,6 +107,9 @@ object QItem {
|
||||
fr"LEFT JOIN" ++ RItem.table ++ fr"ref ON" ++ RItem.Columns.inReplyTo
|
||||
.prefix("i")
|
||||
.is(RItem.Columns.id.prefix("ref")) ++
|
||||
fr"LEFT JOIN" ++ RFolder.table ++ fr"f ON" ++ RItem.Columns.folder
|
||||
.prefix("i")
|
||||
.is(RFolder.Columns.id.prefix("f")) ++
|
||||
fr"WHERE" ++ RItem.Columns.id.prefix("i").is(id)
|
||||
|
||||
val q = cq
|
||||
@ -115,6 +120,7 @@ object QItem {
|
||||
Option[RPerson],
|
||||
Option[RPerson],
|
||||
Option[REquipment],
|
||||
Option[IdRef],
|
||||
Option[IdRef]
|
||||
)
|
||||
]
|
||||
@ -132,7 +138,7 @@ object QItem {
|
||||
arch <- archives
|
||||
ts <- tags
|
||||
} yield data.map(d =>
|
||||
ItemData(d._1, d._2, d._3, d._4, d._5, d._6, ts, att, srcs, arch)
|
||||
ItemData(d._1, d._2, d._3, d._4, d._5, d._6, d._7, ts, att, srcs, arch)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ object RItem {
|
||||
val created = Column("created")
|
||||
val updated = Column("updated")
|
||||
val notes = Column("notes")
|
||||
val folder = Column("folder_id")
|
||||
val folder = Column("folder_id")
|
||||
val all = List(
|
||||
id,
|
||||
cid,
|
||||
@ -243,7 +243,17 @@ object RItem {
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(cid.is(coll), concEquipment.is(Some(currentEquip))),
|
||||
commas(concPerson.setTo(None: Option[Ident]), updated.setTo(t))
|
||||
commas(concEquipment.setTo(None: Option[Ident]), updated.setTo(t))
|
||||
).update.run
|
||||
} yield n
|
||||
|
||||
def updateFolder(itemId: Ident, coll: Ident, folderId: Option[Ident]): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(cid.is(coll), id.is(itemId)),
|
||||
commas(folder.setTo(folderId), updated.setTo(t))
|
||||
).update.run
|
||||
} yield n
|
||||
|
||||
|
@ -77,6 +77,7 @@ module Api exposing
|
||||
, setCorrOrg
|
||||
, setCorrPerson
|
||||
, setDirection
|
||||
, setFolder
|
||||
, setItemDate
|
||||
, setItemDueDate
|
||||
, setItemName
|
||||
@ -1262,6 +1263,16 @@ setDirection flags item dir receive =
|
||||
}
|
||||
|
||||
|
||||
setFolder : Flags -> String -> OptionalId -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
||||
setFolder flags item id receive =
|
||||
Http2.authPut
|
||||
{ url = flags.config.baseUrl ++ "/api/v1/sec/item/" ++ item ++ "/folder"
|
||||
, account = getAccount flags
|
||||
, body = Http.jsonBody (Api.Model.OptionalId.encode id)
|
||||
, expect = Http.expectJson receive Api.Model.BasicResult.decoder
|
||||
}
|
||||
|
||||
|
||||
setCorrOrg : Flags -> String -> OptionalId -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
||||
setCorrOrg flags item id receive =
|
||||
Http2.authPut
|
||||
|
@ -11,6 +11,8 @@ import Api.Model.Attachment exposing (Attachment)
|
||||
import Api.Model.BasicResult exposing (BasicResult)
|
||||
import Api.Model.DirectionValue exposing (DirectionValue)
|
||||
import Api.Model.EquipmentList exposing (EquipmentList)
|
||||
import Api.Model.FolderItem exposing (FolderItem)
|
||||
import Api.Model.FolderList exposing (FolderList)
|
||||
import Api.Model.IdName exposing (IdName)
|
||||
import Api.Model.ItemDetail exposing (ItemDetail)
|
||||
import Api.Model.ItemProposals exposing (ItemProposals)
|
||||
@ -71,6 +73,7 @@ type alias Model =
|
||||
, corrPersonModel : Comp.Dropdown.Model IdName
|
||||
, concPersonModel : Comp.Dropdown.Model IdName
|
||||
, concEquipModel : Comp.Dropdown.Model IdName
|
||||
, folderModel : Comp.Dropdown.Model IdName
|
||||
, nameModel : String
|
||||
, notesModel : Maybe String
|
||||
, notesField : NotesField
|
||||
@ -165,6 +168,11 @@ emptyModel =
|
||||
{ makeOption = \e -> { value = e.id, text = e.name }
|
||||
, placeholder = ""
|
||||
}
|
||||
, folderModel =
|
||||
Comp.Dropdown.makeSingle
|
||||
{ makeOption = \e -> { value = e.id, text = e.name }
|
||||
, placeholder = ""
|
||||
}
|
||||
, nameModel = ""
|
||||
, notesModel = Nothing
|
||||
, notesField = ViewNotes
|
||||
@ -268,6 +276,8 @@ type Msg
|
||||
| EditAttachNameSet String
|
||||
| EditAttachNameSubmit
|
||||
| EditAttachNameResp (Result Http.Error BasicResult)
|
||||
| GetFolderResp (Result Http.Error FolderList)
|
||||
| FolderDropdownMsg (Comp.Dropdown.Msg IdName)
|
||||
|
||||
|
||||
|
||||
@ -281,6 +291,7 @@ getOptions flags =
|
||||
, Api.getOrgLight flags GetOrgResp
|
||||
, Api.getPersonsLight flags GetPersonResp
|
||||
, Api.getEquipments flags "" GetEquipResp
|
||||
, Api.getFolders flags "" False GetFolderResp
|
||||
]
|
||||
|
||||
|
||||
@ -310,6 +321,16 @@ setDirection flags model =
|
||||
Cmd.none
|
||||
|
||||
|
||||
setFolder : Flags -> Model -> Maybe IdName -> Cmd Msg
|
||||
setFolder flags model mref =
|
||||
let
|
||||
idref =
|
||||
Maybe.map .id mref
|
||||
|> OptionalId
|
||||
in
|
||||
Api.setFolder flags model.item.id idref SaveResp
|
||||
|
||||
|
||||
setCorrOrg : Flags -> Model -> Maybe IdName -> Cmd Msg
|
||||
setCorrOrg flags model mref =
|
||||
let
|
||||
@ -523,6 +544,20 @@ update key flags next msg model =
|
||||
( m7, c7, s7 ) =
|
||||
update key flags next AddFilesReset m6
|
||||
|
||||
( m8, c8, s8 ) =
|
||||
update key
|
||||
flags
|
||||
next
|
||||
(FolderDropdownMsg
|
||||
(Comp.Dropdown.SetSelection
|
||||
(item.folder
|
||||
|> Maybe.map List.singleton
|
||||
|> Maybe.withDefault []
|
||||
)
|
||||
)
|
||||
)
|
||||
m7
|
||||
|
||||
proposalCmd =
|
||||
if item.state == "created" then
|
||||
Api.getItemProposals flags item.id GetProposalResp
|
||||
@ -530,7 +565,7 @@ update key flags next msg model =
|
||||
else
|
||||
Cmd.none
|
||||
in
|
||||
( { m7
|
||||
( { m8
|
||||
| item = item
|
||||
, nameModel = item.name
|
||||
, notesModel = item.notes
|
||||
@ -548,11 +583,12 @@ update key flags next msg model =
|
||||
, c5
|
||||
, c6
|
||||
, c7
|
||||
, c8
|
||||
, getOptions flags
|
||||
, proposalCmd
|
||||
, Api.getSentMails flags item.id SentMailsResp
|
||||
]
|
||||
, Sub.batch [ s1, s2, s3, s4, s5, s6, s7 ]
|
||||
, Sub.batch [ s1, s2, s3, s4, s5, s6, s7, s8 ]
|
||||
)
|
||||
|
||||
SetActiveAttachment pos ->
|
||||
@ -575,6 +611,26 @@ update key flags next msg model =
|
||||
else
|
||||
noSub ( model, Api.itemDetail flags model.item.id GetItemResp )
|
||||
|
||||
FolderDropdownMsg m ->
|
||||
let
|
||||
( m2, c2 ) =
|
||||
Comp.Dropdown.update m model.folderModel
|
||||
|
||||
newModel =
|
||||
{ model | folderModel = m2 }
|
||||
|
||||
idref =
|
||||
Comp.Dropdown.getSelected m2 |> List.head
|
||||
|
||||
save =
|
||||
if isDropdownChangeMsg m then
|
||||
setFolder flags newModel idref
|
||||
|
||||
else
|
||||
Cmd.none
|
||||
in
|
||||
noSub ( newModel, Cmd.batch [ save, Cmd.map FolderDropdownMsg c2 ] )
|
||||
|
||||
TagDropdownMsg m ->
|
||||
let
|
||||
( m2, c2 ) =
|
||||
@ -827,6 +883,18 @@ update key flags next msg model =
|
||||
SetDueDateSuggestion date ->
|
||||
noSub ( model, setDueDate flags model (Just date) )
|
||||
|
||||
GetFolderResp (Ok fs) ->
|
||||
let
|
||||
opts =
|
||||
fs.items
|
||||
|> List.map (\e -> IdName e.id e.name)
|
||||
|> Comp.Dropdown.SetOptions
|
||||
in
|
||||
update key flags next (FolderDropdownMsg opts) model
|
||||
|
||||
GetFolderResp (Err _) ->
|
||||
noSub ( model, Cmd.none )
|
||||
|
||||
GetTagsResp (Ok tags) ->
|
||||
let
|
||||
tagList =
|
||||
@ -2082,6 +2150,13 @@ renderEditForm settings model =
|
||||
]
|
||||
]
|
||||
]
|
||||
, div [ class "field" ]
|
||||
[ label []
|
||||
[ Icons.folderIcon "grey"
|
||||
, text "Folder"
|
||||
]
|
||||
, Html.map FolderDropdownMsg (Comp.Dropdown.view settings model.folderModel)
|
||||
]
|
||||
, div [ class "field" ]
|
||||
[ label []
|
||||
[ Icons.directionIcon "grey"
|
||||
|
Loading…
Reference in New Issue
Block a user