From 2e364674ee119d59da719e1548d48464d965fa2c Mon Sep 17 00:00:00 2001 From: davidvader Date: Fri, 2 Feb 2024 16:56:42 -0600 Subject: [PATCH] refactor: pagination consistency, urlchanged with tab switch focus skipping, and layout improvements --- src/elm/Api/Operations.elm | 49 +++++++++++--- src/elm/Components/Builds.elm | 4 +- src/elm/Components/Pager.elm | 2 +- src/elm/Components/RecentBuilds.elm | 4 +- src/elm/Components/Secrets.elm | 6 +- src/elm/Components/Tabs.elm | 71 +++++++++++--------- src/elm/Effect.elm | 19 +++++- src/elm/Layouts/Default.elm | 5 +- src/elm/Layouts/Default/Build.elm | 35 +++++++--- src/elm/Layouts/Default/Org.elm | 56 ++++++++------- src/elm/Layouts/Default/Repo.elm | 59 ++++++++++------ src/elm/Pages/Account/Login.elm | 2 +- src/elm/Pages/Account/Settings.elm | 2 +- src/elm/Pages/Account/SourceRepos.elm | 2 +- src/elm/Pages/Org_.elm | 51 ++++++++++++-- src/elm/Pages/Org_/Builds.elm | 2 +- src/elm/Pages/Org_/Repo_/Audit.elm | 8 +-- src/elm/Pages/Org_/Repo_/Build_.elm | 40 +++++++---- src/elm/Pages/Org_/Repo_/Build_/Graph.elm | 22 +++--- src/elm/Pages/Org_/Repo_/Build_/Pipeline.elm | 70 ++++++++++++------- src/elm/Pages/Org_/Repo_/Build_/Services.elm | 22 +++--- src/elm/Pages/Org_/Repo_/Deployments.elm | 2 +- src/elm/Pages/Org_/Repo_/Schedules.elm | 22 +++--- 23 files changed, 367 insertions(+), 188 deletions(-) diff --git a/src/elm/Api/Operations.elm b/src/elm/Api/Operations.elm index edc0d0ae3..32822b3fd 100644 --- a/src/elm/Api/Operations.elm +++ b/src/elm/Api/Operations.elm @@ -134,7 +134,10 @@ getUserSourceRepos baseUrl session = getRepo : String -> Session -> { a | org : String, repo : String } -> Request Vela.Repository getRepo baseUrl session options = get baseUrl - (Api.Endpoint.Repository options.org options.repo) + (Api.Endpoint.Repository + options.org + options.repo + ) Vela.decodeRepository |> withAuth session @@ -144,7 +147,10 @@ getRepo baseUrl session options = enableRepo : String -> Session -> Http.Body -> Request Vela.Repository enableRepo baseUrl session body = post baseUrl - (Api.Endpoint.Repositories Nothing Nothing) + (Api.Endpoint.Repositories + Nothing + Nothing + ) body Vela.decodeRepository |> withAuth session @@ -155,7 +161,10 @@ enableRepo baseUrl session body = updateRepo : String -> Session -> { a | org : String, repo : String, body : Http.Body } -> Request Vela.Repository updateRepo baseUrl session options = put baseUrl - (Api.Endpoint.Repository options.org options.repo) + (Api.Endpoint.Repository + options.org + options.repo + ) options.body Vela.decodeRepository |> withAuth session @@ -166,7 +175,10 @@ updateRepo baseUrl session options = repairRepo : String -> Session -> { a | org : String, repo : String } -> Request String repairRepo baseUrl session options = patch baseUrl - (Api.Endpoint.RepositoryRepair options.org options.repo) + (Api.Endpoint.RepositoryRepair + options.org + options.repo + ) Json.Decode.string |> withAuth session @@ -176,7 +188,10 @@ repairRepo baseUrl session options = chownRepo : String -> Session -> { a | org : String, repo : String } -> Request String chownRepo baseUrl session options = patch baseUrl - (Api.Endpoint.RepositoryChown options.org options.repo) + (Api.Endpoint.RepositoryChown + options.org + options.repo + ) Json.Decode.string |> withAuth session @@ -186,17 +201,33 @@ chownRepo baseUrl session options = disableRepo : String -> Session -> { a | org : String, repo : String } -> Request String disableRepo baseUrl session options = delete baseUrl - (Api.Endpoint.Repository options.org options.repo) + (Api.Endpoint.Repository + options.org + options.repo + ) Json.Decode.string |> withAuth session {-| getOrgRepos : retrieves the repositories for an org -} -getOrgRepos : String -> Session -> { a | org : String } -> Request (List Vela.Repository) -getOrgRepos baseUrl session { org } = +getOrgRepos : + String + -> Session + -> + { a + | org : String + , pageNumber : Maybe Int + , perPage : Maybe Int + } + -> Request (List Vela.Repository) +getOrgRepos baseUrl session options = get baseUrl - (Api.Endpoint.OrgRepositories Nothing Nothing org) + (Api.Endpoint.OrgRepositories + options.pageNumber + options.perPage + options.org + ) Vela.decodeRepositories |> withAuth session diff --git a/src/elm/Components/Builds.elm b/src/elm/Components/Builds.elm index ff74793c6..9eec4a6a6 100644 --- a/src/elm/Components/Builds.elm +++ b/src/elm/Components/Builds.elm @@ -127,10 +127,10 @@ view shared props = builds RemoteData.Loading -> - Util.largeLoader + Util.smallLoader RemoteData.NotAsked -> - Util.largeLoader + Util.smallLoader RemoteData.Failure _ -> div [ Util.testAttribute "builds-error" ] diff --git a/src/elm/Components/Pager.elm b/src/elm/Components/Pager.elm index c737de85f..42e1fa519 100644 --- a/src/elm/Components/Pager.elm +++ b/src/elm/Components/Pager.elm @@ -104,7 +104,7 @@ view links labels toMsg = _ -> 1 in - div [ class "pager-actions" ] + div [ class "pager-actions", class "buttons" ] [ button [ disabled <| isFirst || (List.length links == 0) , Util.testAttribute "pager-previous" diff --git a/src/elm/Components/RecentBuilds.elm b/src/elm/Components/RecentBuilds.elm index 3f7cba082..0ea017d78 100644 --- a/src/elm/Components/RecentBuilds.elm +++ b/src/elm/Components/RecentBuilds.elm @@ -36,10 +36,10 @@ view shared props = ] else - Util.smallLoader + text "" _ -> - text "" + Util.smallLoader {-| viewRecentBuild : takes recent build and renders status and link to build as a small icon widget diff --git a/src/elm/Components/Secrets.elm b/src/elm/Components/Secrets.elm index 848fd7d66..5076a4fa9 100644 --- a/src/elm/Components/Secrets.elm +++ b/src/elm/Components/Secrets.elm @@ -69,7 +69,7 @@ viewOrgSecrets shared props = ) _ -> - ( Util.largeLoader, [] ) + ( Util.smallLoader, [] ) cfg = Components.Table.Config @@ -119,7 +119,7 @@ viewRepoSecrets shared props = ) _ -> - ( Util.largeLoader, [] ) + ( Util.smallLoader, [] ) cfg = Components.Table.Config @@ -169,7 +169,7 @@ viewSharedSecrets shared props = ) _ -> - ( Util.largeLoader, [] ) + ( Util.smallLoader, [] ) cfg = Components.Table.Config diff --git a/src/elm/Components/Tabs.elm b/src/elm/Components/Tabs.elm index 0ec572c1c..cdf991402 100644 --- a/src/elm/Components/Tabs.elm +++ b/src/elm/Components/Tabs.elm @@ -6,19 +6,21 @@ SPDX-License-Identifier: Apache-2.0 module Components.Tabs exposing (Tab, view, viewBuildTabs, viewOrgTabs, viewRepoTabs) import Api.Pagination as Pagination +import Dict exposing (Dict) import Html exposing (Html, a, div, span, text) import Html.Attributes exposing (class, classList) import RemoteData +import Route import Route.Path import Shared +import Url exposing (Url) import Utils.Helpers as Util {-| Tab : record to represent information used by page navigation tab -} type alias Tab = - { currentPath : Route.Path.Path - , toPath : Route.Path.Path + { toPath : Route.Path.Path , name : String , isAlerting : Bool , show : Bool @@ -27,10 +29,10 @@ type alias Tab = {-| view : takes list of tab records and renders them with spacers and horizontal filler -} -view : List Tab -> String -> Html msg -view tabs testLabel = +view : Dict String Url -> Route.Path.Path -> List Tab -> String -> Html msg +view tabHistory currentPath tabs testLabel = tabs - |> List.filterMap viewTab + |> List.filterMap (viewTab tabHistory currentPath) |> List.intersperse viewSpacer |> (\t -> t ++ [ viewFiller ]) |> div [ class "jump-bar", Util.testAttribute testLabel ] @@ -38,8 +40,25 @@ view tabs testLabel = {-| viewTab : takes single tab record and renders jump link, uses current page to display conditional style -} -viewTab : Tab -> Maybe (Html msg) -viewTab { name, currentPath, toPath, isAlerting, show } = +viewTab : Dict String Url -> Route.Path.Path -> Tab -> Maybe (Html msg) +viewTab tabHistory currentPath { name, toPath, isAlerting, show } = + let + toRoute = + Dict.get (Route.Path.toString toPath) tabHistory + |> Maybe.map (Route.fromUrl ()) + |> Maybe.map + (\r -> + { path = r.path + , query = r.query |> Dict.insert "tab_switch" "true" + , hash = r.hash + } + ) + |> Maybe.withDefault + { path = toPath + , query = Dict.empty + , hash = Nothing + } + in if show then Just <| a @@ -48,7 +67,7 @@ viewTab { name, currentPath, toPath, isAlerting, show } = , ( "alerting", isAlerting ) ] , currentPathClass currentPath toPath - , Route.Path.href toPath + , Route.href toRoute , Util.testAttribute <| "jump-" ++ name ] [ text name ] @@ -87,37 +106,34 @@ currentPathClass p1 p2 = viewOrgTabs : - { currentPath : Route.Path.Path - , org : String - , maybePage : Maybe Pagination.Page - , maybePerPage : Maybe Pagination.PerPage - , maybeEvent : Maybe String - } + Shared.Model + -> + { currentPath : Route.Path.Path + , org : String + , tabHistory : Dict String Url + } -> Html msg -viewOrgTabs props = +viewOrgTabs shared props = let tabs = [ { name = "Repositories" - , currentPath = props.currentPath , toPath = Route.Path.Org_ { org = props.org } , isAlerting = False , show = True } , { name = "Builds" - , currentPath = props.currentPath , toPath = Route.Path.Org_Builds { org = props.org } , isAlerting = False , show = True } , { name = "Secrets" - , currentPath = props.currentPath , toPath = Route.Path.SecretsEngine_OrgOrg_ { org = props.org, engine = "native" } , isAlerting = False , show = True } ] in - view tabs "jump-bar-repo" + view props.tabHistory props.currentPath tabs "jump-bar-repo" @@ -130,6 +146,7 @@ viewRepoTabs : { currentPath : Route.Path.Path , org : String , repo : String + , tabHistory : Dict String Url } -> Html msg viewRepoTabs shared props = @@ -168,7 +185,6 @@ viewRepoTabs shared props = tabs = [ { name = "Builds" - , currentPath = props.currentPath , toPath = Route.Path.Org_Repo_ { org = props.org @@ -178,7 +194,6 @@ viewRepoTabs shared props = , show = True } , { name = "Deployments" - , currentPath = props.currentPath , toPath = Route.Path.Org_Repo_Deployments { org = props.org @@ -188,7 +203,6 @@ viewRepoTabs shared props = , show = True } , { name = "Secrets" - , currentPath = props.currentPath , toPath = Route.Path.SecretsEngine_RepoOrg_Repo_ { org = props.org @@ -199,30 +213,28 @@ viewRepoTabs shared props = , show = True } , { name = "Schedules" - , currentPath = props.currentPath , toPath = Route.Path.Org_Repo_Schedules { org = props.org, repo = props.repo } , isAlerting = False , show = showSchedules } , { name = "Audit" - , currentPath = props.currentPath , toPath = Route.Path.Org_Repo_Audit { org = props.org, repo = props.repo } , isAlerting = auditAlerting , show = True } , { name = "Settings" - , currentPath = props.currentPath , toPath = Route.Path.Org_Repo_Settings { org = props.org, repo = props.repo } , isAlerting = False , show = True } ] in - view tabs "jump-bar-repo" + view props.tabHistory props.currentPath tabs "jump-bar-repo" -- BUILD +-- fromHistory : Dict String Url -> String -> Route.Path.Path viewBuildTabs : @@ -232,13 +244,13 @@ viewBuildTabs : , repo : String , buildNumber : String , currentPath : Route.Path.Path + , tabHistory : Dict String Url } -> Html msg viewBuildTabs shared props = let tabs = [ { name = "Build" - , currentPath = props.currentPath , toPath = Route.Path.Org_Repo_Build_ { org = props.org @@ -249,7 +261,6 @@ viewBuildTabs shared props = , show = True } , { name = "Services" - , currentPath = props.currentPath , toPath = Route.Path.Org_Repo_Build_Services { org = props.org @@ -260,7 +271,6 @@ viewBuildTabs shared props = , show = True } , { name = "Pipeline" - , currentPath = props.currentPath , toPath = Route.Path.Org_Repo_Build_Pipeline { org = props.org @@ -271,7 +281,6 @@ viewBuildTabs shared props = , show = True } , { name = "Visualize" - , currentPath = props.currentPath , toPath = Route.Path.Org_Repo_Build_Graph { org = props.org @@ -283,4 +292,4 @@ viewBuildTabs shared props = } ] in - view tabs "jump-bar-build" + view props.tabHistory props.currentPath tabs "jump-bar-build" diff --git a/src/elm/Effect.elm b/src/elm/Effect.elm index 74ad84c3b..f29b91bb3 100644 --- a/src/elm/Effect.elm +++ b/src/elm/Effect.elm @@ -9,7 +9,7 @@ module Effect exposing , sendCmd, sendMsg , pushRoute, replaceRoute, loadExternalUrl , map, toCmd - , addAlertError, addAlertSuccess, addDeployment, addOrgSecret, addRepoSchedule, addRepoSecret, addSharedSecret, alertsUpdate, chownRepo, clearRedirect, deleteOrgSecret, deleteRepoSchedule, deleteRepoSecret, deleteSharedSecret, disableRepo, downloadFile, enableRepo, expandPipelineConfig, finishAuthentication, focusOn, getBuild, getBuildGraph, getBuildServiceLog, getBuildServices, getBuildStepLog, getBuildSteps, getCurrentUser, getOrgBuilds, getOrgRepos, getOrgSecret, getOrgSecrets, getPipelineConfig, getPipelineTemplates, getRepo, getRepoBuilds, getRepoBuildsShared, getRepoDeployments, getRepoHooks, getRepoHooksShared, getRepoSchedule, getRepoSchedules, getRepoSecret, getRepoSecrets, getSharedSecret, getSharedSecrets, handleHttpError, logout, pushPath, redeliverHook, repairRepo, replacePath, setRedirect, setTheme, updateFavicon, updateFavorites, updateOrgSecret, updateRepo, updateRepoSchedule, updateRepoSecret, updateSharedSecret + , addAlertError, addAlertSuccess, addDeployment, addOrgSecret, addRepoSchedule, addRepoSecret, addSharedSecret, alertsUpdate, chownRepo, clearRedirect, deleteOrgSecret, deleteRepoSchedule, deleteRepoSecret, deleteSharedSecret, disableRepo, downloadFile, enableRepo, expandPipelineConfig, finishAuthentication, focusOn, getBuild, getBuildGraph, getBuildServiceLog, getBuildServices, getBuildStepLog, getBuildSteps, getCurrentUser, getOrgBuilds, getOrgRepos, getOrgSecret, getOrgSecrets, getPipelineConfig, getPipelineTemplates, getRepo, getRepoBuilds, getRepoBuildsShared, getRepoDeployments, getRepoHooks, getRepoHooksShared, getRepoSchedule, getRepoSchedules, getRepoSecret, getRepoSecrets, getSharedSecret, getSharedSecrets, handleHttpError, logout, pushPath, redeliverHook, repairRepo, replacePath, replaceRouteRemoveTabHistorySkipDomFocus, setRedirect, setTheme, updateFavicon, updateFavorites, updateOrgSecret, updateRepo, updateRepoSchedule, updateRepoSecret, updateSharedSecret ) {-| @@ -374,6 +374,8 @@ getOrgRepos : { baseUrl : String , session : Auth.Session.Session , onResponse : Result (Http.Detailed.Error String) ( Http.Metadata, List Vela.Repository ) -> msg + , pageNumber : Maybe Int + , perPage : Maybe Int , org : String } -> Effect msg @@ -1175,3 +1177,18 @@ focusOn options = downloadFile : { filename : String, content : String, map : String -> String } -> Effect msg downloadFile options = SendSharedMsg <| Shared.Msg.DownloadFile options + + +replaceRouteRemoveTabHistorySkipDomFocus : Route.Route params -> Effect msg +replaceRouteRemoveTabHistorySkipDomFocus route = + if Dict.get "tab_switch" route.query /= Nothing then + replaceRoute + { path = route.path + , query = + route.query + |> Dict.remove "tab_switch" + , hash = route.hash + } + + else + none diff --git a/src/elm/Layouts/Default.elm b/src/elm/Layouts/Default.elm index e965c9ecb..47726e36a 100644 --- a/src/elm/Layouts/Default.elm +++ b/src/elm/Layouts/Default.elm @@ -228,10 +228,7 @@ view props shared route { toContentMsg, model, content } = ] , crumbs = Components.Crumbs.view route.path props.crumbs } - , main_ [ class "content-wrap" ] - (Components.Util.view shared route props.utilButtons - :: content.body - ) + , main_ [ class "content-wrap" ] (Components.Util.view shared route props.utilButtons :: content.body) , Components.Footer.view { toasties = shared.toasties , copyAlertMsg = AddAlertCopiedToClipboard diff --git a/src/elm/Layouts/Default/Build.elm b/src/elm/Layouts/Default/Build.elm index b442c4c77..10b810121 100644 --- a/src/elm/Layouts/Default/Build.elm +++ b/src/elm/Layouts/Default/Build.elm @@ -11,6 +11,7 @@ import Components.Favorites import Components.Help import Components.RecentBuilds import Components.Tabs +import Dict exposing (Dict) import Effect exposing (Effect) import Html exposing (Html) import Http @@ -22,6 +23,7 @@ import Route exposing (Route) import Route.Path import Shared import Time +import Url exposing (Url) import Utils.Errors import Utils.Favicons as Favicons import Utils.Interval as Interval @@ -57,8 +59,8 @@ map fn props = layout : Props contentMsg -> Shared.Model -> Route () -> Layout (Layouts.Default.Props contentMsg) Model Msg contentMsg layout props shared route = Layout.new - { init = init props shared - , update = update props shared + { init = init props shared route + , update = update props shared route , view = view props shared route , subscriptions = subscriptions } @@ -78,12 +80,14 @@ layout props shared route = type alias Model = { build : WebData Vela.Build + , tabHistory : Dict String Url } -init : Props contentMsg -> Shared.Model -> () -> ( Model, Effect Msg ) -init props shared _ = +init : Props contentMsg -> Shared.Model -> Route () -> () -> ( Model, Effect Msg ) +init props shared route _ = ( { build = RemoteData.Loading + , tabHistory = Dict.empty } , Effect.batch [ Effect.getCurrentUser {} @@ -111,7 +115,8 @@ init props shared _ = type Msg - = --BROWSER + = Pls + | --BROWSER OnUrlChanged { from : Route (), to : Route () } -- BUILD | GetBuildResponse (Result (Http.Detailed.Error String) ( Http.Metadata, Vela.Build )) @@ -119,12 +124,22 @@ type Msg | Tick { time : Time.Posix, interval : Interval.Interval } -update : Props contentMsg -> Shared.Model -> Msg -> Model -> ( Model, Effect Msg ) -update props shared msg model = +update : Props contentMsg -> Shared.Model -> Route () -> Msg -> Model -> ( Model, Effect Msg ) +update props shared route msg model = case msg of + Pls -> + let + _ = + Debug.log "Pls" "123" + in + ( model, Effect.none ) + -- BROWSER - OnUrlChanged _ -> - ( model + OnUrlChanged options -> + ( { model + | tabHistory = + model.tabHistory |> Dict.insert (Route.Path.toString options.to.path) options.to.url + } , Effect.batch [ Effect.getRepoBuildsShared { pageNumber = Nothing @@ -141,6 +156,7 @@ update props shared msg model = , repo = props.repo , buildNumber = props.buildNumber } + , Effect.replaceRouteRemoveTabHistorySkipDomFocus route ] ) @@ -214,6 +230,7 @@ view props shared route { toContentMsg, model, content } = , repo = props.repo , buildNumber = props.buildNumber , currentPath = route.path + , tabHistory = model.tabHistory } ] ++ content.body diff --git a/src/elm/Layouts/Default/Org.elm b/src/elm/Layouts/Default/Org.elm index c60003c4f..e58c9dbec 100644 --- a/src/elm/Layouts/Default/Org.elm +++ b/src/elm/Layouts/Default/Org.elm @@ -8,12 +8,16 @@ module Layouts.Default.Org exposing (Model, Msg, Props, layout, map) import Components.Crumbs import Components.Help import Components.Tabs +import Components.Util +import Dict exposing (Dict) import Effect exposing (Effect) import Html exposing (..) import Layout exposing (Layout) import Layouts.Default import Route exposing (Route) +import Route.Path import Shared +import Url exposing (Url) import View exposing (View) @@ -39,22 +43,15 @@ map fn props = layout : Props contentMsg -> Shared.Model -> Route () -> Layout (Layouts.Default.Props contentMsg) Model Msg contentMsg layout props shared route = Layout.new - { init = init shared - , update = update + { init = init shared route + , update = update shared route , view = view props shared route , subscriptions = subscriptions } + |> Layout.withOnUrlChanged OnUrlChanged |> Layout.withParentProps { navButtons = props.navButtons - , utilButtons = - [ Components.Tabs.viewOrgTabs - { org = props.org - , currentPath = route.path - , maybePage = Nothing - , maybePerPage = Nothing - , maybeEvent = Nothing - } - ] + , utilButtons = [] , helpCommands = props.helpCommands , crumbs = props.crumbs , repo = Nothing @@ -66,12 +63,13 @@ layout props shared route = type alias Model = - {} + { tabHistory : Dict String Url } -init : Shared.Model -> () -> ( Model, Effect Msg ) -init shared _ = - ( {} +init : Shared.Model -> Route () -> () -> ( Model, Effect Msg ) +init shared route _ = + ( { tabHistory = Dict.empty + } , Effect.getCurrentUser {} ) @@ -81,15 +79,18 @@ init shared _ = type Msg - = NoOp + = OnUrlChanged { from : Route (), to : Route () } -update : Msg -> Model -> ( Model, Effect Msg ) -update msg model = +update : Shared.Model -> Route () -> Msg -> Model -> ( Model, Effect Msg ) +update shared route msg model = case msg of - NoOp -> - ( model - , Effect.none + OnUrlChanged options -> + ( { model + | tabHistory = + model.tabHistory |> Dict.insert (Route.Path.toString options.to.path) options.to.url + } + , Effect.replaceRouteRemoveTabHistorySkipDomFocus route ) @@ -106,6 +107,15 @@ view : Props contentMsg -> Shared.Model -> Route () -> { toContentMsg : Msg -> c view props shared route { toContentMsg, model, content } = { title = props.org ++ " " ++ content.title , body = - [ Html.span [] content.body - ] + Components.Util.view shared + route + (Components.Tabs.viewOrgTabs + shared + { org = props.org + , currentPath = route.path + , tabHistory = model.tabHistory + } + :: props.utilButtons + ) + :: content.body } diff --git a/src/elm/Layouts/Default/Repo.elm b/src/elm/Layouts/Default/Repo.elm index 85a0b923f..6049f147d 100644 --- a/src/elm/Layouts/Default/Repo.elm +++ b/src/elm/Layouts/Default/Repo.elm @@ -8,15 +8,18 @@ module Layouts.Default.Repo exposing (Model, Msg, Props, layout, map) import Components.Crumbs import Components.Help import Components.Tabs +import Components.Util +import Dict exposing (Dict) import Effect exposing (Effect) import Html exposing (..) import Layout exposing (Layout) import Layouts.Default import Route exposing (Route) +import Route.Path import Shared import Time +import Url exposing (Url) import Utils.Interval as Interval -import Vela import View exposing (View) @@ -44,21 +47,15 @@ map fn props = layout : Props contentMsg -> Shared.Model -> Route () -> Layout (Layouts.Default.Props contentMsg) Model Msg contentMsg layout props shared route = Layout.new - { init = init props shared - , update = update props + { init = init props shared route + , update = update props route , view = view props shared route , subscriptions = subscriptions } + |> Layout.withOnUrlChanged OnUrlChanged |> Layout.withParentProps { navButtons = props.navButtons - , utilButtons = - Components.Tabs.viewRepoTabs - shared - { org = props.org - , repo = props.repo - , currentPath = route.path - } - :: props.utilButtons + , utilButtons = [] , helpCommands = props.helpCommands , crumbs = props.crumbs , repo = Just ( props.org, props.repo ) @@ -70,12 +67,13 @@ layout props shared route = type alias Model = - {} + { tabHistory : Dict String Url } -init : Props contentMsg -> Shared.Model -> () -> ( Model, Effect Msg ) -init props shared _ = - ( {} +init : Props contentMsg -> Shared.Model -> Route () -> () -> ( Model, Effect Msg ) +init props shared route _ = + ( { tabHistory = Dict.empty + } , Effect.batch [ Effect.getCurrentUser {} , Effect.getRepoBuildsShared @@ -101,12 +99,23 @@ init props shared _ = type Msg - = Tick { time : Time.Posix, interval : Interval.Interval } + = --BROWSER + OnUrlChanged { from : Route (), to : Route () } + -- REFRESH + | Tick { time : Time.Posix, interval : Interval.Interval } -update : Props contentMsg -> Msg -> Model -> ( Model, Effect Msg ) -update props msg model = +update : Props contentMsg -> Route () -> Msg -> Model -> ( Model, Effect Msg ) +update props route msg model = case msg of + OnUrlChanged options -> + ( { model + | tabHistory = + model.tabHistory |> Dict.insert (Route.Path.toString options.to.path) options.to.url + } + , Effect.replaceRouteRemoveTabHistorySkipDomFocus route + ) + Tick options -> ( model , Effect.batch @@ -141,5 +150,17 @@ subscriptions model = view : Props contentMsg -> Shared.Model -> Route () -> { toContentMsg : Msg -> contentMsg, content : View contentMsg, model : Model } -> View contentMsg view props shared route { toContentMsg, model, content } = { title = props.org ++ "/" ++ props.repo ++ " " ++ content.title - , body = content.body + , body = + Components.Util.view shared + route + (Components.Tabs.viewRepoTabs + shared + { org = props.org + , repo = props.repo + , currentPath = route.path + , tabHistory = model.tabHistory + } + :: props.utilButtons + ) + :: content.body } diff --git a/src/elm/Pages/Account/Login.elm b/src/elm/Pages/Account/Login.elm index d50b237d4..58dffac9d 100644 --- a/src/elm/Pages/Account/Login.elm +++ b/src/elm/Pages/Account/Login.elm @@ -51,8 +51,8 @@ toLayout : Model -> Layouts.Layout Msg toLayout model = Layouts.Default { navButtons = [] - , utilButtons = [] , helpCommands = [] + , utilButtons = [] , crumbs = [ ( "Account", Nothing ) , ( "Login", Nothing ) diff --git a/src/elm/Pages/Account/Settings.elm b/src/elm/Pages/Account/Settings.elm index c4f6b4774..3eeb457c7 100644 --- a/src/elm/Pages/Account/Settings.elm +++ b/src/elm/Pages/Account/Settings.elm @@ -64,8 +64,8 @@ toLayout : Auth.User -> Model -> Layouts.Layout Msg toLayout user model = Layouts.Default { navButtons = [] - , utilButtons = [] , helpCommands = [] + , utilButtons = [] , crumbs = [ ( "Overview", Just Route.Path.Home ) , ( "My Settings", Nothing ) diff --git a/src/elm/Pages/Account/SourceRepos.elm b/src/elm/Pages/Account/SourceRepos.elm index 839316070..f4793949d 100644 --- a/src/elm/Pages/Account/SourceRepos.elm +++ b/src/elm/Pages/Account/SourceRepos.elm @@ -93,8 +93,8 @@ toLayout user shared model = text "Refresh List" ] ] - , utilButtons = [] , helpCommands = [] + , utilButtons = [] , crumbs = [ ( "Overview", Just Route.Path.Home ) , ( "Account", Nothing ) diff --git a/src/elm/Pages/Org_.elm b/src/elm/Pages/Org_.elm index 6b114f3c1..3bb0a241c 100644 --- a/src/elm/Pages/Org_.elm +++ b/src/elm/Pages/Org_.elm @@ -5,14 +5,18 @@ SPDX-License-Identifier: Apache-2.0 module Pages.Org_ exposing (Model, Msg, page, view) +import Api.Pagination import Auth +import Components.Pager import Components.Repo +import Dict import Effect exposing (Effect) import Html exposing (Html, a, div, h1, p, text) import Html.Attributes exposing (class) import Http import Http.Detailed import Layouts +import LinkHeader exposing (WebLink) import Page exposing (Page) import RemoteData exposing (WebData) import Route exposing (Route) @@ -62,17 +66,21 @@ toLayout user route model = type alias Model = { repos : WebData (List Vela.Repository) + , pager : List WebLink } init : Shared.Model -> Route { org : String } -> () -> ( Model, Effect Msg ) init shared route () = ( { repos = RemoteData.Loading + , pager = [] } , Effect.getOrgRepos { baseUrl = shared.velaAPIBaseURL , session = shared.session , onResponse = GetOrgReposResponse + , pageNumber = Dict.get "page" route.query |> Maybe.andThen String.toInt + , perPage = Dict.get "perPage" route.query |> Maybe.andThen String.toInt , org = route.params.org } ) @@ -85,6 +93,7 @@ init shared route () = type Msg = -- REPOS GetOrgReposResponse (Result (Http.Detailed.Error String) ( Http.Metadata, List Vela.Repository )) + | GotoPage Int -- FAVORITES | ToggleFavorite Vela.Org (Maybe Vela.Repo) -- REFRESH @@ -97,8 +106,11 @@ update shared route msg model = -- REPOS GetOrgReposResponse response -> case response of - Ok ( _, repos ) -> - ( { model | repos = RemoteData.Success repos } + Ok ( meta, repos ) -> + ( { model + | repos = RemoteData.Success repos + , pager = Api.Pagination.get meta.headers + } , Effect.none ) @@ -107,6 +119,26 @@ update shared route msg model = , Effect.handleHttpError { httpError = error } ) + GotoPage pageNumber -> + ( model + , Effect.batch + [ Effect.pushRoute + { path = route.path + , query = + Dict.update "page" (\_ -> Just <| String.fromInt pageNumber) route.query + , hash = route.hash + } + , Effect.getOrgRepos + { baseUrl = shared.velaAPIBaseURL + , session = shared.session + , onResponse = GetOrgReposResponse + , pageNumber = Just pageNumber + , perPage = Dict.get "perPage" route.query |> Maybe.andThen String.toInt + , org = route.params.org + } + ] + ) + -- FAVORITES ToggleFavorite org maybeRepo -> ( model @@ -121,6 +153,8 @@ update shared route msg model = , session = shared.session , onResponse = GetOrgReposResponse , org = route.params.org + , pageNumber = Dict.get "page" route.query |> Maybe.andThen String.toInt + , perPage = Dict.get "perPage" route.query |> Maybe.andThen String.toInt } ) @@ -142,7 +176,13 @@ view : Shared.Model -> Route { org : String } -> Model -> View Msg view shared route model = { title = "Repos" , body = - [ case model.repos of + [ Html.caption + [ class "builds-caption" + ] + [ Html.span [] [] + , Components.Pager.view model.pager Components.Pager.defaultLabels GotoPage + ] + , case model.repos of RemoteData.Success repos -> if List.length repos == 0 then div [] @@ -161,10 +201,10 @@ view shared route model = div [] (List.map (\repository -> viewRepo shared (RemoteData.unwrap [] .favorites shared.user) False repository.org repository.name) repos) RemoteData.Loading -> - Util.largeLoader + Util.smallLoader RemoteData.NotAsked -> - Util.largeLoader + Util.smallLoader RemoteData.Failure _ -> div [ Util.testAttribute "repos-error" ] @@ -172,6 +212,7 @@ view shared route model = [ text "There was an error fetching repos, please refresh or try again later!" ] ] + , Components.Pager.view model.pager Components.Pager.defaultLabels GotoPage ] } diff --git a/src/elm/Pages/Org_/Builds.elm b/src/elm/Pages/Org_/Builds.elm index 3c6674bb1..95e3e86bb 100644 --- a/src/elm/Pages/Org_/Builds.elm +++ b/src/elm/Pages/Org_/Builds.elm @@ -281,7 +281,7 @@ view shared route model = [ class "builds-caption" ] [ span [] [] - , Components.Pager.view model.pager Components.Pager.defaultLabels GotoPage + , Html.div [ class "buttons" ] [ Components.Pager.view model.pager Components.Pager.defaultLabels GotoPage ] ] , Components.Builds.viewHeader { maybeEvent = Dict.get "event" route.query diff --git a/src/elm/Pages/Org_/Repo_/Audit.elm b/src/elm/Pages/Org_/Repo_/Audit.elm index 7cddfbe56..a83b775c8 100644 --- a/src/elm/Pages/Org_/Repo_/Audit.elm +++ b/src/elm/Pages/Org_/Repo_/Audit.elm @@ -93,7 +93,7 @@ type alias Model = init : Shared.Model -> Route { org : String, repo : String } -> () -> ( Model, Effect Msg ) init shared route () = - ( { hooks = RemoteData.Loading + ( { hooks = shared.hooks , pager = [] } , Effect.getRepoHooks @@ -231,9 +231,7 @@ viewHooks shared model hooks = let actions = Just <| - div [ class "buttons" ] - [ Components.Pager.view model.pager Components.Pager.defaultLabels GotoPage - ] + Components.Pager.view model.pager Components.Pager.defaultLabels GotoPage ( noRowsView, rows ) = case hooks of @@ -261,7 +259,7 @@ viewHooks shared model hooks = ) _ -> - ( Util.largeLoader, [] ) + ( Util.smallLoader, [] ) cfg = Components.Table.Config diff --git a/src/elm/Pages/Org_/Repo_/Build_.elm b/src/elm/Pages/Org_/Repo_/Build_.elm index a5ef3f0e3..f5330b3fc 100644 --- a/src/elm/Pages/Org_/Repo_/Build_.elm +++ b/src/elm/Pages/Org_/Repo_/Build_.elm @@ -98,16 +98,26 @@ init shared route () = , focus = Focus.fromString route.hash , logFollow = 0 } - , Effect.getBuildSteps - { baseUrl = shared.velaAPIBaseURL - , session = shared.session - , onResponse = GetBuildStepsResponse - , pageNumber = Nothing - , perPage = Just 100 - , org = route.params.org - , repo = route.params.repo - , buildNumber = route.params.buildNumber - } + , Effect.batch + [ Effect.getBuildSteps + { baseUrl = shared.velaAPIBaseURL + , session = shared.session + , onResponse = + GetBuildStepsResponse + { applyDomFocus = + route.query + |> Dict.get "tab_switch" + |> Maybe.withDefault "false" + |> (==) "false" + } + , pageNumber = Nothing + , perPage = Just 100 + , org = route.params.org + , repo = route.params.repo + , buildNumber = route.params.buildNumber + } + , Effect.none + ] ) @@ -122,7 +132,7 @@ type Msg | PushUrlHash { hash : String } | FocusOn { target : String } -- STEPS - | GetBuildStepsResponse (Result (Http.Detailed.Error String) ( Http.Metadata, List Vela.Step )) + | GetBuildStepsResponse { applyDomFocus : Bool } (Result (Http.Detailed.Error String) ( Http.Metadata, List Vela.Step )) | GetBuildStepsRefreshResponse (Result (Http.Detailed.Error String) ( Http.Metadata, List Vela.Step )) | GetBuildStepLogResponse { step : Vela.Step, applyDomFocus : Bool, previousFocus : Maybe Focus.Focus } (Result (Http.Detailed.Error String) ( Http.Metadata, Vela.Log )) | GetBuildStepLogRefreshResponse { step : Vela.Step } (Result (Http.Detailed.Error String) ( Http.Metadata, Vela.Log )) @@ -175,10 +185,12 @@ update shared route msg model = ) FocusOn options -> - ( model, Effect.focusOn options ) + ( model + , Effect.focusOn options + ) -- STEPS - GetBuildStepsResponse response -> + GetBuildStepsResponse options response -> case response of Ok ( _, steps ) -> ( { model | steps = RemoteData.succeed steps } @@ -189,7 +201,7 @@ update shared route msg model = (\step -> ExpandStep { step = step - , applyDomFocus = True + , applyDomFocus = options.applyDomFocus , previousFocus = Nothing } |> Effect.sendMsg diff --git a/src/elm/Pages/Org_/Repo_/Build_/Graph.elm b/src/elm/Pages/Org_/Repo_/Build_/Graph.elm index 200b73a92..71d0f8ee7 100644 --- a/src/elm/Pages/Org_/Repo_/Build_/Graph.elm +++ b/src/elm/Pages/Org_/Repo_/Build_/Graph.elm @@ -101,14 +101,16 @@ init shared route () = , showServices = True , showSteps = True } - , Effect.getBuildGraph - { baseUrl = shared.velaAPIBaseURL - , session = shared.session - , onResponse = GetBuildGraphResponse { freshDraw = True } - , org = route.params.org - , repo = route.params.repo - , buildNumber = route.params.buildNumber - } + , Effect.batch + [ Effect.getBuildGraph + { baseUrl = shared.velaAPIBaseURL + , session = shared.session + , onResponse = GetBuildGraphResponse { freshDraw = True } + , org = route.params.org + , repo = route.params.repo + , buildNumber = route.params.buildNumber + } + ] ) @@ -499,10 +501,10 @@ view shared route model = ] RemoteData.Loading -> - Util.largeLoader + Util.smallLoader RemoteData.NotAsked -> - Util.largeLoader + Util.smallLoader , Svg.svg [ Svg.Attributes.class "elm-build-graph-root" ] diff --git a/src/elm/Pages/Org_/Repo_/Build_/Pipeline.elm b/src/elm/Pages/Org_/Repo_/Build_/Pipeline.elm index 9db006fc7..606f66909 100644 --- a/src/elm/Pages/Org_/Repo_/Build_/Pipeline.elm +++ b/src/elm/Pages/Org_/Repo_/Build_/Pipeline.elm @@ -102,14 +102,23 @@ init shared route () = (\e -> String.toLower e == "true") , expanding = False } - , Effect.getBuild - { baseUrl = shared.velaAPIBaseURL - , session = shared.session - , onResponse = GetBuildResponse - , org = route.params.org - , repo = route.params.repo - , buildNumber = route.params.buildNumber - } + , Effect.batch + [ Effect.getBuild + { baseUrl = shared.velaAPIBaseURL + , session = shared.session + , onResponse = + GetBuildResponse + { applyDomFocus = + route.query + |> Dict.get "tab_switch" + |> Maybe.withDefault "false" + |> (==) "false" + } + , org = route.params.org + , repo = route.params.repo + , buildNumber = route.params.buildNumber + } + ] ) @@ -118,17 +127,18 @@ init shared route () = type Msg - = -- BROWSER - OnExpandQueryParameterChanged { from : Maybe String, to : Maybe String } + = NoOp + -- BROWSER + | OnExpandQueryParameterChanged { from : Maybe String, to : Maybe String } | PushUrlQueryParameter { key : String, value : String } | OnHashChanged { from : Maybe String, to : Maybe String } | PushUrlHash { hash : String } | FocusOn { target : String } -- BUILD - | GetBuildResponse (Result (Http.Detailed.Error String) ( Http.Metadata, Vela.Build )) + | GetBuildResponse { applyDomFocus : Bool } (Result (Http.Detailed.Error String) ( Http.Metadata, Vela.Build )) -- PIPELINE - | GetBuildPipelineConfigResponse (Result (Http.Detailed.Error String) ( Http.Metadata, Vela.PipelineConfig )) - | GetExpandBuildPipelineConfigResponse (Result (Http.Detailed.Error String) ( Http.Metadata, String )) + | GetBuildPipelineConfigResponse { applyDomFocus : Bool } (Result (Http.Detailed.Error String) ( Http.Metadata, Vela.PipelineConfig )) + | GetExpandBuildPipelineConfigResponse { applyDomFocus : Bool } (Result (Http.Detailed.Error String) ( Http.Metadata, String )) | ToggleExpand | DownloadPipeline { filename : String, content : String, map : String -> String } -- TEMPLATES @@ -139,6 +149,9 @@ type Msg update : Shared.Model -> Route { org : String, repo : String, buildNumber : String } -> Msg -> Model -> ( Model, Effect Msg ) update shared route msg model = case msg of + NoOp -> + ( model, Effect.none ) + -- BROWSER OnExpandQueryParameterChanged options -> let @@ -157,7 +170,7 @@ update shared route msg model = Effect.expandPipelineConfig { baseUrl = shared.velaAPIBaseURL , session = shared.session - , onResponse = GetExpandBuildPipelineConfigResponse + , onResponse = GetExpandBuildPipelineConfigResponse { applyDomFocus = False } , org = route.params.org , repo = route.params.repo , ref = build.commit @@ -167,7 +180,7 @@ update shared route msg model = Effect.getPipelineConfig { baseUrl = shared.velaAPIBaseURL , session = shared.session - , onResponse = GetBuildPipelineConfigResponse + , onResponse = GetBuildPipelineConfigResponse { applyDomFocus = False } , org = route.params.org , repo = route.params.repo , ref = build.commit @@ -177,7 +190,7 @@ update shared route msg model = Effect.getBuild { baseUrl = shared.velaAPIBaseURL , session = shared.session - , onResponse = GetBuildResponse + , onResponse = GetBuildResponse { applyDomFocus = False } , org = route.params.org , repo = route.params.repo , buildNumber = route.params.buildNumber @@ -233,16 +246,18 @@ update shared route msg model = , repo = route.params.repo , buildNumber = route.params.buildNumber } - , query = route.query + , query = route.query |> Dict.remove "focus" , hash = Just options.hash } ) FocusOn options -> - ( model, Effect.focusOn options ) + ( model + , Effect.focusOn options + ) -- BUILD - GetBuildResponse response -> + GetBuildResponse options response -> case response of Ok ( _, build ) -> let @@ -251,7 +266,7 @@ update shared route msg model = Effect.expandPipelineConfig { baseUrl = shared.velaAPIBaseURL , session = shared.session - , onResponse = GetExpandBuildPipelineConfigResponse + , onResponse = GetExpandBuildPipelineConfigResponse { applyDomFocus = options.applyDomFocus } , org = route.params.org , repo = route.params.repo , ref = build.commit @@ -261,7 +276,7 @@ update shared route msg model = Effect.getPipelineConfig { baseUrl = shared.velaAPIBaseURL , session = shared.session - , onResponse = GetBuildPipelineConfigResponse + , onResponse = GetBuildPipelineConfigResponse { applyDomFocus = options.applyDomFocus } , org = route.params.org , repo = route.params.repo , ref = build.commit @@ -287,7 +302,7 @@ update shared route msg model = ) -- PIPELINE - GetBuildPipelineConfigResponse response -> + GetBuildPipelineConfigResponse options response -> case response of Ok ( _, pipeline ) -> ( { model @@ -298,7 +313,7 @@ update shared route msg model = } , expanding = False } - , if Focus.canTarget model.focus then + , if Focus.canTarget model.focus && options.applyDomFocus then FocusOn { target = Focus.toDomTarget model.focus } |> Effect.sendMsg @@ -311,7 +326,7 @@ update shared route msg model = , Effect.handleHttpError { httpError = error } ) - GetExpandBuildPipelineConfigResponse response -> + GetExpandBuildPipelineConfigResponse options response -> case response of Ok ( _, expandedPipeline ) -> ( { model @@ -322,7 +337,12 @@ update shared route msg model = } , expanding = False } - , Effect.none + , if Focus.canTarget model.focus && options.applyDomFocus then + FocusOn { target = Focus.toDomTarget model.focus } + |> Effect.sendMsg + + else + Effect.none ) Err error -> diff --git a/src/elm/Pages/Org_/Repo_/Build_/Services.elm b/src/elm/Pages/Org_/Repo_/Build_/Services.elm index 0605b3b7f..53874a266 100644 --- a/src/elm/Pages/Org_/Repo_/Build_/Services.elm +++ b/src/elm/Pages/Org_/Repo_/Build_/Services.elm @@ -98,16 +98,18 @@ init shared route () = , focus = Focus.fromString route.hash , logFollow = 0 } - , Effect.getBuildServices - { baseUrl = shared.velaAPIBaseURL - , session = shared.session - , onResponse = GetBuildServicesResponse - , pageNumber = Nothing - , perPage = Just 100 - , org = route.params.org - , repo = route.params.repo - , buildNumber = route.params.buildNumber - } + , Effect.batch + [ Effect.getBuildServices + { baseUrl = shared.velaAPIBaseURL + , session = shared.session + , onResponse = GetBuildServicesResponse + , pageNumber = Nothing + , perPage = Just 100 + , org = route.params.org + , repo = route.params.repo + , buildNumber = route.params.buildNumber + } + ] ) diff --git a/src/elm/Pages/Org_/Repo_/Deployments.elm b/src/elm/Pages/Org_/Repo_/Deployments.elm index cff9f257b..bac46bccf 100644 --- a/src/elm/Pages/Org_/Repo_/Deployments.elm +++ b/src/elm/Pages/Org_/Repo_/Deployments.elm @@ -273,7 +273,7 @@ viewDeployments model route = ( viewError error, [] ) _ -> - ( Util.largeLoader, [] ) + ( Util.smallLoader, [] ) cfg = Components.Table.Config diff --git a/src/elm/Pages/Org_/Repo_/Schedules.elm b/src/elm/Pages/Org_/Repo_/Schedules.elm index 291d7c28c..832154c33 100644 --- a/src/elm/Pages/Org_/Repo_/Schedules.elm +++ b/src/elm/Pages/Org_/Repo_/Schedules.elm @@ -78,15 +78,17 @@ init shared route () = ( { schedules = RemoteData.Loading , pager = [] } - , Effect.getRepoSchedules - { baseUrl = shared.velaAPIBaseURL - , session = shared.session - , onResponse = GetRepoSchedulesResponse - , pageNumber = Dict.get "page" route.query |> Maybe.andThen String.toInt - , perPage = Dict.get "perPage" route.query |> Maybe.andThen String.toInt - , org = route.params.org - , repo = route.params.repo - } + , Effect.batch + [ Effect.getRepoSchedules + { baseUrl = shared.velaAPIBaseURL + , session = shared.session + , onResponse = GetRepoSchedulesResponse + , pageNumber = Dict.get "page" route.query |> Maybe.andThen String.toInt + , perPage = Dict.get "perPage" route.query |> Maybe.andThen String.toInt + , org = route.params.org + , repo = route.params.repo + } + ] ) @@ -241,7 +243,7 @@ viewRepoSchedules shared model org repo = ) _ -> - ( Util.largeLoader, [] ) + ( Util.smallLoader, [] ) else ( viewSchedulesNotAllowedSpan