From 3852c69da1c0f0d19befad79bfa586a6c3923755 Mon Sep 17 00:00:00 2001 From: Eike Kettner Date: Mon, 14 Sep 2020 18:43:04 +0200 Subject: [PATCH] Scroll to the current item when going back from detail The list view now supports an item id that will be scrolled to and is highlighted with a shadow. When going back from detail view this is now used to scroll to the currently viewed item. --- modules/webapp/src/main/elm/App/Data.elm | 2 +- modules/webapp/src/main/elm/App/Update.elm | 12 ++++- modules/webapp/src/main/elm/App/View.elm | 17 +++++-- .../webapp/src/main/elm/Comp/ItemCardList.elm | 17 +++---- .../src/main/elm/Comp/ItemDetail/Update.elm | 2 +- .../src/main/elm/Comp/ItemDetail/View.elm | 2 +- modules/webapp/src/main/elm/Page.elm | 23 +++++++--- .../webapp/src/main/elm/Page/Home/Update.elm | 35 +++++++++++---- .../webapp/src/main/elm/Page/Home/View.elm | 6 +-- .../src/main/elm/Page/ItemDetail/Update.elm | 7 ++- .../webapp/src/main/elm/Page/Login/Update.elm | 2 +- .../webapp/src/main/elm/Page/Upload/View.elm | 2 +- modules/webapp/src/main/elm/Ports.elm | 6 ++- modules/webapp/src/main/webjar/docspell.css | 6 ++- modules/webapp/src/main/webjar/docspell.js | 44 +++++++++++++------ 15 files changed, 131 insertions(+), 52 deletions(-) diff --git a/modules/webapp/src/main/elm/App/Data.elm b/modules/webapp/src/main/elm/App/Data.elm index 28fbd8d4..c461fadc 100644 --- a/modules/webapp/src/main/elm/App/Data.elm +++ b/modules/webapp/src/main/elm/App/Data.elm @@ -160,7 +160,7 @@ checkPage flags page = defaultPage : Flags -> Page defaultPage flags = if isSignedIn flags then - HomePage + HomePage Nothing else LoginPage Nothing diff --git a/modules/webapp/src/main/elm/App/Update.elm b/modules/webapp/src/main/elm/App/Update.elm index 10439077..f7734e50 100644 --- a/modules/webapp/src/main/elm/App/Update.elm +++ b/modules/webapp/src/main/elm/App/Update.elm @@ -304,8 +304,16 @@ updateLogin lmsg model = updateHome : Page.Home.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg ) updateHome lmsg model = let + mid = + case model.page of + HomePage x -> + x + + _ -> + Nothing + ( lm, lc, ls ) = - Page.Home.Update.update model.key model.flags model.uiSettings lmsg model.homeModel + Page.Home.Update.update mid model.key model.flags model.uiSettings lmsg model.homeModel in ( { model | homeModel = lm @@ -330,7 +338,7 @@ updateManageData lmsg model = initPage : Model -> Page -> ( Model, Cmd Msg, Sub Msg ) initPage model page = case page of - HomePage -> + HomePage mid -> Util.Update.andThen2 [ updateHome Page.Home.Data.Init , updateQueue Page.Queue.Data.StopRefresh diff --git a/modules/webapp/src/main/elm/App/View.elm b/modules/webapp/src/main/elm/App/View.elm index 346983e6..a5b58d29 100644 --- a/modules/webapp/src/main/elm/App/View.elm +++ b/modules/webapp/src/main/elm/App/View.elm @@ -65,7 +65,7 @@ defaultLayout model = [ div [ class "ui fluid container" ] [ a [ class "header item narrow-item" - , Page.href HomePage + , Page.href (HomePage Nothing) ] [ img [ class "image" @@ -81,7 +81,7 @@ defaultLayout model = ] , div [ class "main-content" ] [ case model.page of - HomePage -> + HomePage _ -> viewHome model LoginPage _ -> @@ -174,7 +174,16 @@ viewLogin model = viewHome : Model -> Html Msg viewHome model = - Html.map HomeMsg (Page.Home.View.view model.flags model.uiSettings model.homeModel) + let + mid = + case model.page of + HomePage x -> + x + + _ -> + Nothing + in + Html.map HomeMsg (Page.Home.View.view mid model.flags model.uiSettings model.homeModel) menuEntry : Model -> Page -> List (Html Msg) -> Html Msg @@ -206,7 +215,7 @@ loginInfo model = ] ] [ menuEntry model - HomePage + (HomePage Nothing) [ img [ class "image icon" , src (model.flags.config.docspellAssetPath ++ "/img/logo-mc-96.png") diff --git a/modules/webapp/src/main/elm/Comp/ItemCardList.elm b/modules/webapp/src/main/elm/Comp/ItemCardList.elm index d7a018fc..dbfbfc50 100644 --- a/modules/webapp/src/main/elm/Comp/ItemCardList.elm +++ b/modules/webapp/src/main/elm/Comp/ItemCardList.elm @@ -120,26 +120,26 @@ updateDrag dm _ msg model = --- View -view : UiSettings -> Model -> Html Msg -view settings model = +view : Maybe String -> UiSettings -> Model -> Html Msg +view current settings model = div [ class "ui container" ] - (List.map (viewGroup settings) model.results.groups) + (List.map (viewGroup current settings) model.results.groups) -viewGroup : UiSettings -> ItemLightGroup -> Html Msg -viewGroup settings group = +viewGroup : Maybe String -> UiSettings -> ItemLightGroup -> Html Msg +viewGroup current settings group = div [ class "item-group" ] [ div [ class "ui horizontal divider header item-list" ] [ i [ class "calendar alternate outline icon" ] [] , text group.name ] , div [ class "ui stackable three cards" ] - (List.map (viewItem settings) group.items) + (List.map (viewItem current settings) group.items) ] -viewItem : UiSettings -> ItemLight -> Html Msg -viewItem settings item = +viewItem : Maybe String -> UiSettings -> ItemLight -> Html Msg +viewItem current settings item = let dirIcon = i [ class (Data.Direction.iconFromMaybe item.direction) ] [] @@ -174,6 +174,7 @@ viewItem settings item = ([ classList [ ( "ui fluid card", True ) , ( newColor, not isConfirmed ) + , ( "current", current == Just item.id ) ] , id item.id , href "#" diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/Update.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/Update.elm index 543a15f2..a3d6844a 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/Update.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/Update.elm @@ -648,7 +648,7 @@ update key flags next msg model = noSub ( model, Page.set key (ItemDetailPage id) ) Nothing -> - noSub ( model, Page.set key HomePage ) + noSub ( model, Page.set key (HomePage Nothing) ) else noSub ( model, Cmd.none ) diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/View.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/View.elm index ccaba322..efef7f41 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/View.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/View.elm @@ -99,7 +99,7 @@ renderDetailMenu inav model = ) ] ] - [ a [ class "item", Page.href HomePage ] + [ a [ class "item", Page.href (HomePage (Just model.item.id)) ] [ i [ class "arrow left icon" ] [] ] , a diff --git a/modules/webapp/src/main/elm/Page.elm b/modules/webapp/src/main/elm/Page.elm index c9e7633e..7308e1a2 100644 --- a/modules/webapp/src/main/elm/Page.elm +++ b/modules/webapp/src/main/elm/Page.elm @@ -24,7 +24,7 @@ import Util.Maybe type Page - = HomePage + = HomePage (Maybe String) | LoginPage (Maybe Page) | ManageDataPage | CollectiveSettingPage @@ -39,7 +39,7 @@ type Page isSecured : Page -> Bool isSecured page = case page of - HomePage -> + HomePage _ -> True LoginPage _ -> @@ -88,7 +88,7 @@ loginPage p = pageName : Page -> String pageName page = case page of - HomePage -> + HomePage _ -> "Home" LoginPage _ -> @@ -147,7 +147,10 @@ uploadId page = pageToString : Page -> String pageToString page = case page of - HomePage -> + HomePage (Just id) -> + "/app/home?item=" ++ id + + HomePage Nothing -> "/app/home" LoginPage referer -> @@ -227,7 +230,12 @@ pathPrefix = parser : Parser (Page -> a) a parser = oneOf - [ Parser.map HomePage (oneOf [ Parser.top, s pathPrefix s "home" ]) + [ Parser.map HomePage + (oneOf + [ Parser.top itemQuery + , s pathPrefix s "home" itemQuery + ] + ) , Parser.map LoginPage (s pathPrefix s "login" pageQuery) , Parser.map ManageDataPage (s pathPrefix s "managedata") , Parser.map CollectiveSettingPage (s pathPrefix s "csettings") @@ -263,3 +271,8 @@ pageQuery = in Query.string "r" |> Query.map parsePage + + +itemQuery : Query.Parser (Maybe String) +itemQuery = + Query.string "item" diff --git a/modules/webapp/src/main/elm/Page/Home/Update.elm b/modules/webapp/src/main/elm/Page/Home/Update.elm index 3cc5c2ed..0aee19ba 100644 --- a/modules/webapp/src/main/elm/Page/Home/Update.elm +++ b/modules/webapp/src/main/elm/Page/Home/Update.elm @@ -8,6 +8,7 @@ import Data.Flags exposing (Flags) import Data.UiSettings exposing (UiSettings) import Page exposing (Page(..)) import Page.Home.Data exposing (..) +import Ports import Throttle import Time import Util.Html exposing (KeyCode(..)) @@ -17,12 +18,12 @@ import Util.String import Util.Update -update : Nav.Key -> Flags -> UiSettings -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg ) -update key flags settings msg model = +update : Maybe String -> Nav.Key -> Flags -> UiSettings -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg ) +update mId key flags settings msg model = case msg of Init -> Util.Update.andThen2 - [ update key flags settings (SearchMenuMsg Comp.SearchMenu.Init) + [ update mId key flags settings (SearchMenuMsg Comp.SearchMenu.Init) , doSearch flags settings ] model @@ -35,7 +36,7 @@ update key flags settings msg model = , searchType = defaultSearchType flags } in - update key flags settings (SearchMenuMsg Comp.SearchMenu.ResetForm) nm + update mId key flags settings (SearchMenuMsg Comp.SearchMenu.ResetForm) nm SearchMenuMsg m -> let @@ -108,7 +109,11 @@ update key flags settings msg model = , moreAvailable = list.groups /= [] } in - update key flags settings (ItemCardListMsg (Comp.ItemCardList.SetResults list)) m + Util.Update.andThen2 + [ update mId key flags settings (ItemCardListMsg (Comp.ItemCardList.SetResults list)) + , scrollToCard mId + ] + m ItemSearchAddResp (Ok list) -> let @@ -123,7 +128,11 @@ update key flags settings msg model = , moreAvailable = list.groups /= [] } in - update key flags settings (ItemCardListMsg (Comp.ItemCardList.AddResults list)) m + Util.Update.andThen2 + [ update mId key flags settings (ItemCardListMsg (Comp.ItemCardList.AddResults list)) + , scrollToCard mId + ] + m ItemSearchAddResp (Err _) -> withSub @@ -185,7 +194,7 @@ update key flags settings msg model = ContentOnlySearch -> SetContentOnly str in - update key flags settings smMsg model + update mId key flags settings smMsg model SetContentOnly str -> withSub @@ -207,7 +216,7 @@ update key flags settings msg model = ) KeyUpMsg (Just Enter) -> - update key flags settings DoSearch model + update mId key flags settings DoSearch model KeyUpMsg _ -> withSub ( model, Cmd.none ) @@ -217,6 +226,16 @@ update key flags settings msg model = --- Helpers +scrollToCard : Maybe String -> Model -> ( Model, Cmd Msg, Sub Msg ) +scrollToCard mId model = + case mId of + Just id -> + ( model, Ports.scrollToElem ( id, 0 ), Sub.none ) + + Nothing -> + ( model, Cmd.none, Sub.none ) + + doSearch : Flags -> UiSettings -> Model -> ( Model, Cmd Msg, Sub Msg ) doSearch flags settings model = let diff --git a/modules/webapp/src/main/elm/Page/Home/View.elm b/modules/webapp/src/main/elm/Page/Home/View.elm index 6d8260be..14287797 100644 --- a/modules/webapp/src/main/elm/Page/Home/View.elm +++ b/modules/webapp/src/main/elm/Page/Home/View.elm @@ -14,8 +14,8 @@ import Page.Home.Data exposing (..) import Util.Html -view : Flags -> UiSettings -> Model -> Html Msg -view flags settings model = +view : Maybe String -> Flags -> UiSettings -> Model -> Html Msg +view current flags settings model = div [ class "home-page ui padded grid" ] [ div [ classList @@ -82,7 +82,7 @@ view flags settings model = ] [ viewSearchBar flags model , Html.map ItemCardListMsg - (Comp.ItemCardList.view settings model.itemListModel) + (Comp.ItemCardList.view current settings model.itemListModel) ] , div [ classList diff --git a/modules/webapp/src/main/elm/Page/ItemDetail/Update.elm b/modules/webapp/src/main/elm/Page/ItemDetail/Update.elm index 46aed752..62ce8bac 100644 --- a/modules/webapp/src/main/elm/Page/ItemDetail/Update.elm +++ b/modules/webapp/src/main/elm/Page/ItemDetail/Update.elm @@ -6,6 +6,7 @@ import Comp.ItemDetail import Comp.ItemDetail.Update import Data.Flags exposing (Flags) import Page.ItemDetail.Data exposing (Model, Msg(..)) +import Ports update : Nav.Key -> Flags -> Maybe String -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg ) @@ -17,7 +18,11 @@ update key flags next msg model = Comp.ItemDetail.update key flags next Comp.ItemDetail.Update.Init model.detail in ( { model | detail = lm } - , Cmd.batch [ Api.itemDetail flags id ItemResp, Cmd.map ItemDetailMsg lc ] + , Cmd.batch + [ Api.itemDetail flags id ItemResp + , Cmd.map ItemDetailMsg lc + , Ports.scrollToTop () + ] , Sub.map ItemDetailMsg ls ) diff --git a/modules/webapp/src/main/elm/Page/Login/Update.elm b/modules/webapp/src/main/elm/Page/Login/Update.elm index 539d2f02..54145cd8 100644 --- a/modules/webapp/src/main/elm/Page/Login/Update.elm +++ b/modules/webapp/src/main/elm/Page/Login/Update.elm @@ -25,7 +25,7 @@ update referrer flags msg model = AuthResp (Ok lr) -> let gotoRef = - Maybe.withDefault HomePage referrer |> Page.goto + Maybe.withDefault (HomePage Nothing) referrer |> Page.goto in if lr.success then ( { model | result = Just lr, password = "" }, Cmd.batch [ setAccount lr, gotoRef ], Just lr ) diff --git a/modules/webapp/src/main/elm/Page/Upload/View.elm b/modules/webapp/src/main/elm/Page/Upload/View.elm index 02e15142..4d32a2b5 100644 --- a/modules/webapp/src/main/elm/Page/Upload/View.elm +++ b/modules/webapp/src/main/elm/Page/Upload/View.elm @@ -77,7 +77,7 @@ renderSuccessMsg public _ = else p [] [ text "Your files have been successfully uploaded. They are now being processed. Check the " - , a [ class "ui link", Page.href HomePage ] + , a [ class "ui link", Page.href (HomePage Nothing) ] [ text "Items page" ] , text " later where the files will arrive eventually. Or go to the " diff --git a/modules/webapp/src/main/elm/Ports.elm b/modules/webapp/src/main/elm/Ports.elm index d401bc1a..65df9907 100644 --- a/modules/webapp/src/main/elm/Ports.elm +++ b/modules/webapp/src/main/elm/Ports.elm @@ -5,6 +5,7 @@ port module Ports exposing , onUiSettingsSaved , removeAccount , scrollToElem + , scrollToTop , setAccount , setAllProgress , setProgress @@ -30,7 +31,10 @@ port setProgress : ( String, Int ) -> Cmd msg port setAllProgress : ( String, Int ) -> Cmd msg -port scrollToElem : String -> Cmd msg +port scrollToElem : ( String, Int ) -> Cmd msg + + +port scrollToTop : () -> Cmd msg port saveUiSettings : ( AuthResult, StoredUiSettings ) -> Cmd msg diff --git a/modules/webapp/src/main/webjar/docspell.css b/modules/webapp/src/main/webjar/docspell.css index fa2e1ceb..0902853e 100644 --- a/modules/webapp/src/main/webjar/docspell.css +++ b/modules/webapp/src/main/webjar/docspell.css @@ -41,7 +41,7 @@ } .default-layout .main-content { - margin-top: 44px; + padding-top: 44px; padding-bottom: 2em; } @@ -97,6 +97,10 @@ .default-layout .ui.cards .ui.card .content.search-highlight .ui.list .item .content .description strong > em { background: rgba(220, 255, 71, 0.6); } +.default-layout .ui.cards .ui.card.current { + /* semantic-ui purple */ + box-shadow: 0 0 6px rgba(0,0,0,0.55); +} .default-layout .qr-code svg { width: 200px; diff --git a/modules/webapp/src/main/webjar/docspell.js b/modules/webapp/src/main/webjar/docspell.js index cb91987f..7f3a565e 100644 --- a/modules/webapp/src/main/webjar/docspell.js +++ b/modules/webapp/src/main/webjar/docspell.js @@ -32,20 +32,36 @@ elmApp.ports.setAllProgress.subscribe(function(input) { }, 100); }); -// elmApp.ports.scrollToElem.subscribe(function(id) { -// if (id && id != "") { -// window.setTimeout(function() { -// var el = document.getElementById(id); -// if (el) { -// if (el["scrollIntoViewIfNeeded"]) { -// el.scrollIntoViewIfNeeded(); -// } else { -// el.scrollIntoView(); -// } -// } -// }, 20); -// } -// }); +elmApp.ports.scrollToTop.subscribe(function() { + window.scrollTo(0, 0); +}); + +elmApp.ports.scrollToElem.subscribe(function(argList) { + var id = argList && argList.length >= 1 + ? argList[0] : null; + var offset = argList && argList.length >= 2 + ? argList[1] : null; + + if (id && id != "") { + window.setTimeout(function() { + var el = document.getElementById(id); + if (el) { + if (el["scrollIntoViewIfNeeded"]) { + el.scrollIntoViewIfNeeded(); + } else { + el.scrollIntoView({ + behavior: "auto", + block: "center", + inline: "nearest" + }); + } + if (offset && offset != 0) { + window.scrollBy(0, offset); + } + } + }, 20); + } +}); elmApp.ports.saveUiSettings.subscribe(function(args) { if (Array.isArray(args) && args.length == 2) {