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.
This commit is contained in:
Eike Kettner
2020-09-14 18:43:04 +02:00
parent 913bfb611c
commit 3852c69da1
15 changed files with 131 additions and 52 deletions

View File

@ -160,7 +160,7 @@ checkPage flags page =
defaultPage : Flags -> Page defaultPage : Flags -> Page
defaultPage flags = defaultPage flags =
if isSignedIn flags then if isSignedIn flags then
HomePage HomePage Nothing
else else
LoginPage Nothing LoginPage Nothing

View File

@ -304,8 +304,16 @@ updateLogin lmsg model =
updateHome : Page.Home.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg ) updateHome : Page.Home.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
updateHome lmsg model = updateHome lmsg model =
let let
mid =
case model.page of
HomePage x ->
x
_ ->
Nothing
( lm, lc, ls ) = ( 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 in
( { model ( { model
| homeModel = lm | homeModel = lm
@ -330,7 +338,7 @@ updateManageData lmsg model =
initPage : Model -> Page -> ( Model, Cmd Msg, Sub Msg ) initPage : Model -> Page -> ( Model, Cmd Msg, Sub Msg )
initPage model page = initPage model page =
case page of case page of
HomePage -> HomePage mid ->
Util.Update.andThen2 Util.Update.andThen2
[ updateHome Page.Home.Data.Init [ updateHome Page.Home.Data.Init
, updateQueue Page.Queue.Data.StopRefresh , updateQueue Page.Queue.Data.StopRefresh

View File

@ -65,7 +65,7 @@ defaultLayout model =
[ div [ class "ui fluid container" ] [ div [ class "ui fluid container" ]
[ a [ a
[ class "header item narrow-item" [ class "header item narrow-item"
, Page.href HomePage , Page.href (HomePage Nothing)
] ]
[ img [ img
[ class "image" [ class "image"
@ -81,7 +81,7 @@ defaultLayout model =
] ]
, div [ class "main-content" ] , div [ class "main-content" ]
[ case model.page of [ case model.page of
HomePage -> HomePage _ ->
viewHome model viewHome model
LoginPage _ -> LoginPage _ ->
@ -174,7 +174,16 @@ viewLogin model =
viewHome : Model -> Html Msg viewHome : Model -> Html Msg
viewHome model = 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 menuEntry : Model -> Page -> List (Html Msg) -> Html Msg
@ -206,7 +215,7 @@ loginInfo model =
] ]
] ]
[ menuEntry model [ menuEntry model
HomePage (HomePage Nothing)
[ img [ img
[ class "image icon" [ class "image icon"
, src (model.flags.config.docspellAssetPath ++ "/img/logo-mc-96.png") , src (model.flags.config.docspellAssetPath ++ "/img/logo-mc-96.png")

View File

@ -120,26 +120,26 @@ updateDrag dm _ msg model =
--- View --- View
view : UiSettings -> Model -> Html Msg view : Maybe String -> UiSettings -> Model -> Html Msg
view settings model = view current settings model =
div [ class "ui container" ] 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 : Maybe String -> UiSettings -> ItemLightGroup -> Html Msg
viewGroup settings group = viewGroup current settings group =
div [ class "item-group" ] div [ class "item-group" ]
[ div [ class "ui horizontal divider header item-list" ] [ div [ class "ui horizontal divider header item-list" ]
[ i [ class "calendar alternate outline icon" ] [] [ i [ class "calendar alternate outline icon" ] []
, text group.name , text group.name
] ]
, div [ class "ui stackable three cards" ] , 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 : Maybe String -> UiSettings -> ItemLight -> Html Msg
viewItem settings item = viewItem current settings item =
let let
dirIcon = dirIcon =
i [ class (Data.Direction.iconFromMaybe item.direction) ] [] i [ class (Data.Direction.iconFromMaybe item.direction) ] []
@ -174,6 +174,7 @@ viewItem settings item =
([ classList ([ classList
[ ( "ui fluid card", True ) [ ( "ui fluid card", True )
, ( newColor, not isConfirmed ) , ( newColor, not isConfirmed )
, ( "current", current == Just item.id )
] ]
, id item.id , id item.id
, href "#" , href "#"

View File

@ -648,7 +648,7 @@ update key flags next msg model =
noSub ( model, Page.set key (ItemDetailPage id) ) noSub ( model, Page.set key (ItemDetailPage id) )
Nothing -> Nothing ->
noSub ( model, Page.set key HomePage ) noSub ( model, Page.set key (HomePage Nothing) )
else else
noSub ( model, Cmd.none ) noSub ( model, Cmd.none )

View File

@ -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" ] [] [ i [ class "arrow left icon" ] []
] ]
, a , a

View File

@ -24,7 +24,7 @@ import Util.Maybe
type Page type Page
= HomePage = HomePage (Maybe String)
| LoginPage (Maybe Page) | LoginPage (Maybe Page)
| ManageDataPage | ManageDataPage
| CollectiveSettingPage | CollectiveSettingPage
@ -39,7 +39,7 @@ type Page
isSecured : Page -> Bool isSecured : Page -> Bool
isSecured page = isSecured page =
case page of case page of
HomePage -> HomePage _ ->
True True
LoginPage _ -> LoginPage _ ->
@ -88,7 +88,7 @@ loginPage p =
pageName : Page -> String pageName : Page -> String
pageName page = pageName page =
case page of case page of
HomePage -> HomePage _ ->
"Home" "Home"
LoginPage _ -> LoginPage _ ->
@ -147,7 +147,10 @@ uploadId page =
pageToString : Page -> String pageToString : Page -> String
pageToString page = pageToString page =
case page of case page of
HomePage -> HomePage (Just id) ->
"/app/home?item=" ++ id
HomePage Nothing ->
"/app/home" "/app/home"
LoginPage referer -> LoginPage referer ->
@ -227,7 +230,12 @@ pathPrefix =
parser : Parser (Page -> a) a parser : Parser (Page -> a) a
parser = parser =
oneOf 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 LoginPage (s pathPrefix </> s "login" <?> pageQuery)
, Parser.map ManageDataPage (s pathPrefix </> s "managedata") , Parser.map ManageDataPage (s pathPrefix </> s "managedata")
, Parser.map CollectiveSettingPage (s pathPrefix </> s "csettings") , Parser.map CollectiveSettingPage (s pathPrefix </> s "csettings")
@ -263,3 +271,8 @@ pageQuery =
in in
Query.string "r" Query.string "r"
|> Query.map parsePage |> Query.map parsePage
itemQuery : Query.Parser (Maybe String)
itemQuery =
Query.string "item"

View File

@ -8,6 +8,7 @@ import Data.Flags exposing (Flags)
import Data.UiSettings exposing (UiSettings) import Data.UiSettings exposing (UiSettings)
import Page exposing (Page(..)) import Page exposing (Page(..))
import Page.Home.Data exposing (..) import Page.Home.Data exposing (..)
import Ports
import Throttle import Throttle
import Time import Time
import Util.Html exposing (KeyCode(..)) import Util.Html exposing (KeyCode(..))
@ -17,12 +18,12 @@ import Util.String
import Util.Update import Util.Update
update : Nav.Key -> Flags -> UiSettings -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg ) update : Maybe String -> Nav.Key -> Flags -> UiSettings -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
update key flags settings msg model = update mId key flags settings msg model =
case msg of case msg of
Init -> Init ->
Util.Update.andThen2 Util.Update.andThen2
[ update key flags settings (SearchMenuMsg Comp.SearchMenu.Init) [ update mId key flags settings (SearchMenuMsg Comp.SearchMenu.Init)
, doSearch flags settings , doSearch flags settings
] ]
model model
@ -35,7 +36,7 @@ update key flags settings msg model =
, searchType = defaultSearchType flags , searchType = defaultSearchType flags
} }
in in
update key flags settings (SearchMenuMsg Comp.SearchMenu.ResetForm) nm update mId key flags settings (SearchMenuMsg Comp.SearchMenu.ResetForm) nm
SearchMenuMsg m -> SearchMenuMsg m ->
let let
@ -108,7 +109,11 @@ update key flags settings msg model =
, moreAvailable = list.groups /= [] , moreAvailable = list.groups /= []
} }
in 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) -> ItemSearchAddResp (Ok list) ->
let let
@ -123,7 +128,11 @@ update key flags settings msg model =
, moreAvailable = list.groups /= [] , moreAvailable = list.groups /= []
} }
in 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 _) -> ItemSearchAddResp (Err _) ->
withSub withSub
@ -185,7 +194,7 @@ update key flags settings msg model =
ContentOnlySearch -> ContentOnlySearch ->
SetContentOnly str SetContentOnly str
in in
update key flags settings smMsg model update mId key flags settings smMsg model
SetContentOnly str -> SetContentOnly str ->
withSub withSub
@ -207,7 +216,7 @@ update key flags settings msg model =
) )
KeyUpMsg (Just Enter) -> KeyUpMsg (Just Enter) ->
update key flags settings DoSearch model update mId key flags settings DoSearch model
KeyUpMsg _ -> KeyUpMsg _ ->
withSub ( model, Cmd.none ) withSub ( model, Cmd.none )
@ -217,6 +226,16 @@ update key flags settings msg model =
--- Helpers --- 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 -> UiSettings -> Model -> ( Model, Cmd Msg, Sub Msg )
doSearch flags settings model = doSearch flags settings model =
let let

View File

@ -14,8 +14,8 @@ import Page.Home.Data exposing (..)
import Util.Html import Util.Html
view : Flags -> UiSettings -> Model -> Html Msg view : Maybe String -> Flags -> UiSettings -> Model -> Html Msg
view flags settings model = view current flags settings model =
div [ class "home-page ui padded grid" ] div [ class "home-page ui padded grid" ]
[ div [ div
[ classList [ classList
@ -82,7 +82,7 @@ view flags settings model =
] ]
[ viewSearchBar flags model [ viewSearchBar flags model
, Html.map ItemCardListMsg , Html.map ItemCardListMsg
(Comp.ItemCardList.view settings model.itemListModel) (Comp.ItemCardList.view current settings model.itemListModel)
] ]
, div , div
[ classList [ classList

View File

@ -6,6 +6,7 @@ import Comp.ItemDetail
import Comp.ItemDetail.Update import Comp.ItemDetail.Update
import Data.Flags exposing (Flags) import Data.Flags exposing (Flags)
import Page.ItemDetail.Data exposing (Model, Msg(..)) import Page.ItemDetail.Data exposing (Model, Msg(..))
import Ports
update : Nav.Key -> Flags -> Maybe String -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg ) 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 Comp.ItemDetail.update key flags next Comp.ItemDetail.Update.Init model.detail
in in
( { model | detail = lm } ( { 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 , Sub.map ItemDetailMsg ls
) )

View File

@ -25,7 +25,7 @@ update referrer flags msg model =
AuthResp (Ok lr) -> AuthResp (Ok lr) ->
let let
gotoRef = gotoRef =
Maybe.withDefault HomePage referrer |> Page.goto Maybe.withDefault (HomePage Nothing) referrer |> Page.goto
in in
if lr.success then if lr.success then
( { model | result = Just lr, password = "" }, Cmd.batch [ setAccount lr, gotoRef ], Just lr ) ( { model | result = Just lr, password = "" }, Cmd.batch [ setAccount lr, gotoRef ], Just lr )

View File

@ -77,7 +77,7 @@ renderSuccessMsg public _ =
else else
p [] p []
[ text "Your files have been successfully uploaded. They are now being processed. Check the " [ 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 "Items page"
] ]
, text " later where the files will arrive eventually. Or go to the " , text " later where the files will arrive eventually. Or go to the "

View File

@ -5,6 +5,7 @@ port module Ports exposing
, onUiSettingsSaved , onUiSettingsSaved
, removeAccount , removeAccount
, scrollToElem , scrollToElem
, scrollToTop
, setAccount , setAccount
, setAllProgress , setAllProgress
, setProgress , setProgress
@ -30,7 +31,10 @@ port setProgress : ( String, Int ) -> Cmd msg
port setAllProgress : ( 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 port saveUiSettings : ( AuthResult, StoredUiSettings ) -> Cmd msg

View File

@ -41,7 +41,7 @@
} }
.default-layout .main-content { .default-layout .main-content {
margin-top: 44px; padding-top: 44px;
padding-bottom: 2em; padding-bottom: 2em;
} }
@ -97,6 +97,10 @@
.default-layout .ui.cards .ui.card .content.search-highlight .ui.list .item .content .description strong > em { .default-layout .ui.cards .ui.card .content.search-highlight .ui.list .item .content .description strong > em {
background: rgba(220, 255, 71, 0.6); 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 { .default-layout .qr-code svg {
width: 200px; width: 200px;

View File

@ -32,20 +32,36 @@ elmApp.ports.setAllProgress.subscribe(function(input) {
}, 100); }, 100);
}); });
// elmApp.ports.scrollToElem.subscribe(function(id) { elmApp.ports.scrollToTop.subscribe(function() {
// if (id && id != "") { window.scrollTo(0, 0);
// window.setTimeout(function() { });
// var el = document.getElementById(id);
// if (el) { elmApp.ports.scrollToElem.subscribe(function(argList) {
// if (el["scrollIntoViewIfNeeded"]) { var id = argList && argList.length >= 1
// el.scrollIntoViewIfNeeded(); ? argList[0] : null;
// } else { var offset = argList && argList.length >= 2
// el.scrollIntoView(); ? argList[1] : null;
// }
// } if (id && id != "") {
// }, 20); 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) { elmApp.ports.saveUiSettings.subscribe(function(args) {
if (Array.isArray(args) && args.length == 2) { if (Array.isArray(args) && args.length == 2) {