diff --git a/modules/backend/src/main/scala/docspell/backend/item/Merge.scala b/modules/backend/src/main/scala/docspell/backend/item/Merge.scala index 12d27a28..54a280d7 100644 --- a/modules/backend/src/main/scala/docspell/backend/item/Merge.scala +++ b/modules/backend/src/main/scala/docspell/backend/item/Merge.scala @@ -81,11 +81,12 @@ object Merge { def moveAttachments(items: NonEmptyList[Ident]): F[Int] = { val target = items.head for { + nextPos <- store.transact(RAttachment.nextPosition(target)) attachs <- store.transact(items.tail.traverse(id => RAttachment.findByItem(id))) attachFlat = attachs.flatMap(_.toList) - n <- attachFlat.traverse(a => - store.transact(RAttachment.updateItemId(a.id, target)) - ) + n <- attachFlat.zipWithIndex.traverse({ case (a, idx) => + store.transact(RAttachment.updateItemId(a.id, target, nextPos + idx)) + }) } yield n.sum } diff --git a/modules/store/src/main/scala/docspell/store/records/RAttachment.scala b/modules/store/src/main/scala/docspell/store/records/RAttachment.scala index f08ff74f..061bb7b7 100644 --- a/modules/store/src/main/scala/docspell/store/records/RAttachment.scala +++ b/modules/store/src/main/scala/docspell/store/records/RAttachment.scala @@ -69,9 +69,9 @@ object RAttachment { DML.set(T.position.increment(1)) ) - def nextPosition(id: Ident): ConnectionIO[Int] = + def nextPosition(itemId: Ident): ConnectionIO[Int] = 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]] .unique } yield max.map(_ + 1).getOrElse(0) @@ -97,8 +97,15 @@ object RAttachment { DML.set(T.fileId.setTo(fId)) ) - def updateItemId(attachId: Ident, itemId: Ident): ConnectionIO[Int] = - DML.update(T, T.id === attachId, DML.set(T.itemId.setTo(itemId))) + def updateItemId(attachId: Ident, itemId: Ident, pos: Int): ConnectionIO[Int] = + DML.update( + T, + T.id === attachId, + DML.set( + T.itemId.setTo(itemId), + T.position.setTo(pos) + ) + ) def updatePosition(attachId: Ident, pos: Int): ConnectionIO[Int] = DML.update(T, T.id === attachId, DML.set(T.position.setTo(pos))) diff --git a/modules/webapp/src/main/elm/Comp/ItemMerge.elm b/modules/webapp/src/main/elm/Comp/ItemMerge.elm index 6bdc6ea4..e59e4513 100644 --- a/modules/webapp/src/main/elm/Comp/ItemMerge.elm +++ b/modules/webapp/src/main/elm/Comp/ItemMerge.elm @@ -126,6 +126,8 @@ type Msg | SubmitMerge | CancelMerge | MergeResp (Result Http.Error BasicResult) + | RemoveItem String + | MoveItem Int Int update : Flags -> Msg -> Model -> UpdateResult @@ -184,6 +186,23 @@ update flags msg model = Nothing -> 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 -> let ids = @@ -295,16 +314,17 @@ itemCard texts settings model index item = currentDrop == Just index && currentDrag /= Just index && currentDrag /= Just (index - 1) in div - ([ classList [ ( "pt-12 mx-2", dropActive ) ] - ] - ++ droppable DragDrop index + (classList + [ ( "pt-12 mx-2", dropActive ) + ] + :: droppable DragDrop index ) [ div ([ class "flex flex-col sm:flex-row rounded" , class "cursor-pointer items-center" , classList - [ ( "border-2 border-blue-500 dark:border-blue-500", index == 0 ) - , ( "bg-blue-100 dark:bg-lightblue-900", index == 0 ) + [ ( "border-2 border-blue-500 dark:border-blue-500", index == 0 && not dropActive ) + , ( "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 ) , ( "bg-yellow-50 dark:bg-lime-900 mt-4", dropActive ) ] @@ -312,20 +332,22 @@ itemCard texts settings model index item = ] ++ draggable DragDrop index ) - [ div - [ class "mr-2 sm:rounded-l w-16 bg-white" + [ div [ class "hidden sm:block" ] + [ span [ class "px-3" ] + [ i [ class "fa fa-ellipsis-v" ] [] + ] + ] + , div + [ class "mr-2 w-16 bg-white" , classList [ ( "hidden", fieldHidden Data.Fields.PreviewImage ) ] ] [ img - [ class "preview-image mx-auto pt-1" - , classList - [ ( "sm:rounded-l", True ) - ] + [ class "preview-image mx-auto" , 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 "font-bold text-lg" @@ -346,6 +368,41 @@ itemCard texts settings model index item = , mainData texts 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 + } + ] + ] ] ] diff --git a/modules/webapp/src/main/elm/Page/Home/View2.elm b/modules/webapp/src/main/elm/Page/Home/View2.elm index 0bf0711a..6a7a62a5 100644 --- a/modules/webapp/src/main/elm/Page/Home/View2.elm +++ b/modules/webapp/src/main/elm/Page/Home/View2.elm @@ -51,11 +51,7 @@ viewContent texts flags settings model = ] (searchStats texts flags settings model ++ itemsBar texts flags settings model - ++ [ div [ class "sm:relative" ] - (itemMergeView texts settings model - ++ itemCardList texts flags settings model - ) - ] + ++ mainView texts flags settings model ++ confirmModal texts model ) @@ -64,26 +60,37 @@ viewContent texts flags settings model = --- Helpers -itemMergeView : Texts -> UiSettings -> Model -> List (Html Msg) -itemMergeView texts settings model = - case model.viewMode of - SelectView svm -> - case svm.action of - MergeSelected -> - [ div - [ class S.dimmerMerge - , class "mt-10 sm:mt-0" - ] - [ Html.map MergeItemsMsg - (Comp.ItemMerge.view texts.itemMerge settings svm.mergeModel) - ] - ] +mainView : Texts -> Flags -> UiSettings -> Model -> List (Html Msg) +mainView texts flags settings model = + let + mergeView = + case model.viewMode of + SelectView svm -> + case svm.action of + MergeSelected -> + Just svm + + _ -> + 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) diff --git a/modules/webapp/src/main/elm/Styles.elm b/modules/webapp/src/main/elm/Styles.elm index 7191bd27..e92b29fe 100644 --- a/modules/webapp/src/main/elm/Styles.elm +++ b/modules/webapp/src/main/elm/Styles.elm @@ -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 " -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 = "border-collapse table w-full" diff --git a/website/site/content/docs/webapp/merge-02.png b/website/site/content/docs/webapp/merge-02.png index 3c73b89d..3a6b9837 100644 Binary files a/website/site/content/docs/webapp/merge-02.png and b/website/site/content/docs/webapp/merge-02.png differ diff --git a/website/site/content/docs/webapp/merge-03.png b/website/site/content/docs/webapp/merge-03.png deleted file mode 100644 index 477259a6..00000000 Binary files a/website/site/content/docs/webapp/merge-03.png and /dev/null differ diff --git a/website/site/content/docs/webapp/merge.md b/website/site/content/docs/webapp/merge.md index 6a6fee2c..7e394ea0 100644 --- a/website/site/content/docs/webapp/merge.md +++ b/website/site/content/docs/webapp/merge.md @@ -30,9 +30,7 @@ selected items. {{ figure(file="merge-02.png") }} The order of this list can matter when merging (see below). You can -move items via drag and drop: - -{{ figure(file="merge-03.png") }} +move items via drag and drop or the buttons on the right. ## Click merge