From d6d16e39bd61e7c697a6ca14d47143f8d73a3188 Mon Sep 17 00:00:00 2001 From: Eike Kettner Date: Sat, 8 Aug 2020 14:03:36 +0200 Subject: [PATCH] Drag-drop items into folders in list view --- .../webapp/src/main/elm/Comp/FolderSelect.elm | 53 +++++----- .../webapp/src/main/elm/Comp/ItemCardList.elm | 27 ++--- .../webapp/src/main/elm/Comp/SearchMenu.elm | 85 ++++++++-------- .../webapp/src/main/elm/Page/Home/Data.elm | 9 +- .../webapp/src/main/elm/Page/Home/Update.elm | 21 +++- .../webapp/src/main/elm/Util/ItemDragDrop.elm | 98 +++++++++++++++++++ modules/webapp/src/main/webjar/docspell.css | 2 +- 7 files changed, 189 insertions(+), 106 deletions(-) create mode 100644 modules/webapp/src/main/elm/Util/ItemDragDrop.elm diff --git a/modules/webapp/src/main/elm/Comp/FolderSelect.elm b/modules/webapp/src/main/elm/Comp/FolderSelect.elm index a1126041..9ca36a80 100644 --- a/modules/webapp/src/main/elm/Comp/FolderSelect.elm +++ b/modules/webapp/src/main/elm/Comp/FolderSelect.elm @@ -12,8 +12,8 @@ import Api.Model.FolderItem exposing (FolderItem) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) -import Html5.DragDrop as DD import Util.ExpandCollapse +import Util.ItemDragDrop as DD import Util.List @@ -39,7 +39,7 @@ init all = type Msg = Toggle FolderItem | ToggleExpand - | FolderDDMsg (DD.Msg String String) + | FolderDDMsg DD.Msg update : Msg -> Model -> ( Model, Maybe FolderItem ) @@ -52,10 +52,10 @@ update msg model = updateDrop : - DD.Model String String + DD.Model -> Msg -> Model - -> ( Model, Maybe FolderItem, DD.Model String String ) + -> ( Model, Maybe FolderItem, DD.DragDropData ) updateDrop dropModel msg model = case msg of Toggle item -> @@ -70,35 +70,20 @@ updateDrop dropModel msg model = model_ = { model | selected = selection } in - ( model_, selectedFolder model_, dropModel ) + ( model_, selectedFolder model_, DD.DragDropData dropModel Nothing ) ToggleExpand -> ( { model | expanded = not model.expanded } , selectedFolder model - , dropModel + , DD.DragDropData dropModel Nothing ) FolderDDMsg lm -> let - ( dm_, result ) = + ddd = DD.update lm dropModel - - _ = - case result of - Just ( item, folder, _ ) -> - let - _ = - Debug.log "item menu" item - - _ = - Debug.log "folder menu" folder - in - Cmd.none - - Nothing -> - Cmd.none in - ( model, selectedFolder model, dm_ ) + ( model, selectedFolder model, ddd ) selectedFolder : Model -> Maybe FolderItem @@ -119,13 +104,23 @@ view = viewDrop DD.init -viewDrop : DD.Model String String -> Int -> Model -> Html Msg +viewDrop : DD.Model -> Int -> Model -> Html Msg viewDrop dropModel constr model = + let + highlightDrop = + DD.getDropId dropModel == Just DD.FolderRemove + in div [ class "ui list" ] [ div [ class "item" ] [ i [ class "folder open icon" ] [] , div [ class "content" ] - [ div [ class "header" ] + [ div + (classList + [ ( "header", True ) + , ( "current-drop-target", highlightDrop ) + ] + :: DD.droppable FolderDDMsg DD.FolderRemove + ) [ text "Folders" ] , div [ class "ui relaxed list" ] @@ -135,7 +130,7 @@ viewDrop dropModel constr model = ] -renderItems : DD.Model String String -> Int -> Model -> List (Html Msg) +renderItems : DD.Model -> Int -> Model -> List (Html Msg) renderItems dropModel constr model = if constr <= 0 then List.map (viewItem dropModel model) model.all @@ -163,7 +158,7 @@ collapseToggle max model = ToggleExpand -viewItem : DD.Model String String -> Model -> FolderItem -> Html Msg +viewItem : DD.Model -> Model -> FolderItem -> Html Msg viewItem dropModel model item = let selected = @@ -177,7 +172,7 @@ viewItem dropModel model item = "folder outline icon" highlightDrop = - DD.getDropId dropModel == Just item.id + DD.getDropId dropModel == Just (DD.Folder item.id) in a ([ classList @@ -188,7 +183,7 @@ viewItem dropModel model item = , href "#" , onClick (Toggle item) ] - ++ DD.droppable FolderDDMsg item.id + ++ DD.droppable FolderDDMsg (DD.Folder item.id) ) [ i [ class icon ] [] , div [ class "content" ] diff --git a/modules/webapp/src/main/elm/Comp/ItemCardList.elm b/modules/webapp/src/main/elm/Comp/ItemCardList.elm index 3a46c5c0..6f11d8a4 100644 --- a/modules/webapp/src/main/elm/Comp/ItemCardList.elm +++ b/modules/webapp/src/main/elm/Comp/ItemCardList.elm @@ -21,8 +21,8 @@ import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) -import Html5.DragDrop as DD import Markdown +import Util.ItemDragDrop as DD import Util.List import Util.String import Util.Time @@ -37,7 +37,7 @@ type Msg = SetResults ItemLightList | AddResults ItemLightList | SelectItem ItemLight - | ItemDDMsg (DD.Msg String String) + | ItemDDMsg DD.Msg init : Model @@ -75,12 +75,12 @@ type alias UpdateResult = { model : Model , cmd : Cmd Msg , selected : Maybe ItemLight - , dragModel : DD.Model String String + , dragModel : DD.Model } updateDrag : - DD.Model String String + DD.Model -> Flags -> Msg -> Model @@ -110,25 +110,10 @@ updateDrag dm _ msg model = ItemDDMsg lm -> let - ( dm_, result ) = + ddd = DD.update lm dm - - _ = - case result of - Just ( item, folder, _ ) -> - let - _ = - Debug.log "item card" item - - _ = - Debug.log "folder card" folder - in - Cmd.none - - Nothing -> - Cmd.none in - UpdateResult model Cmd.none Nothing dm_ + UpdateResult model Cmd.none Nothing ddd.model diff --git a/modules/webapp/src/main/elm/Comp/SearchMenu.elm b/modules/webapp/src/main/elm/Comp/SearchMenu.elm index a5a6ddb6..fb7aeb67 100644 --- a/modules/webapp/src/main/elm/Comp/SearchMenu.elm +++ b/modules/webapp/src/main/elm/Comp/SearchMenu.elm @@ -1,6 +1,5 @@ module Comp.SearchMenu exposing - ( DragDropData - , Model + ( Model , Msg(..) , NextState , getItemSearch @@ -32,11 +31,10 @@ import DatePicker exposing (DatePicker) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onCheck, onClick, onInput) -import Html5.DragDrop as DD import Http import Util.Html exposing (KeyCode(..)) +import Util.ItemDragDrop as DD import Util.Maybe -import Util.Update @@ -222,26 +220,21 @@ type Msg | GetFolderResp (Result Http.Error FolderList) -type alias DragDropData = - { folderDrop : DD.Model String String - } - - type alias NextState = { model : Model , cmd : Cmd Msg , stateChange : Bool - , dragDrop : DragDropData + , dragDrop : DD.DragDropData } update : Flags -> UiSettings -> Msg -> Model -> NextState update = - updateDrop (DragDropData DD.init) + updateDrop DD.init -updateDrop : DragDropData -> Flags -> UiSettings -> Msg -> Model -> NextState -updateDrop dd flags settings msg model = +updateDrop : DD.Model -> Flags -> UiSettings -> Msg -> Model -> NextState +updateDrop ddm flags settings msg model = case msg of Init -> let @@ -279,7 +272,7 @@ updateDrop dd flags settings msg model = , cdp ] , stateChange = False - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } ResetForm -> @@ -302,14 +295,14 @@ updateDrop dd flags settings msg model = { model = model_ , cmd = Cmd.none , stateChange = False - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } GetTagsResp (Err _) -> { model = model , cmd = Cmd.none , stateChange = False - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } GetEquipResp (Ok equips) -> @@ -323,7 +316,7 @@ updateDrop dd flags settings msg model = { model = model , cmd = Cmd.none , stateChange = False - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } GetOrgResp (Ok orgs) -> @@ -337,7 +330,7 @@ updateDrop dd flags settings msg model = { model = model , cmd = Cmd.none , stateChange = False - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } GetPersonResp (Ok ps) -> @@ -346,10 +339,10 @@ updateDrop dd flags settings msg model = Comp.Dropdown.SetOptions ps.items next1 = - updateDrop dd flags settings (CorrPersonMsg opts) model + updateDrop ddm flags settings (CorrPersonMsg opts) model next2 = - updateDrop next1.dragDrop flags settings (ConcPersonMsg opts) next1.model + updateDrop next1.dragDrop.model flags settings (ConcPersonMsg opts) next1.model in next2 @@ -357,7 +350,7 @@ updateDrop dd flags settings msg model = { model = model , cmd = Cmd.none , stateChange = False - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } TagSelectMsg m -> @@ -372,7 +365,7 @@ updateDrop dd flags settings msg model = } , cmd = Cmd.none , stateChange = sel /= model.tagSelection - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } DirectionMsg m -> @@ -383,7 +376,7 @@ updateDrop dd flags settings msg model = { model = { model | directionModel = m2 } , cmd = Cmd.map DirectionMsg c2 , stateChange = isDropdownChangeMsg m - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } OrgMsg m -> @@ -394,7 +387,7 @@ updateDrop dd flags settings msg model = { model = { model | orgModel = m2 } , cmd = Cmd.map OrgMsg c2 , stateChange = isDropdownChangeMsg m - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } CorrPersonMsg m -> @@ -405,7 +398,7 @@ updateDrop dd flags settings msg model = { model = { model | corrPersonModel = m2 } , cmd = Cmd.map CorrPersonMsg c2 , stateChange = isDropdownChangeMsg m - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } ConcPersonMsg m -> @@ -416,7 +409,7 @@ updateDrop dd flags settings msg model = { model = { model | concPersonModel = m2 } , cmd = Cmd.map ConcPersonMsg c2 , stateChange = isDropdownChangeMsg m - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } ConcEquipmentMsg m -> @@ -427,7 +420,7 @@ updateDrop dd flags settings msg model = { model = { model | concEquipmentModel = m2 } , cmd = Cmd.map ConcEquipmentMsg c2 , stateChange = isDropdownChangeMsg m - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } ToggleInbox -> @@ -438,7 +431,7 @@ updateDrop dd flags settings msg model = { model = { model | inboxCheckbox = not current } , cmd = Cmd.none , stateChange = True - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } FromDateMsg m -> @@ -457,7 +450,7 @@ updateDrop dd flags settings msg model = { model = { model | fromDateModel = dp, fromDate = nextDate } , cmd = Cmd.none , stateChange = model.fromDate /= nextDate - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } UntilDateMsg m -> @@ -476,7 +469,7 @@ updateDrop dd flags settings msg model = { model = { model | untilDateModel = dp, untilDate = nextDate } , cmd = Cmd.none , stateChange = model.untilDate /= nextDate - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } FromDueDateMsg m -> @@ -495,7 +488,7 @@ updateDrop dd flags settings msg model = { model = { model | fromDueDateModel = dp, fromDueDate = nextDate } , cmd = Cmd.none , stateChange = model.fromDueDate /= nextDate - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } UntilDueDateMsg m -> @@ -514,7 +507,7 @@ updateDrop dd flags settings msg model = { model = { model | untilDueDateModel = dp, untilDueDate = nextDate } , cmd = Cmd.none , stateChange = model.untilDueDate /= nextDate - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } SetName str -> @@ -525,7 +518,7 @@ updateDrop dd flags settings msg model = { model = { model | nameModel = next } , cmd = Cmd.none , stateChange = False - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } SetAllName str -> @@ -536,7 +529,7 @@ updateDrop dd flags settings msg model = { model = { model | allNameModel = next } , cmd = Cmd.none , stateChange = False - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } SetFulltext str -> @@ -547,28 +540,28 @@ updateDrop dd flags settings msg model = { model = { model | fulltextModel = next } , cmd = Cmd.none , stateChange = False - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } KeyUpMsg (Just Enter) -> { model = model , cmd = Cmd.none , stateChange = True - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } KeyUpMsg _ -> { model = model , cmd = Cmd.none , stateChange = False - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } ToggleNameHelp -> { model = { model | showNameHelp = not model.showNameHelp } , cmd = Cmd.none , stateChange = False - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } GetFolderResp (Ok fs) -> @@ -579,20 +572,20 @@ updateDrop dd flags settings msg model = { model = model_ , cmd = Cmd.none , stateChange = False - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } GetFolderResp (Err _) -> { model = model , cmd = Cmd.none , stateChange = False - , dragDrop = dd + , dragDrop = DD.DragDropData ddm Nothing } FolderSelectMsg lm -> let - ( fsm, sel, dd_ ) = - Comp.FolderSelect.updateDrop dd.folderDrop lm model.folderList + ( fsm, sel, ddd ) = + Comp.FolderSelect.updateDrop ddm lm model.folderList in { model = { model @@ -601,7 +594,7 @@ updateDrop dd flags settings msg model = } , cmd = Cmd.none , stateChange = model.selectedFolder /= sel - , dragDrop = { dd | folderDrop = dd_ } + , dragDrop = ddd } @@ -611,10 +604,10 @@ updateDrop dd flags settings msg model = view : Flags -> UiSettings -> Model -> Html Msg view = - viewDrop (DragDropData DD.init) + viewDrop (DD.DragDropData DD.init Nothing) -viewDrop : DragDropData -> Flags -> UiSettings -> Model -> Html Msg +viewDrop : DD.DragDropData -> Flags -> UiSettings -> Model -> Html Msg viewDrop ddd flags settings model = let formHeader icon headline = @@ -648,7 +641,7 @@ viewDrop ddd flags settings model = [ Html.map TagSelectMsg (Comp.TagSelect.viewTags settings model.tagSelectModel) , Html.map TagSelectMsg (Comp.TagSelect.viewCats settings model.tagSelectModel) , Html.map FolderSelectMsg - (Comp.FolderSelect.viewDrop ddd.folderDrop settings.searchMenuFolderCount model.folderList) + (Comp.FolderSelect.viewDrop ddd.model settings.searchMenuFolderCount model.folderList) ] , div [ class segmentClass ] [ formHeader (Icons.correspondentIcon "") diff --git a/modules/webapp/src/main/elm/Page/Home/Data.elm b/modules/webapp/src/main/elm/Page/Home/Data.elm index f492d04b..b8661b96 100644 --- a/modules/webapp/src/main/elm/Page/Home/Data.elm +++ b/modules/webapp/src/main/elm/Page/Home/Data.elm @@ -16,14 +16,14 @@ import Api.Model.ItemLightList exposing (ItemLightList) import Api.Model.ItemSearch import Comp.FixedDropdown import Comp.ItemCardList -import Comp.SearchMenu exposing (DragDropData) +import Comp.SearchMenu import Data.Flags exposing (Flags) import Data.Items import Data.UiSettings exposing (UiSettings) -import Html5.DragDrop as DD import Http import Throttle exposing (Throttle) import Util.Html exposing (KeyCode(..)) +import Util.ItemDragDrop as DD type alias Model = @@ -40,7 +40,7 @@ type alias Model = , searchType : SearchType , searchTypeForm : SearchType , contentOnlySearch : Maybe String - , dragDropData : DragDropData + , dragDropData : DD.DragDropData } @@ -70,8 +70,7 @@ init flags = , searchTypeForm = defaultSearchType flags , contentOnlySearch = Nothing , dragDropData = - { folderDrop = DD.init - } + DD.DragDropData DD.init Nothing } diff --git a/modules/webapp/src/main/elm/Page/Home/Update.elm b/modules/webapp/src/main/elm/Page/Home/Update.elm index 93c44afb..b424abb0 100644 --- a/modules/webapp/src/main/elm/Page/Home/Update.elm +++ b/modules/webapp/src/main/elm/Page/Home/Update.elm @@ -6,12 +6,12 @@ import Comp.ItemCardList import Comp.SearchMenu import Data.Flags exposing (Flags) import Data.UiSettings exposing (UiSettings) -import Html5.DragDrop as DD import Page exposing (Page(..)) import Page.Home.Data exposing (..) import Throttle import Time import Util.Html exposing (KeyCode(..)) +import Util.ItemDragDrop as DD import Util.Maybe import Util.String import Util.Update @@ -41,12 +41,24 @@ update key flags settings msg model = let nextState = Comp.SearchMenu.updateDrop - model.dragDropData + model.dragDropData.model flags settings m model.searchMenuModel + dropCmd = + case nextState.dragDrop.dropped of + Just dropped -> + let + _ = + Debug.log "item/folder" dropped + in + DD.makeUpdateCmd flags (\_ -> DoSearch) nextState.dragDrop.dropped + + Nothing -> + Cmd.none + newModel = { model | searchMenuModel = nextState.model @@ -64,6 +76,7 @@ update key flags settings msg model = , Cmd.batch [ c2 , Cmd.map SearchMenuMsg nextState.cmd + , dropCmd ] , s2 ) @@ -71,7 +84,7 @@ update key flags settings msg model = ItemCardListMsg m -> let result = - Comp.ItemCardList.updateDrag model.dragDropData.folderDrop + Comp.ItemCardList.updateDrag model.dragDropData.model flags m model.itemListModel @@ -87,7 +100,7 @@ update key flags settings msg model = withSub ( { model | itemListModel = result.model - , dragDropData = { folderDrop = result.dragModel } + , dragDropData = DD.DragDropData result.dragModel Nothing } , Cmd.batch [ Cmd.map ItemCardListMsg result.cmd, cmd ] ) diff --git a/modules/webapp/src/main/elm/Util/ItemDragDrop.elm b/modules/webapp/src/main/elm/Util/ItemDragDrop.elm new file mode 100644 index 00000000..31fa704b --- /dev/null +++ b/modules/webapp/src/main/elm/Util/ItemDragDrop.elm @@ -0,0 +1,98 @@ +module Util.ItemDragDrop exposing + ( DragDropData + , Dropped + , ItemDrop(..) + , Model + , Msg + , draggable + , droppable + , getDropId + , init + , makeUpdateCmd + , update + ) + +import Api +import Api.Model.BasicResult exposing (BasicResult) +import Api.Model.OptionalId exposing (OptionalId) +import Data.Flags exposing (Flags) +import Html exposing (Attribute) +import Html5.DragDrop as DD +import Http + + +type ItemDrop + = Tag String + | Folder String + | FolderRemove + + +type alias Model = + DD.Model String ItemDrop + + +type alias Msg = + DD.Msg String ItemDrop + + +type alias Dropped = + { itemId : String + , target : ItemDrop + } + + +type alias DragDropData = + { model : Model + , dropped : Maybe Dropped + } + + +init : Model +init = + DD.init + + +update : Msg -> Model -> DragDropData +update msg model = + let + ( m, res ) = + DD.update msg model + in + DragDropData m (Maybe.map (\( id, t, _ ) -> Dropped id t) res) + + +makeUpdateCmd : + Flags + -> (Result Http.Error BasicResult -> msg) + -> Maybe Dropped + -> Cmd msg +makeUpdateCmd flags receive droppedMaybe = + case droppedMaybe of + Just dropped -> + case dropped.target of + Folder fid -> + Api.setFolder flags dropped.itemId (OptionalId (Just fid)) receive + + FolderRemove -> + Api.setFolder flags dropped.itemId (OptionalId Nothing) receive + + Tag _ -> + Cmd.none + + Nothing -> + Cmd.none + + +droppable : (Msg -> msg) -> ItemDrop -> List (Attribute msg) +droppable tagger dropId = + DD.droppable tagger dropId + + +draggable : (Msg -> msg) -> String -> List (Attribute msg) +draggable tagger itemId = + DD.draggable tagger itemId + + +getDropId : Model -> Maybe ItemDrop +getDropId model = + DD.getDropId model diff --git a/modules/webapp/src/main/webjar/docspell.css b/modules/webapp/src/main/webjar/docspell.css index 32e904fd..8ae37e61 100644 --- a/modules/webapp/src/main/webjar/docspell.css +++ b/modules/webapp/src/main/webjar/docspell.css @@ -166,7 +166,7 @@ textarea.markdown-editor { background: rgba(240,248,255,0.4); } -.default-layout .ui.menu .item.current-drop-target, a.item.current-drop-target { +.default-layout .ui.menu .item.current-drop-target, .header.current-drop-target, .item.current-drop-target { background: rgba(0,0,0,0.2); }