mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-04 06:05:59 +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 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 setCorrOrg(item: Ident, org: Option[Ident], collective: Ident): F[AddResult]
|
||||||
|
|
||||||
def addCorrOrg(item: Ident, org: OOrganization.OrgAndContacts): F[AddResult]
|
def addCorrOrg(item: Ident, org: OOrganization.OrgAndContacts): F[AddResult]
|
||||||
@ -131,6 +133,16 @@ object OItem {
|
|||||||
.attempt
|
.attempt
|
||||||
.map(AddResult.fromUpdate)
|
.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] =
|
def setCorrOrg(item: Ident, org: Option[Ident], collective: Ident): F[AddResult] =
|
||||||
store
|
store
|
||||||
.transact(RItem.updateCorrOrg(item, collective, org))
|
.transact(RItem.updateCorrOrg(item, collective, org))
|
||||||
|
@ -1365,6 +1365,31 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/BasicResult"
|
$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:
|
/sec/item/{id}/corrOrg:
|
||||||
put:
|
put:
|
||||||
tags: [ Item ]
|
tags: [ Item ]
|
||||||
@ -3167,6 +3192,8 @@ components:
|
|||||||
$ref: "#/components/schemas/IdName"
|
$ref: "#/components/schemas/IdName"
|
||||||
inReplyTo:
|
inReplyTo:
|
||||||
$ref: "#/components/schemas/IdName"
|
$ref: "#/components/schemas/IdName"
|
||||||
|
folder:
|
||||||
|
$ref: "#/components/schemas/IdName"
|
||||||
dueDate:
|
dueDate:
|
||||||
type: integer
|
type: integer
|
||||||
format: date-time
|
format: date-time
|
||||||
|
@ -85,6 +85,7 @@ trait Conversions {
|
|||||||
data.concPerson.map(p => IdName(p.pid, p.name)),
|
data.concPerson.map(p => IdName(p.pid, p.name)),
|
||||||
data.concEquip.map(e => IdName(e.eid, e.name)),
|
data.concEquip.map(e => IdName(e.eid, e.name)),
|
||||||
data.inReplyTo.map(mkIdName),
|
data.inReplyTo.map(mkIdName),
|
||||||
|
data.folder.map(mkIdName),
|
||||||
data.item.dueDate,
|
data.item.dueDate,
|
||||||
data.item.notes,
|
data.item.notes,
|
||||||
data.attachments.map((mkAttachment(data) _).tupled).toList,
|
data.attachments.map((mkAttachment(data) _).tupled).toList,
|
||||||
|
@ -149,6 +149,13 @@ object ItemRoutes {
|
|||||||
resp <- Ok(Conversions.basicResult(res, "Direction updated"))
|
resp <- Ok(Conversions.basicResult(res, "Direction updated"))
|
||||||
} yield resp
|
} 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" =>
|
case req @ PUT -> Root / Ident(id) / "corrOrg" =>
|
||||||
for {
|
for {
|
||||||
idref <- req.as[OptionalId]
|
idref <- req.as[OptionalId]
|
||||||
|
@ -66,6 +66,7 @@ object QItem {
|
|||||||
concPerson: Option[RPerson],
|
concPerson: Option[RPerson],
|
||||||
concEquip: Option[REquipment],
|
concEquip: Option[REquipment],
|
||||||
inReplyTo: Option[IdRef],
|
inReplyTo: Option[IdRef],
|
||||||
|
folder: Option[IdRef],
|
||||||
tags: Vector[RTag],
|
tags: Vector[RTag],
|
||||||
attachments: Vector[(RAttachment, FileMeta)],
|
attachments: Vector[(RAttachment, FileMeta)],
|
||||||
sources: Vector[(RAttachmentSource, FileMeta)],
|
sources: Vector[(RAttachmentSource, FileMeta)],
|
||||||
@ -83,10 +84,11 @@ object QItem {
|
|||||||
val P1C = RPerson.Columns.all.map(_.prefix("p1"))
|
val P1C = RPerson.Columns.all.map(_.prefix("p1"))
|
||||||
val EC = REquipment.Columns.all.map(_.prefix("e"))
|
val EC = REquipment.Columns.all.map(_.prefix("e"))
|
||||||
val ICC = List(RItem.Columns.id, RItem.Columns.name).map(_.prefix("ref"))
|
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 =
|
val cq =
|
||||||
selectSimple(
|
selectSimple(
|
||||||
IC ++ OC ++ P0C ++ P1C ++ EC ++ ICC,
|
IC ++ OC ++ P0C ++ P1C ++ EC ++ ICC ++ FC,
|
||||||
RItem.table ++ fr"i",
|
RItem.table ++ fr"i",
|
||||||
Fragment.empty
|
Fragment.empty
|
||||||
) ++
|
) ++
|
||||||
@ -105,6 +107,9 @@ object QItem {
|
|||||||
fr"LEFT JOIN" ++ RItem.table ++ fr"ref ON" ++ RItem.Columns.inReplyTo
|
fr"LEFT JOIN" ++ RItem.table ++ fr"ref ON" ++ RItem.Columns.inReplyTo
|
||||||
.prefix("i")
|
.prefix("i")
|
||||||
.is(RItem.Columns.id.prefix("ref")) ++
|
.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)
|
fr"WHERE" ++ RItem.Columns.id.prefix("i").is(id)
|
||||||
|
|
||||||
val q = cq
|
val q = cq
|
||||||
@ -115,6 +120,7 @@ object QItem {
|
|||||||
Option[RPerson],
|
Option[RPerson],
|
||||||
Option[RPerson],
|
Option[RPerson],
|
||||||
Option[REquipment],
|
Option[REquipment],
|
||||||
|
Option[IdRef],
|
||||||
Option[IdRef]
|
Option[IdRef]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
@ -132,7 +138,7 @@ object QItem {
|
|||||||
arch <- archives
|
arch <- archives
|
||||||
ts <- tags
|
ts <- tags
|
||||||
} yield data.map(d =>
|
} 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 created = Column("created")
|
||||||
val updated = Column("updated")
|
val updated = Column("updated")
|
||||||
val notes = Column("notes")
|
val notes = Column("notes")
|
||||||
val folder = Column("folder_id")
|
val folder = Column("folder_id")
|
||||||
val all = List(
|
val all = List(
|
||||||
id,
|
id,
|
||||||
cid,
|
cid,
|
||||||
@ -243,7 +243,17 @@ object RItem {
|
|||||||
n <- updateRow(
|
n <- updateRow(
|
||||||
table,
|
table,
|
||||||
and(cid.is(coll), concEquipment.is(Some(currentEquip))),
|
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
|
).update.run
|
||||||
} yield n
|
} yield n
|
||||||
|
|
||||||
|
@ -77,6 +77,7 @@ module Api exposing
|
|||||||
, setCorrOrg
|
, setCorrOrg
|
||||||
, setCorrPerson
|
, setCorrPerson
|
||||||
, setDirection
|
, setDirection
|
||||||
|
, setFolder
|
||||||
, setItemDate
|
, setItemDate
|
||||||
, setItemDueDate
|
, setItemDueDate
|
||||||
, setItemName
|
, 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 -> String -> OptionalId -> (Result Http.Error BasicResult -> msg) -> Cmd msg
|
||||||
setCorrOrg flags item id receive =
|
setCorrOrg flags item id receive =
|
||||||
Http2.authPut
|
Http2.authPut
|
||||||
|
@ -11,6 +11,8 @@ import Api.Model.Attachment exposing (Attachment)
|
|||||||
import Api.Model.BasicResult exposing (BasicResult)
|
import Api.Model.BasicResult exposing (BasicResult)
|
||||||
import Api.Model.DirectionValue exposing (DirectionValue)
|
import Api.Model.DirectionValue exposing (DirectionValue)
|
||||||
import Api.Model.EquipmentList exposing (EquipmentList)
|
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.IdName exposing (IdName)
|
||||||
import Api.Model.ItemDetail exposing (ItemDetail)
|
import Api.Model.ItemDetail exposing (ItemDetail)
|
||||||
import Api.Model.ItemProposals exposing (ItemProposals)
|
import Api.Model.ItemProposals exposing (ItemProposals)
|
||||||
@ -71,6 +73,7 @@ type alias Model =
|
|||||||
, corrPersonModel : Comp.Dropdown.Model IdName
|
, corrPersonModel : Comp.Dropdown.Model IdName
|
||||||
, concPersonModel : Comp.Dropdown.Model IdName
|
, concPersonModel : Comp.Dropdown.Model IdName
|
||||||
, concEquipModel : Comp.Dropdown.Model IdName
|
, concEquipModel : Comp.Dropdown.Model IdName
|
||||||
|
, folderModel : Comp.Dropdown.Model IdName
|
||||||
, nameModel : String
|
, nameModel : String
|
||||||
, notesModel : Maybe String
|
, notesModel : Maybe String
|
||||||
, notesField : NotesField
|
, notesField : NotesField
|
||||||
@ -165,6 +168,11 @@ emptyModel =
|
|||||||
{ makeOption = \e -> { value = e.id, text = e.name }
|
{ makeOption = \e -> { value = e.id, text = e.name }
|
||||||
, placeholder = ""
|
, placeholder = ""
|
||||||
}
|
}
|
||||||
|
, folderModel =
|
||||||
|
Comp.Dropdown.makeSingle
|
||||||
|
{ makeOption = \e -> { value = e.id, text = e.name }
|
||||||
|
, placeholder = ""
|
||||||
|
}
|
||||||
, nameModel = ""
|
, nameModel = ""
|
||||||
, notesModel = Nothing
|
, notesModel = Nothing
|
||||||
, notesField = ViewNotes
|
, notesField = ViewNotes
|
||||||
@ -268,6 +276,8 @@ type Msg
|
|||||||
| EditAttachNameSet String
|
| EditAttachNameSet String
|
||||||
| EditAttachNameSubmit
|
| EditAttachNameSubmit
|
||||||
| EditAttachNameResp (Result Http.Error BasicResult)
|
| 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.getOrgLight flags GetOrgResp
|
||||||
, Api.getPersonsLight flags GetPersonResp
|
, Api.getPersonsLight flags GetPersonResp
|
||||||
, Api.getEquipments flags "" GetEquipResp
|
, Api.getEquipments flags "" GetEquipResp
|
||||||
|
, Api.getFolders flags "" False GetFolderResp
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -310,6 +321,16 @@ setDirection flags model =
|
|||||||
Cmd.none
|
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 -> Maybe IdName -> Cmd Msg
|
||||||
setCorrOrg flags model mref =
|
setCorrOrg flags model mref =
|
||||||
let
|
let
|
||||||
@ -523,6 +544,20 @@ update key flags next msg model =
|
|||||||
( m7, c7, s7 ) =
|
( m7, c7, s7 ) =
|
||||||
update key flags next AddFilesReset m6
|
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 =
|
proposalCmd =
|
||||||
if item.state == "created" then
|
if item.state == "created" then
|
||||||
Api.getItemProposals flags item.id GetProposalResp
|
Api.getItemProposals flags item.id GetProposalResp
|
||||||
@ -530,7 +565,7 @@ update key flags next msg model =
|
|||||||
else
|
else
|
||||||
Cmd.none
|
Cmd.none
|
||||||
in
|
in
|
||||||
( { m7
|
( { m8
|
||||||
| item = item
|
| item = item
|
||||||
, nameModel = item.name
|
, nameModel = item.name
|
||||||
, notesModel = item.notes
|
, notesModel = item.notes
|
||||||
@ -548,11 +583,12 @@ update key flags next msg model =
|
|||||||
, c5
|
, c5
|
||||||
, c6
|
, c6
|
||||||
, c7
|
, c7
|
||||||
|
, c8
|
||||||
, getOptions flags
|
, getOptions flags
|
||||||
, proposalCmd
|
, proposalCmd
|
||||||
, Api.getSentMails flags item.id SentMailsResp
|
, 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 ->
|
SetActiveAttachment pos ->
|
||||||
@ -575,6 +611,26 @@ update key flags next msg model =
|
|||||||
else
|
else
|
||||||
noSub ( model, Api.itemDetail flags model.item.id GetItemResp )
|
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 ->
|
TagDropdownMsg m ->
|
||||||
let
|
let
|
||||||
( m2, c2 ) =
|
( m2, c2 ) =
|
||||||
@ -827,6 +883,18 @@ update key flags next msg model =
|
|||||||
SetDueDateSuggestion date ->
|
SetDueDateSuggestion date ->
|
||||||
noSub ( model, setDueDate flags model (Just 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) ->
|
GetTagsResp (Ok tags) ->
|
||||||
let
|
let
|
||||||
tagList =
|
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" ]
|
, div [ class "field" ]
|
||||||
[ label []
|
[ label []
|
||||||
[ Icons.directionIcon "grey"
|
[ Icons.directionIcon "grey"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user