mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-06 07:05:59 +00:00
Merge pull request #1012 from eikek/fixup/414-merge-items
Fixup/414 merge items
This commit is contained in:
commit
7f6bb6994d
@ -81,11 +81,12 @@ object Merge {
|
|||||||
def moveAttachments(items: NonEmptyList[Ident]): F[Int] = {
|
def moveAttachments(items: NonEmptyList[Ident]): F[Int] = {
|
||||||
val target = items.head
|
val target = items.head
|
||||||
for {
|
for {
|
||||||
|
nextPos <- store.transact(RAttachment.nextPosition(target))
|
||||||
attachs <- store.transact(items.tail.traverse(id => RAttachment.findByItem(id)))
|
attachs <- store.transact(items.tail.traverse(id => RAttachment.findByItem(id)))
|
||||||
attachFlat = attachs.flatMap(_.toList)
|
attachFlat = attachs.flatMap(_.toList)
|
||||||
n <- attachFlat.traverse(a =>
|
n <- attachFlat.zipWithIndex.traverse({ case (a, idx) =>
|
||||||
store.transact(RAttachment.updateItemId(a.id, target))
|
store.transact(RAttachment.updateItemId(a.id, target, nextPos + idx))
|
||||||
)
|
})
|
||||||
} yield n.sum
|
} yield n.sum
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,9 +69,9 @@ object RAttachment {
|
|||||||
DML.set(T.position.increment(1))
|
DML.set(T.position.increment(1))
|
||||||
)
|
)
|
||||||
|
|
||||||
def nextPosition(id: Ident): ConnectionIO[Int] =
|
def nextPosition(itemId: Ident): ConnectionIO[Int] =
|
||||||
for {
|
for {
|
||||||
max <- Select(max(T.position).s, from(T), T.itemId === id).build
|
max <- Select(max(T.position).s, from(T), T.itemId === itemId).build
|
||||||
.query[Option[Int]]
|
.query[Option[Int]]
|
||||||
.unique
|
.unique
|
||||||
} yield max.map(_ + 1).getOrElse(0)
|
} yield max.map(_ + 1).getOrElse(0)
|
||||||
@ -97,8 +97,15 @@ object RAttachment {
|
|||||||
DML.set(T.fileId.setTo(fId))
|
DML.set(T.fileId.setTo(fId))
|
||||||
)
|
)
|
||||||
|
|
||||||
def updateItemId(attachId: Ident, itemId: Ident): ConnectionIO[Int] =
|
def updateItemId(attachId: Ident, itemId: Ident, pos: Int): ConnectionIO[Int] =
|
||||||
DML.update(T, T.id === attachId, DML.set(T.itemId.setTo(itemId)))
|
DML.update(
|
||||||
|
T,
|
||||||
|
T.id === attachId,
|
||||||
|
DML.set(
|
||||||
|
T.itemId.setTo(itemId),
|
||||||
|
T.position.setTo(pos)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def updatePosition(attachId: Ident, pos: Int): ConnectionIO[Int] =
|
def updatePosition(attachId: Ident, pos: Int): ConnectionIO[Int] =
|
||||||
DML.update(T, T.id === attachId, DML.set(T.position.setTo(pos)))
|
DML.update(T, T.id === attachId, DML.set(T.position.setTo(pos)))
|
||||||
|
@ -126,6 +126,8 @@ type Msg
|
|||||||
| SubmitMerge
|
| SubmitMerge
|
||||||
| CancelMerge
|
| CancelMerge
|
||||||
| MergeResp (Result Http.Error BasicResult)
|
| MergeResp (Result Http.Error BasicResult)
|
||||||
|
| RemoveItem String
|
||||||
|
| MoveItem Int Int
|
||||||
|
|
||||||
|
|
||||||
update : Flags -> Msg -> Model -> UpdateResult
|
update : Flags -> Msg -> Model -> UpdateResult
|
||||||
@ -184,6 +186,23 @@ update flags msg model =
|
|||||||
Nothing ->
|
Nothing ->
|
||||||
notDoneResult ( model_, Cmd.none )
|
notDoneResult ( model_, Cmd.none )
|
||||||
|
|
||||||
|
RemoveItem id ->
|
||||||
|
let
|
||||||
|
remove item =
|
||||||
|
item.id /= id
|
||||||
|
in
|
||||||
|
notDoneResult
|
||||||
|
( { model | items = List.filter remove model.items }
|
||||||
|
, Cmd.none
|
||||||
|
)
|
||||||
|
|
||||||
|
MoveItem index before ->
|
||||||
|
let
|
||||||
|
items =
|
||||||
|
Util.List.changePosition index before model.items
|
||||||
|
in
|
||||||
|
notDoneResult ( { model | items = items }, Cmd.none )
|
||||||
|
|
||||||
SubmitMerge ->
|
SubmitMerge ->
|
||||||
let
|
let
|
||||||
ids =
|
ids =
|
||||||
@ -295,16 +314,17 @@ itemCard texts settings model index item =
|
|||||||
currentDrop == Just index && currentDrag /= Just index && currentDrag /= Just (index - 1)
|
currentDrop == Just index && currentDrag /= Just index && currentDrag /= Just (index - 1)
|
||||||
in
|
in
|
||||||
div
|
div
|
||||||
([ classList [ ( "pt-12 mx-2", dropActive ) ]
|
(classList
|
||||||
]
|
[ ( "pt-12 mx-2", dropActive )
|
||||||
++ droppable DragDrop index
|
]
|
||||||
|
:: droppable DragDrop index
|
||||||
)
|
)
|
||||||
[ div
|
[ div
|
||||||
([ class "flex flex-col sm:flex-row rounded"
|
([ class "flex flex-col sm:flex-row rounded"
|
||||||
, class "cursor-pointer items-center"
|
, class "cursor-pointer items-center"
|
||||||
, classList
|
, classList
|
||||||
[ ( "border-2 border-blue-500 dark:border-blue-500", index == 0 )
|
[ ( "border-2 border-blue-500 dark:border-blue-500", index == 0 && not dropActive )
|
||||||
, ( "bg-blue-100 dark:bg-lightblue-900", index == 0 )
|
, ( "bg-blue-100 dark:bg-lightblue-900", index == 0 && not dropActive )
|
||||||
, ( "border border-gray-400 dark:border-bluegray-600 dark:hover:border-bluegray-500 bg-white dark:bg-bluegray-700 mt-2", index /= 0 )
|
, ( "border border-gray-400 dark:border-bluegray-600 dark:hover:border-bluegray-500 bg-white dark:bg-bluegray-700 mt-2", index /= 0 )
|
||||||
, ( "bg-yellow-50 dark:bg-lime-900 mt-4", dropActive )
|
, ( "bg-yellow-50 dark:bg-lime-900 mt-4", dropActive )
|
||||||
]
|
]
|
||||||
@ -312,20 +332,22 @@ itemCard texts settings model index item =
|
|||||||
]
|
]
|
||||||
++ draggable DragDrop index
|
++ draggable DragDrop index
|
||||||
)
|
)
|
||||||
[ div
|
[ div [ class "hidden sm:block" ]
|
||||||
[ class "mr-2 sm:rounded-l w-16 bg-white"
|
[ span [ class "px-3" ]
|
||||||
|
[ i [ class "fa fa-ellipsis-v" ] []
|
||||||
|
]
|
||||||
|
]
|
||||||
|
, div
|
||||||
|
[ class "mr-2 w-16 bg-white"
|
||||||
, classList [ ( "hidden", fieldHidden Data.Fields.PreviewImage ) ]
|
, classList [ ( "hidden", fieldHidden Data.Fields.PreviewImage ) ]
|
||||||
]
|
]
|
||||||
[ img
|
[ img
|
||||||
[ class "preview-image mx-auto pt-1"
|
[ class "preview-image mx-auto"
|
||||||
, classList
|
|
||||||
[ ( "sm:rounded-l", True )
|
|
||||||
]
|
|
||||||
, src previewUrl
|
, src previewUrl
|
||||||
]
|
]
|
||||||
[]
|
[]
|
||||||
]
|
]
|
||||||
, div [ class "flex-grow flex flex-col py-1 px-2" ]
|
, div [ class "flex-grow flex flex-col py-1 px-2 h-full" ]
|
||||||
[ div [ class "flex flex-col sm:flex-row items-center" ]
|
[ div [ class "flex flex-col sm:flex-row items-center" ]
|
||||||
[ div
|
[ div
|
||||||
[ class "font-bold text-lg"
|
[ class "font-bold text-lg"
|
||||||
@ -346,6 +368,41 @@ itemCard texts settings model index item =
|
|||||||
, mainData texts settings item
|
, mainData texts settings item
|
||||||
, mainTagsAndFields2 settings item
|
, mainTagsAndFields2 settings item
|
||||||
]
|
]
|
||||||
|
, div [ class "flex flex-row w-full sm:flex-col sm:w-auto items-center border-t sm:border-0 mt-2 sm:mt-0" ]
|
||||||
|
[ div [ class "flex flex-grow justify-center" ]
|
||||||
|
[ Comp.Basic.genericButton
|
||||||
|
{ label = ""
|
||||||
|
, icon = "fa fa-arrow-up"
|
||||||
|
, disabled = index == 0
|
||||||
|
, handler = onClick (MoveItem index (index - 1))
|
||||||
|
, attrs = [ href "#" ]
|
||||||
|
, baseStyle = "py-2 px-4 h-full w-full" ++ S.secondaryBasicButtonMain
|
||||||
|
, activeStyle = S.secondaryBasicButtonHover
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, div [ class "flex flex-grow justify-center" ]
|
||||||
|
[ Comp.Basic.genericButton
|
||||||
|
{ label = ""
|
||||||
|
, icon = "fa fa-times"
|
||||||
|
, disabled = False
|
||||||
|
, handler = onClick (RemoveItem item.id)
|
||||||
|
, attrs = [ href "#" ]
|
||||||
|
, baseStyle = "py-2 px-4 h-full w-full" ++ S.secondaryBasicButtonMain
|
||||||
|
, activeStyle = S.secondaryBasicButtonHover
|
||||||
|
}
|
||||||
|
]
|
||||||
|
, div [ class "flex flex-grow justify-center" ]
|
||||||
|
[ Comp.Basic.genericButton
|
||||||
|
{ label = ""
|
||||||
|
, icon = "fa fa-arrow-down"
|
||||||
|
, disabled = index == List.length model.items - 1
|
||||||
|
, handler = onClick (MoveItem (index + 1) index)
|
||||||
|
, attrs = [ href "#" ]
|
||||||
|
, baseStyle = "py-2 px-4 h-full w-full" ++ S.secondaryBasicButtonMain
|
||||||
|
, activeStyle = S.secondaryBasicButtonHover
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -51,11 +51,7 @@ viewContent texts flags settings model =
|
|||||||
]
|
]
|
||||||
(searchStats texts flags settings model
|
(searchStats texts flags settings model
|
||||||
++ itemsBar texts flags settings model
|
++ itemsBar texts flags settings model
|
||||||
++ [ div [ class "sm:relative" ]
|
++ mainView texts flags settings model
|
||||||
(itemMergeView texts settings model
|
|
||||||
++ itemCardList texts flags settings model
|
|
||||||
)
|
|
||||||
]
|
|
||||||
++ confirmModal texts model
|
++ confirmModal texts model
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -64,26 +60,37 @@ viewContent texts flags settings model =
|
|||||||
--- Helpers
|
--- Helpers
|
||||||
|
|
||||||
|
|
||||||
itemMergeView : Texts -> UiSettings -> Model -> List (Html Msg)
|
mainView : Texts -> Flags -> UiSettings -> Model -> List (Html Msg)
|
||||||
itemMergeView texts settings model =
|
mainView texts flags settings model =
|
||||||
case model.viewMode of
|
let
|
||||||
SelectView svm ->
|
mergeView =
|
||||||
case svm.action of
|
case model.viewMode of
|
||||||
MergeSelected ->
|
SelectView svm ->
|
||||||
[ div
|
case svm.action of
|
||||||
[ class S.dimmerMerge
|
MergeSelected ->
|
||||||
, class "mt-10 sm:mt-0"
|
Just svm
|
||||||
]
|
|
||||||
[ Html.map MergeItemsMsg
|
_ ->
|
||||||
(Comp.ItemMerge.view texts.itemMerge settings svm.mergeModel)
|
Nothing
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
[]
|
Nothing
|
||||||
|
in
|
||||||
|
case mergeView of
|
||||||
|
Just svm ->
|
||||||
|
[ div [ class "sm:relative mb-2" ]
|
||||||
|
(itemMergeView texts settings svm)
|
||||||
|
]
|
||||||
|
|
||||||
_ ->
|
Nothing ->
|
||||||
[]
|
itemCardList texts flags settings model
|
||||||
|
|
||||||
|
|
||||||
|
itemMergeView : Texts -> UiSettings -> SelectViewModel -> List (Html Msg)
|
||||||
|
itemMergeView texts settings svm =
|
||||||
|
[ Html.map MergeItemsMsg
|
||||||
|
(Comp.ItemMerge.view texts.itemMerge settings svm.mergeModel)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
confirmModal : Texts -> Model -> List (Html Msg)
|
confirmModal : Texts -> Model -> List (Html Msg)
|
||||||
|
@ -343,11 +343,6 @@ dimmerCard =
|
|||||||
" absolute top-0 left-0 w-full h-full bg-black bg-opacity-60 dark:bg-lightblue-900 dark:bg-opacity-60 z-30 flex flex-col items-center justify-center px-4 py-2 "
|
" absolute top-0 left-0 w-full h-full bg-black bg-opacity-60 dark:bg-lightblue-900 dark:bg-opacity-60 z-30 flex flex-col items-center justify-center px-4 py-2 "
|
||||||
|
|
||||||
|
|
||||||
dimmerMerge : String
|
|
||||||
dimmerMerge =
|
|
||||||
" absolute top-0 left-0 w-full h-full bg-white bg-opacity-100 dark:bg-bluegray-800 dark:bg-opacity-100 z-40 flex flex-col"
|
|
||||||
|
|
||||||
|
|
||||||
tableMain : String
|
tableMain : String
|
||||||
tableMain =
|
tableMain =
|
||||||
"border-collapse table w-full"
|
"border-collapse table w-full"
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
Binary file not shown.
Before Width: | Height: | Size: 132 KiB |
@ -30,9 +30,7 @@ selected items.
|
|||||||
{{ figure(file="merge-02.png") }}
|
{{ figure(file="merge-02.png") }}
|
||||||
|
|
||||||
The order of this list can matter when merging (see below). You can
|
The order of this list can matter when merging (see below). You can
|
||||||
move items via drag and drop:
|
move items via drag and drop or the buttons on the right.
|
||||||
|
|
||||||
{{ figure(file="merge-03.png") }}
|
|
||||||
|
|
||||||
|
|
||||||
## Click merge
|
## Click merge
|
||||||
|
Loading…
x
Reference in New Issue
Block a user