From 8b05bc4f7fe8d41698f5676da4797eabc9093f0d Mon Sep 17 00:00:00 2001 From: wass3r <1301201+wass3r@users.noreply.github.com> Date: Tue, 19 Nov 2024 00:58:21 -0600 Subject: [PATCH] wip --- elm.json | 8 +- src/elm/Api/Endpoint.elm | 6 +- src/elm/Api/Operations.elm | 29 ++ src/elm/Components/Tabs.elm | 5 + src/elm/Effect.elm | 24 +- src/elm/Layouts.elm | 8 +- src/elm/Layouts/Default/Build.elm | 4 + src/elm/Layouts/Default/Repo.elm | 1 + src/elm/Main.elm | 511 ++++++++++--------- src/elm/Main/Pages/Model.elm | 16 +- src/elm/Main/Pages/Msg.elm | 16 +- src/elm/Pages/Org_/Repo_.elm | 8 + src/elm/Pages/Org_/Repo_/Insights.elm | 688 ++++++++++++++++++++++++++ src/elm/Route.elm | 4 +- src/elm/Route/Path.elm | 11 + src/elm/Route/Query.elm | 6 +- src/elm/Shared/Msg.elm | 2 +- src/elm/Utils/Helpers.elm | 50 ++ src/scss/_main.scss | 24 + 19 files changed, 1170 insertions(+), 251 deletions(-) create mode 100644 src/elm/Pages/Org_/Repo_/Insights.elm diff --git a/elm.json b/elm.json index 401a1c798..f8039faf8 100644 --- a/elm.json +++ b/elm.json @@ -26,17 +26,23 @@ "krisajenkins/remotedata": "6.0.1", "pablen/toasty": "1.2.0", "ryan-haskell/date-format": "1.0.0", + "terezka/elm-charts": "4.0.0", "vito/elm-ansi": "9.0.2" }, "indirect": { + "K-Adam/elm-dom": "1.0.0", "avh4/elm-fifo": "1.0.4", + "danhandrea/elm-time-extra": "1.1.0", "elm/parser": "1.1.0", "elm/random": "1.0.0", "elm/regex": "1.0.0", "elm/virtual-dom": "1.0.3", "elm-community/intdict": "3.1.0", + "justinmimbs/date": "4.1.0", + "justinmimbs/time-extra": "1.2.0", "myrho/elm-round": "1.0.5", - "rtfeldman/elm-iso8601-date-strings": "1.1.4" + "rtfeldman/elm-iso8601-date-strings": "1.1.4", + "terezka/intervals": "2.0.2" } }, "test-dependencies": { diff --git a/src/elm/Api/Endpoint.elm b/src/elm/Api/Endpoint.elm index 581a71c81..c2dbe343d 100644 --- a/src/elm/Api/Endpoint.elm +++ b/src/elm/Api/Endpoint.elm @@ -39,7 +39,7 @@ type Endpoint | Hooks (Maybe Pagination.Page) (Maybe Pagination.PerPage) Vela.Org Vela.Repo | Hook Vela.Org Vela.Repo Vela.HookNumber | OrgBuilds (Maybe Pagination.Page) (Maybe Pagination.PerPage) (Maybe Vela.Event) Vela.Org - | Builds (Maybe Pagination.Page) (Maybe Pagination.PerPage) (Maybe Vela.Event) Vela.Org Vela.Repo + | Builds (Maybe Pagination.Page) (Maybe Pagination.PerPage) (Maybe Vela.Event) (Maybe Int) Vela.Org Vela.Repo | Build Vela.Org Vela.Repo Vela.BuildNumber | CancelBuild Vela.Org Vela.Repo Vela.BuildNumber | ApproveBuild Vela.Org Vela.Repo Vela.BuildNumber @@ -106,8 +106,8 @@ toUrl api endpoint = OrgBuilds maybePage maybePerPage maybeEvent org -> url api [ "repos", org, "builds" ] <| Pagination.toQueryParams maybePage maybePerPage ++ [ UB.string "event" <| Maybe.withDefault "" maybeEvent ] - Builds maybePage maybePerPage maybeEvent org repo -> - url api [ "repos", org, repo, "builds" ] <| Pagination.toQueryParams maybePage maybePerPage ++ [ UB.string "event" <| Maybe.withDefault "" maybeEvent ] + Builds maybePage maybePerPage maybeEvent maybeAfter org repo -> + url api [ "repos", org, repo, "builds" ] <| Pagination.toQueryParams maybePage maybePerPage ++ [ UB.string "event" <| Maybe.withDefault "" maybeEvent, UB.int "after" <| Maybe.withDefault 0 maybeAfter ] Build org repo build -> url api [ "repos", org, repo, "builds", build ] [] diff --git a/src/elm/Api/Operations.elm b/src/elm/Api/Operations.elm index a807775c6..31c950f39 100644 --- a/src/elm/Api/Operations.elm +++ b/src/elm/Api/Operations.elm @@ -22,6 +22,7 @@ module Api.Operations exposing , finishAuthentication , getAllBuildServices , getAllBuildSteps + , getAllBuilds , getBuild , getBuildGraph , getBuildServiceLog @@ -279,6 +280,7 @@ getRepoBuilds : , pageNumber : Maybe Int , perPage : Maybe Int , maybeEvent : Maybe String + , maybeAfter : Maybe Int } -> Request (List Vela.Build) getRepoBuilds baseUrl session options = @@ -287,6 +289,7 @@ getRepoBuilds baseUrl session options = options.pageNumber options.perPage options.maybeEvent + options.maybeAfter options.org options.repo ) @@ -684,6 +687,32 @@ getBuildSteps baseUrl session options = |> withAuth session +{-| getAllBuilds : retrieves all builds. +-} +getAllBuilds : + String + -> Session + -> + { a + | org : String + , repo : String + , after : Int + } + -> Request Vela.Build +getAllBuilds baseUrl session options = + get baseUrl + (Api.Endpoint.Builds + (Just 1) + (Just 100) + Nothing + (Just options.after) + options.org + options.repo + ) + Vela.decodeBuild + |> withAuth session + + {-| getAllBuildSteps : retrieves all steps for a build. -} getAllBuildSteps : diff --git a/src/elm/Components/Tabs.elm b/src/elm/Components/Tabs.elm index d5ba6b65b..4fdeacb83 100644 --- a/src/elm/Components/Tabs.elm +++ b/src/elm/Components/Tabs.elm @@ -231,6 +231,11 @@ viewRepoTabs shared props = , isAlerting = False , show = showSchedules } + , { name = "Insights" + , toPath = Route.Path.Org__Repo__Insights { org = props.org, repo = props.repo } + , isAlerting = False + , show = True + } , { name = "Audit" , toPath = Route.Path.Org__Repo__Hooks { org = props.org, repo = props.repo } , isAlerting = auditAlerting diff --git a/src/elm/Effect.elm b/src/elm/Effect.elm index 0e1678869..af7bc7817 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, addFavorites, addOrgSecret, addRepoSchedule, addRepoSecret, addSharedSecret, alertsUpdate, approveBuild, cancelBuild, chownRepo, clearRedirect, deleteOrgSecret, deleteRepoSchedule, deleteRepoSecret, deleteSharedSecret, disableRepo, downloadFile, enableRepo, expandPipelineConfig, finishAuthentication, focusOn, getAllBuildServices, getAllBuildSteps, getBuild, getBuildGraph, getBuildServiceLog, getBuildServices, getBuildStepLog, getBuildSteps, getCurrentUser, getCurrentUserShared, getDashboard, getDashboards, getOrgBuilds, getOrgRepos, getOrgSecret, getOrgSecrets, getPipelineConfig, getPipelineTemplates, getRepo, getRepoBuilds, getRepoBuildsShared, getRepoDeployments, getRepoHooks, getRepoHooksShared, getRepoSchedule, getRepoSchedules, getRepoSecret, getRepoSecrets, getSettings, getSharedSecret, getSharedSecrets, getWorkers, handleHttpError, logout, pushPath, redeliverHook, repairRepo, replacePath, replaceRouteRemoveTabHistorySkipDomFocus, restartBuild, setRedirect, setTheme, updateFavicon, updateFavorite, updateOrgSecret, updateRepo, updateRepoHooksShared, updateRepoSchedule, updateRepoSecret, updateSettings, updateSharedSecret, updateSourceReposShared + , addAlertError, addAlertSuccess, addDeployment, addFavorites, addOrgSecret, addRepoSchedule, addRepoSecret, addSharedSecret, alertsUpdate, approveBuild, cancelBuild, chownRepo, clearRedirect, deleteOrgSecret, deleteRepoSchedule, deleteRepoSecret, deleteSharedSecret, disableRepo, downloadFile, enableRepo, expandPipelineConfig, finishAuthentication, focusOn, getAllBuildServices, getAllBuildSteps, getAllBuilds, getBuild, getBuildGraph, getBuildServiceLog, getBuildServices, getBuildStepLog, getBuildSteps, getCurrentUser, getCurrentUserShared, getDashboard, getDashboards, getOrgBuilds, getOrgRepos, getOrgSecret, getOrgSecrets, getPipelineConfig, getPipelineTemplates, getRepo, getRepoBuilds, getRepoBuildsShared, getRepoDeployments, getRepoHooks, getRepoHooksShared, getRepoSchedule, getRepoSchedules, getRepoSecret, getRepoSecrets, getSettings, getSharedSecret, getSharedSecrets, getWorkers, handleHttpError, logout, pushPath, redeliverHook, repairRepo, replacePath, replaceRouteRemoveTabHistorySkipDomFocus, restartBuild, setRedirect, setTheme, updateFavicon, updateFavorite, updateOrgSecret, updateRepo, updateRepoHooksShared, updateRepoSchedule, updateRepoSecret, updateSettings, updateSharedSecret, updateSourceReposShared ) {-| @@ -437,6 +437,7 @@ getRepoBuildsShared : { pageNumber : Maybe Int , perPage : Maybe Int , maybeEvent : Maybe String + , maybeAfter : Maybe Int , org : String , repo : String } @@ -796,6 +797,26 @@ getBuildSteps options = |> sendCmd +getAllBuilds : + { baseUrl : String + , session : Auth.Session.Session + , onResponse : Result (Http.Detailed.Error String) ( Http.Metadata, List Vela.Build ) -> msg + , org : String + , repo : String + , after : Int + } + -> Effect msg +getAllBuilds options = + Api.tryAll + options.onResponse + (Api.Operations.getAllBuilds + options.baseUrl + options.session + options + ) + |> sendCmd + + getAllBuildSteps : { baseUrl : String , session : Auth.Session.Session @@ -1303,6 +1324,7 @@ getRepoBuilds : , pageNumber : Maybe Int , perPage : Maybe Int , maybeEvent : Maybe String + , maybeAfter : Maybe Int , org : String , repo : String } diff --git a/src/elm/Layouts.elm b/src/elm/Layouts.elm index 2fcfe065d..c0ce725f3 100644 --- a/src/elm/Layouts.elm +++ b/src/elm/Layouts.elm @@ -27,13 +27,13 @@ map fn layout = Default data Default_Admin data -> - Default_Admin (Layouts.Default.Admin.map fn data) + Default_Admin (Layouts.Default.Admin.map fn data) Default_Build data -> - Default_Build (Layouts.Default.Build.map fn data) + Default_Build (Layouts.Default.Build.map fn data) Default_Org data -> - Default_Org (Layouts.Default.Org.map fn data) + Default_Org (Layouts.Default.Org.map fn data) Default_Repo data -> - Default_Repo (Layouts.Default.Repo.map fn data) + Default_Repo (Layouts.Default.Repo.map fn data) diff --git a/src/elm/Layouts/Default/Build.elm b/src/elm/Layouts/Default/Build.elm index 9c1aef9bd..98879c7bd 100644 --- a/src/elm/Layouts/Default/Build.elm +++ b/src/elm/Layouts/Default/Build.elm @@ -105,6 +105,7 @@ init props shared route _ = { pageNumber = Nothing , perPage = Nothing , maybeEvent = Nothing + , maybeAfter = Nothing , org = props.org , repo = props.repo } @@ -157,6 +158,7 @@ update props shared route msg model = { pageNumber = Nothing , perPage = Nothing , maybeEvent = Nothing + , maybeAfter = Nothing , org = props.org , repo = props.repo } @@ -225,6 +227,7 @@ update props shared route msg model = { pageNumber = Nothing , perPage = Nothing , maybeEvent = Nothing + , maybeAfter = Nothing , org = props.org , repo = props.repo } @@ -342,6 +345,7 @@ update props shared route msg model = { pageNumber = Nothing , perPage = Nothing , maybeEvent = Nothing + , maybeAfter = Nothing , org = props.org , repo = props.repo } diff --git a/src/elm/Layouts/Default/Repo.elm b/src/elm/Layouts/Default/Repo.elm index 3727ff4ad..423dcfcb7 100644 --- a/src/elm/Layouts/Default/Repo.elm +++ b/src/elm/Layouts/Default/Repo.elm @@ -93,6 +93,7 @@ init props shared route _ = { pageNumber = Nothing , perPage = Nothing , maybeEvent = Nothing + , maybeAfter = Nothing , org = props.org , repo = props.repo } diff --git a/src/elm/Main.elm b/src/elm/Main.elm index d99ca23a9..572b653bc 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -28,6 +28,7 @@ import Main.Pages.Model import Main.Pages.Msg import Maybe.Extra import Page +import Pages.Home_ import Pages.Account.Authenticate import Pages.Account.Login import Pages.Account.Logout @@ -45,25 +46,26 @@ import Pages.Dash.Secrets.Engine_.Shared.Org_.Team_.Add import Pages.Dash.Secrets.Engine_.Shared.Org_.Team_.Name_ import Pages.Dashboards import Pages.Dashboards.Dashboard_ -import Pages.Home_ -import Pages.NotFound_ +import Pages.Status.Workers import Pages.Org_ import Pages.Org_.Builds import Pages.Org_.Repo_ -import Pages.Org_.Repo_.Build_ -import Pages.Org_.Repo_.Build_.Graph -import Pages.Org_.Repo_.Build_.Pipeline -import Pages.Org_.Repo_.Build_.Services import Pages.Org_.Repo_.Deployments import Pages.Org_.Repo_.Deployments.Add import Pages.Org_.Repo_.Hooks +import Pages.Org_.Repo_.Insights import Pages.Org_.Repo_.Pulls import Pages.Org_.Repo_.Schedules import Pages.Org_.Repo_.Schedules.Add import Pages.Org_.Repo_.Schedules.Name_ import Pages.Org_.Repo_.Settings import Pages.Org_.Repo_.Tags -import Pages.Status.Workers +import Pages.Org_.Repo_.Build_ +import Pages.Org_.Repo_.Build_.Graph +import Pages.Org_.Repo_.Build_.Pipeline +import Pages.Org_.Repo_.Build_.Services +import Pages.NotFound_ +import Pages.NotFound_ import Route exposing (Route) import Route.Path import Shared @@ -117,10 +119,10 @@ init json url key = , shared = sharedModel } , Cmd.batch - [ Tuple.second page - , layout |> Maybe.map Tuple.second |> Maybe.withDefault Cmd.none - , fromSharedEffect { key = key, url = url, shared = sharedModel } sharedEffect - ] + [ Tuple.second page + , layout |> Maybe.map Tuple.second |> Maybe.withDefault Cmd.none + , fromSharedEffect { key = key, url = url, shared = sharedModel } sharedEffect + ] ) @@ -256,10 +258,9 @@ initLayout model layout = Layout.init defaultLayout () in ( Main.Layouts.Model.Default_Admin { default = defaultLayoutModel, admin = adminLayoutModel } - , Cmd.batch - [ fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default_Admin adminLayoutEffect) - , fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default defaultLayoutEffect) - ] + , Cmd.batch [ fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default_Admin adminLayoutEffect) + , fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default defaultLayoutEffect) + ] ) ( Layouts.Default_Build props, Just (Main.Layouts.Model.Default existing) ) -> @@ -350,10 +351,9 @@ initLayout model layout = Layout.init defaultLayout () in ( Main.Layouts.Model.Default_Build { default = defaultLayoutModel, build = buildLayoutModel } - , Cmd.batch - [ fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default_Build buildLayoutEffect) - , fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default defaultLayoutEffect) - ] + , Cmd.batch [ fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default_Build buildLayoutEffect) + , fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default defaultLayoutEffect) + ] ) ( Layouts.Default_Org props, Just (Main.Layouts.Model.Default existing) ) -> @@ -444,10 +444,9 @@ initLayout model layout = Layout.init defaultLayout () in ( Main.Layouts.Model.Default_Org { default = defaultLayoutModel, org = orgLayoutModel } - , Cmd.batch - [ fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default_Org orgLayoutEffect) - , fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default defaultLayoutEffect) - ] + , Cmd.batch [ fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default_Org orgLayoutEffect) + , fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default defaultLayoutEffect) + ] ) ( Layouts.Default_Repo props, Just (Main.Layouts.Model.Default existing) ) -> @@ -538,10 +537,9 @@ initLayout model layout = Layout.init defaultLayout () in ( Main.Layouts.Model.Default_Repo { default = defaultLayoutModel, repo = repoLayoutModel } - , Cmd.batch - [ fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default_Repo repoLayoutEffect) - , fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default defaultLayoutEffect) - ] + , Cmd.batch [ fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default_Repo repoLayoutEffect) + , fromLayoutEffect model (Effect.map Main.Layouts.Msg.Default defaultLayoutEffect) + ] ) @@ -560,12 +558,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth Main.Pages.Model.Home_ (Effect.map Main.Pages.Msg.Home_ >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Home_ >> Page)) |> Maybe.map (initLayout model) @@ -581,12 +579,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth Main.Pages.Model.Account_Authenticate (Effect.map Main.Pages.Msg.Account_Authenticate >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Account_Authenticate >> Page)) |> Maybe.map (initLayout model) @@ -601,12 +599,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth Main.Pages.Model.Account_Login (Effect.map Main.Pages.Msg.Account_Login >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Account_Login >> Page)) |> Maybe.map (initLayout model) @@ -621,12 +619,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth Main.Pages.Model.Account_Logout (Effect.map Main.Pages.Msg.Account_Logout >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Account_Logout >> Page)) |> Maybe.map (initLayout model) @@ -644,12 +642,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth Main.Pages.Model.Account_Settings (Effect.map Main.Pages.Msg.Account_Settings >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Account_Settings >> Page)) |> Maybe.map (initLayout model) @@ -668,12 +666,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth Main.Pages.Model.Account_SourceRepos (Effect.map Main.Pages.Msg.Account_SourceRepos >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Account_SourceRepos >> Page)) |> Maybe.map (initLayout model) @@ -692,12 +690,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth Main.Pages.Model.Admin_Settings (Effect.map Main.Pages.Msg.Admin_Settings >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Admin_Settings >> Page)) |> Maybe.map (initLayout model) @@ -716,12 +714,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Dash_Secrets_Engine__Org_Org_ params) (Effect.map Main.Pages.Msg.Dash_Secrets_Engine__Org_Org_ >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Dash_Secrets_Engine__Org_Org_ >> Page)) |> Maybe.map (initLayout model) @@ -740,12 +738,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Dash_Secrets_Engine__Org_Org__Add params) (Effect.map Main.Pages.Msg.Dash_Secrets_Engine__Org_Org__Add >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Dash_Secrets_Engine__Org_Org__Add >> Page)) |> Maybe.map (initLayout model) @@ -764,12 +762,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Dash_Secrets_Engine__Org_Org__Name_ params) (Effect.map Main.Pages.Msg.Dash_Secrets_Engine__Org_Org__Name_ >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Dash_Secrets_Engine__Org_Org__Name_ >> Page)) |> Maybe.map (initLayout model) @@ -788,12 +786,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Dash_Secrets_Engine__Repo_Org__Repo_ params) (Effect.map Main.Pages.Msg.Dash_Secrets_Engine__Repo_Org__Repo_ >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Dash_Secrets_Engine__Repo_Org__Repo_ >> Page)) |> Maybe.map (initLayout model) @@ -812,12 +810,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Dash_Secrets_Engine__Repo_Org__Repo__Add params) (Effect.map Main.Pages.Msg.Dash_Secrets_Engine__Repo_Org__Repo__Add >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Dash_Secrets_Engine__Repo_Org__Repo__Add >> Page)) |> Maybe.map (initLayout model) @@ -836,12 +834,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Dash_Secrets_Engine__Repo_Org__Repo__Name_ params) (Effect.map Main.Pages.Msg.Dash_Secrets_Engine__Repo_Org__Repo__Name_ >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Dash_Secrets_Engine__Repo_Org__Repo__Name_ >> Page)) |> Maybe.map (initLayout model) @@ -860,12 +858,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Dash_Secrets_Engine__Shared_Org__Team_ params) (Effect.map Main.Pages.Msg.Dash_Secrets_Engine__Shared_Org__Team_ >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Dash_Secrets_Engine__Shared_Org__Team_ >> Page)) |> Maybe.map (initLayout model) @@ -884,12 +882,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Dash_Secrets_Engine__Shared_Org__Team__Add params) (Effect.map Main.Pages.Msg.Dash_Secrets_Engine__Shared_Org__Team__Add >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Dash_Secrets_Engine__Shared_Org__Team__Add >> Page)) |> Maybe.map (initLayout model) @@ -908,12 +906,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Dash_Secrets_Engine__Shared_Org__Team__Name_ params) (Effect.map Main.Pages.Msg.Dash_Secrets_Engine__Shared_Org__Team__Name_ >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Dash_Secrets_Engine__Shared_Org__Team__Name_ >> Page)) |> Maybe.map (initLayout model) @@ -932,12 +930,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth Main.Pages.Model.Dashboards (Effect.map Main.Pages.Msg.Dashboards >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Dashboards >> Page)) |> Maybe.map (initLayout model) @@ -956,12 +954,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Dashboards_Dashboard_ params) (Effect.map Main.Pages.Msg.Dashboards_Dashboard_ >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Dashboards_Dashboard_ >> Page)) |> Maybe.map (initLayout model) @@ -980,12 +978,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth Main.Pages.Model.Status_Workers (Effect.map Main.Pages.Msg.Status_Workers >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Status_Workers >> Page)) |> Maybe.map (initLayout model) @@ -1004,12 +1002,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org_ params) (Effect.map Main.Pages.Msg.Org_ >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org_ >> Page)) |> Maybe.map (initLayout model) @@ -1028,12 +1026,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org__Builds params) (Effect.map Main.Pages.Msg.Org__Builds >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Builds >> Page)) |> Maybe.map (initLayout model) @@ -1052,12 +1050,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org__Repo_ params) (Effect.map Main.Pages.Msg.Org__Repo_ >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo_ >> Page)) |> Maybe.map (initLayout model) @@ -1076,12 +1074,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org__Repo__Deployments params) (Effect.map Main.Pages.Msg.Org__Repo__Deployments >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Deployments >> Page)) |> Maybe.map (initLayout model) @@ -1100,12 +1098,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org__Repo__Deployments_Add params) (Effect.map Main.Pages.Msg.Org__Repo__Deployments_Add >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Deployments_Add >> Page)) |> Maybe.map (initLayout model) @@ -1124,18 +1122,42 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org__Repo__Hooks params) (Effect.map Main.Pages.Msg.Org__Repo__Hooks >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Hooks >> Page)) |> Maybe.map (initLayout model) } ) + Route.Path.Org__Repo__Insights params -> + runWhenAuthenticatedWithLayout + model + (\user -> + let + page : Page.Page Pages.Org_.Repo_.Insights.Model Pages.Org_.Repo_.Insights.Msg + page = + Pages.Org_.Repo_.Insights.page user model.shared (Route.fromUrl params model.url) + + ( pageModel, pageEffect ) = + Page.init page () + in + { page = + Tuple.mapBoth + (Main.Pages.Model.Org__Repo__Insights params) + (Effect.map Main.Pages.Msg.Org__Repo__Insights >> fromPageEffect model) + ( pageModel, pageEffect ) + , layout = + Page.layout pageModel page + |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Insights >> Page)) + |> Maybe.map (initLayout model) + } + ) + Route.Path.Org__Repo__Pulls params -> let page : Page.Page Pages.Org_.Repo_.Pulls.Model Pages.Org_.Repo_.Pulls.Msg @@ -1145,12 +1167,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org__Repo__Pulls params) (Effect.map Main.Pages.Msg.Org__Repo__Pulls >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Pulls >> Page)) |> Maybe.map (initLayout model) @@ -1168,12 +1190,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org__Repo__Schedules params) (Effect.map Main.Pages.Msg.Org__Repo__Schedules >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Schedules >> Page)) |> Maybe.map (initLayout model) @@ -1192,12 +1214,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org__Repo__Schedules_Add params) (Effect.map Main.Pages.Msg.Org__Repo__Schedules_Add >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Schedules_Add >> Page)) |> Maybe.map (initLayout model) @@ -1216,12 +1238,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org__Repo__Schedules_Name_ params) (Effect.map Main.Pages.Msg.Org__Repo__Schedules_Name_ >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Schedules_Name_ >> Page)) |> Maybe.map (initLayout model) @@ -1240,12 +1262,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org__Repo__Settings params) (Effect.map Main.Pages.Msg.Org__Repo__Settings >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Settings >> Page)) |> Maybe.map (initLayout model) @@ -1261,12 +1283,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org__Repo__Tags params) (Effect.map Main.Pages.Msg.Org__Repo__Tags >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Tags >> Page)) |> Maybe.map (initLayout model) @@ -1284,12 +1306,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org__Repo__Build_ params) (Effect.map Main.Pages.Msg.Org__Repo__Build_ >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Build_ >> Page)) |> Maybe.map (initLayout model) @@ -1308,12 +1330,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org__Repo__Build__Graph params) (Effect.map Main.Pages.Msg.Org__Repo__Build__Graph >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Build__Graph >> Page)) |> Maybe.map (initLayout model) @@ -1332,12 +1354,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org__Repo__Build__Pipeline params) (Effect.map Main.Pages.Msg.Org__Repo__Build__Pipeline >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Build__Pipeline >> Page)) |> Maybe.map (initLayout model) @@ -1356,12 +1378,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth (Main.Pages.Model.Org__Repo__Build__Services params) (Effect.map Main.Pages.Msg.Org__Repo__Build__Services >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Build__Services >> Page)) |> Maybe.map (initLayout model) @@ -1377,12 +1399,12 @@ initPageAndLayout model = ( pageModel, pageEffect ) = Page.init page () in - { page = + { page = Tuple.mapBoth Main.Pages.Model.NotFound_ (Effect.map Main.Pages.Msg.NotFound_ >> fromPageEffect model) ( pageModel, pageEffect ) - , layout = + , layout = Page.layout pageModel page |> Maybe.map (Layouts.map (Main.Pages.Msg.NotFound_ >> Page)) |> Maybe.map (initLayout model) @@ -1421,7 +1443,7 @@ runWhenAuthenticatedWithLayout model toRecord = toRecord user Auth.Action.LoadCustomPage -> - { page = + { page = ( Main.Pages.Model.Loading_ , Cmd.none ) @@ -1429,35 +1451,35 @@ runWhenAuthenticatedWithLayout model toRecord = } Auth.Action.ReplaceRoute options -> - { page = + { page = ( Main.Pages.Model.Redirecting_ , Cmd.batch - [ toCmd (Effect.replaceRoute options) - , Maybe.Extra.unwrap - Cmd.none - (\from -> Interop.setRedirect <| Json.Encode.string from) - (Dict.get "from" options.query) - ] + [ toCmd (Effect.replaceRoute options) + , Maybe.Extra.unwrap + Cmd.none + (\from -> Interop.setRedirect <| Json.Encode.string from) + (Dict.get "from" options.query) + ] ) , layout = Nothing } Auth.Action.PushRoute options -> - { page = + { page = ( Main.Pages.Model.Redirecting_ , Cmd.batch - [ toCmd (Effect.pushRoute options) - , Maybe.Extra.unwrap - Cmd.none - (\from -> Interop.setRedirect <| Json.Encode.string from) - (Dict.get "from" options.query) - ] + [ toCmd (Effect.pushRoute options) + , Maybe.Extra.unwrap + Cmd.none + (\from -> Interop.setRedirect <| Json.Encode.string from) + (Dict.get "from" options.query) + ] ) , layout = Nothing } Auth.Action.LoadExternalUrl externalUrl -> - { page = + { page = ( Main.Pages.Model.Redirecting_ , Browser.Navigation.load externalUrl ) @@ -1504,16 +1526,15 @@ update msg model = in ( newModel , Cmd.batch - [ toPageUrlHookCmd newModel - { from = Route.fromUrl () model.url - , to = Route.fromUrl () newModel.url - } - , toLayoutUrlHookCmd model - newModel - { from = Route.fromUrl () model.url - , to = Route.fromUrl () newModel.url - } - ] + [ toPageUrlHookCmd newModel + { from = Route.fromUrl () model.url + , to = Route.fromUrl () newModel.url + } + , toLayoutUrlHookCmd model newModel + { from = Route.fromUrl () model.url + , to = Route.fromUrl () newModel.url + } + ] ) else @@ -1537,14 +1558,13 @@ update msg model = in ( newModel , Cmd.batch - [ pageCmd - , layoutCmd - , toLayoutUrlHookCmd model - newModel - { from = Route.fromUrl () model.url - , to = Route.fromUrl () newModel.url - } - ] + [ pageCmd + , layoutCmd + , toLayoutUrlHookCmd model newModel + { from = Route.fromUrl () model.url + , to = Route.fromUrl () newModel.url + } + ] ) Page pageMsg -> @@ -1575,7 +1595,7 @@ update msg model = , Auth.onPageLoad sharedModel (Route.fromUrl () model.url) ) in - if isAuthProtected (Route.fromUrl () model.url).path && hasActionTypeChanged oldAction newAction then + if isAuthProtected (Route.fromUrl () model.url).path && (hasActionTypeChanged oldAction newAction) then let { layout, page } = initPageAndLayout { key = model.key, shared = sharedModel, url = model.url, layout = model.layout } @@ -1590,10 +1610,10 @@ update msg model = in ( { model | shared = sharedModel, page = pageModel, layout = layoutModel } , Cmd.batch - [ pageCmd - , layoutCmd - , fromSharedEffect { model | shared = sharedModel } sharedEffect - ] + [ pageCmd + , layoutCmd + , fromSharedEffect { model | shared = sharedModel } sharedEffect + ] ) else @@ -1604,8 +1624,8 @@ update msg model = Batch messages -> ( model , messages - |> List.map (Task.succeed >> Task.perform identity) - |> Cmd.batch + |> List.map (Task.succeed >> Task.perform identity) + |> Cmd.batch ) @@ -1850,6 +1870,16 @@ updateFromPage msg model = (Page.update (Pages.Org_.Repo_.Hooks.page user model.shared (Route.fromUrl params model.url)) pageMsg pageModel) ) + ( Main.Pages.Msg.Org__Repo__Insights pageMsg, Main.Pages.Model.Org__Repo__Insights params pageModel ) -> + runWhenAuthenticated + model + (\user -> + Tuple.mapBoth + (Main.Pages.Model.Org__Repo__Insights params) + (Effect.map Main.Pages.Msg.Org__Repo__Insights >> fromPageEffect model) + (Page.update (Pages.Org_.Repo_.Insights.page user model.shared (Route.fromUrl params model.url)) pageMsg pageModel) + ) + ( Main.Pages.Msg.Org__Repo__Pulls pageMsg, Main.Pages.Model.Org__Repo__Pulls params pageModel ) -> Tuple.mapBoth (Main.Pages.Model.Org__Repo__Pulls params) @@ -2195,6 +2225,12 @@ toLayoutFromPage model = |> Maybe.andThen (Page.layout pageModel) |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Hooks >> Page)) + Main.Pages.Model.Org__Repo__Insights params pageModel -> + Route.fromUrl params model.url + |> toAuthProtectedPage model Pages.Org_.Repo_.Insights.page + |> Maybe.andThen (Page.layout pageModel) + |> Maybe.map (Layouts.map (Main.Pages.Msg.Org__Repo__Insights >> Page)) + Main.Pages.Model.Org__Repo__Pulls params pageModel -> Route.fromUrl params model.url |> Pages.Org_.Repo_.Pulls.page model.shared @@ -2296,7 +2332,7 @@ hasActionTypeChanged oldAction newAction = ( Auth.Action.LoadExternalUrl _, Auth.Action.LoadExternalUrl _ ) -> False - ( _, _ ) -> + ( _, _ ) -> True @@ -2519,6 +2555,15 @@ subscriptions model = ) (Auth.onPageLoad model.shared (Route.fromUrl () model.url)) + Main.Pages.Model.Org__Repo__Insights params pageModel -> + Auth.Action.subscriptions + (\user -> + Page.subscriptions (Pages.Org_.Repo_.Insights.page user model.shared (Route.fromUrl params model.url)) pageModel + |> Sub.map Main.Pages.Msg.Org__Repo__Insights + |> Sub.map Page + ) + (Auth.onPageLoad model.shared (Route.fromUrl () model.url)) + Main.Pages.Model.Org__Repo__Pulls params pageModel -> Page.subscriptions (Pages.Org_.Repo_.Pulls.page model.shared (Route.fromUrl params model.url)) pageModel |> Sub.map Main.Pages.Msg.Org__Repo__Pulls @@ -2636,11 +2681,11 @@ subscriptions model = in Sub.batch [ Layout.subscriptions (Layouts.Default.layout defaultProps model.shared route) layoutModel.default - |> Sub.map Main.Layouts.Msg.Default - |> Sub.map Layout + |> Sub.map Main.Layouts.Msg.Default + |> Sub.map Layout , Layout.subscriptions (Layouts.Default.Admin.layout props model.shared route) layoutModel.admin - |> Sub.map Main.Layouts.Msg.Default_Admin - |> Sub.map Layout + |> Sub.map Main.Layouts.Msg.Default_Admin + |> Sub.map Layout ] ( Just (Layouts.Default_Build props), Just (Main.Layouts.Model.Default_Build layoutModel) ) -> @@ -2651,11 +2696,11 @@ subscriptions model = in Sub.batch [ Layout.subscriptions (Layouts.Default.layout defaultProps model.shared route) layoutModel.default - |> Sub.map Main.Layouts.Msg.Default - |> Sub.map Layout + |> Sub.map Main.Layouts.Msg.Default + |> Sub.map Layout , Layout.subscriptions (Layouts.Default.Build.layout props model.shared route) layoutModel.build - |> Sub.map Main.Layouts.Msg.Default_Build - |> Sub.map Layout + |> Sub.map Main.Layouts.Msg.Default_Build + |> Sub.map Layout ] ( Just (Layouts.Default_Org props), Just (Main.Layouts.Model.Default_Org layoutModel) ) -> @@ -2666,11 +2711,11 @@ subscriptions model = in Sub.batch [ Layout.subscriptions (Layouts.Default.layout defaultProps model.shared route) layoutModel.default - |> Sub.map Main.Layouts.Msg.Default - |> Sub.map Layout + |> Sub.map Main.Layouts.Msg.Default + |> Sub.map Layout , Layout.subscriptions (Layouts.Default.Org.layout props model.shared route) layoutModel.org - |> Sub.map Main.Layouts.Msg.Default_Org - |> Sub.map Layout + |> Sub.map Main.Layouts.Msg.Default_Org + |> Sub.map Layout ] ( Just (Layouts.Default_Repo props), Just (Main.Layouts.Model.Default_Repo layoutModel) ) -> @@ -2681,11 +2726,11 @@ subscriptions model = in Sub.batch [ Layout.subscriptions (Layouts.Default.layout defaultProps model.shared route) layoutModel.default - |> Sub.map Main.Layouts.Msg.Default - |> Sub.map Layout + |> Sub.map Main.Layouts.Msg.Default + |> Sub.map Layout , Layout.subscriptions (Layouts.Default.Repo.layout props model.shared route) layoutModel.repo - |> Sub.map Main.Layouts.Msg.Default_Repo - |> Sub.map Layout + |> Sub.map Main.Layouts.Msg.Default_Repo + |> Sub.map Layout ] _ -> @@ -2693,7 +2738,7 @@ subscriptions model = in Sub.batch [ Shared.subscriptions route model.shared - |> Sub.map Shared + |> Sub.map Shared , subscriptionsFromPage , subscriptionsFromLayout ] @@ -2743,7 +2788,7 @@ toView model = (Layouts.Default.layout defaultProps model.shared route) { model = layoutModel.default , toContentMsg = Main.Layouts.Msg.Default >> Layout - , content = + , content = Layout.view (Layouts.Default.Admin.layout props model.shared route) { model = layoutModel.admin @@ -2762,7 +2807,7 @@ toView model = (Layouts.Default.layout defaultProps model.shared route) { model = layoutModel.default , toContentMsg = Main.Layouts.Msg.Default >> Layout - , content = + , content = Layout.view (Layouts.Default.Build.layout props model.shared route) { model = layoutModel.build @@ -2781,7 +2826,7 @@ toView model = (Layouts.Default.layout defaultProps model.shared route) { model = layoutModel.default , toContentMsg = Main.Layouts.Msg.Default >> Layout - , content = + , content = Layout.view (Layouts.Default.Org.layout props model.shared route) { model = layoutModel.org @@ -2800,7 +2845,7 @@ toView model = (Layouts.Default.layout defaultProps model.shared route) { model = layoutModel.default , toContentMsg = Main.Layouts.Msg.Default >> Layout - , content = + , content = Layout.view (Layouts.Default.Repo.layout props model.shared route) { model = layoutModel.repo @@ -3029,6 +3074,15 @@ viewPage model = ) (Auth.onPageLoad model.shared (Route.fromUrl () model.url)) + Main.Pages.Model.Org__Repo__Insights params pageModel -> + Auth.Action.view (View.map never (Auth.viewCustomPage model.shared (Route.fromUrl () model.url))) + (\user -> + Page.view (Pages.Org_.Repo_.Insights.page user model.shared (Route.fromUrl params model.url)) pageModel + |> View.map Main.Pages.Msg.Org__Repo__Insights + |> View.map Page + ) + (Auth.onPageLoad model.shared (Route.fromUrl () model.url)) + Main.Pages.Model.Org__Repo__Pulls params pageModel -> Page.view (Pages.Org_.Repo_.Pulls.page model.shared (Route.fromUrl params model.url)) pageModel |> View.map Main.Pages.Msg.Org__Repo__Pulls @@ -3183,7 +3237,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Home_ pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Home_.page user model.shared (Route.fromUrl () model.url)) + Page.toUrlMessages routes (Pages.Home_.page user model.shared (Route.fromUrl () model.url)) |> List.map Main.Pages.Msg.Home_ |> List.map Page |> toCommands @@ -3191,19 +3245,19 @@ toPageUrlHookCmd model routes = (Auth.onPageLoad model.shared (Route.fromUrl () model.url)) Main.Pages.Model.Account_Authenticate pageModel -> - Page.toUrlMessages routes (Pages.Account.Authenticate.page model.shared (Route.fromUrl () model.url)) + Page.toUrlMessages routes (Pages.Account.Authenticate.page model.shared (Route.fromUrl () model.url)) |> List.map Main.Pages.Msg.Account_Authenticate |> List.map Page |> toCommands Main.Pages.Model.Account_Login pageModel -> - Page.toUrlMessages routes (Pages.Account.Login.page model.shared (Route.fromUrl () model.url)) + Page.toUrlMessages routes (Pages.Account.Login.page model.shared (Route.fromUrl () model.url)) |> List.map Main.Pages.Msg.Account_Login |> List.map Page |> toCommands Main.Pages.Model.Account_Logout pageModel -> - Page.toUrlMessages routes (Pages.Account.Logout.page model.shared (Route.fromUrl () model.url)) + Page.toUrlMessages routes (Pages.Account.Logout.page model.shared (Route.fromUrl () model.url)) |> List.map Main.Pages.Msg.Account_Logout |> List.map Page |> toCommands @@ -3211,7 +3265,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Account_Settings pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Account.Settings.page user model.shared (Route.fromUrl () model.url)) + Page.toUrlMessages routes (Pages.Account.Settings.page user model.shared (Route.fromUrl () model.url)) |> List.map Main.Pages.Msg.Account_Settings |> List.map Page |> toCommands @@ -3221,7 +3275,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Account_SourceRepos pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Account.SourceRepos.page user model.shared (Route.fromUrl () model.url)) + Page.toUrlMessages routes (Pages.Account.SourceRepos.page user model.shared (Route.fromUrl () model.url)) |> List.map Main.Pages.Msg.Account_SourceRepos |> List.map Page |> toCommands @@ -3231,7 +3285,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Admin_Settings pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Admin.Settings.page user model.shared (Route.fromUrl () model.url)) + Page.toUrlMessages routes (Pages.Admin.Settings.page user model.shared (Route.fromUrl () model.url)) |> List.map Main.Pages.Msg.Admin_Settings |> List.map Page |> toCommands @@ -3241,7 +3295,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Dash_Secrets_Engine__Org_Org_ params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Org.Org_.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Org.Org_.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Dash_Secrets_Engine__Org_Org_ |> List.map Page |> toCommands @@ -3251,7 +3305,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Dash_Secrets_Engine__Org_Org__Add params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Org.Org_.Add.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Org.Org_.Add.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Dash_Secrets_Engine__Org_Org__Add |> List.map Page |> toCommands @@ -3261,7 +3315,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Dash_Secrets_Engine__Org_Org__Name_ params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Org.Org_.Name_.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Org.Org_.Name_.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Dash_Secrets_Engine__Org_Org__Name_ |> List.map Page |> toCommands @@ -3271,7 +3325,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Dash_Secrets_Engine__Repo_Org__Repo_ params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Repo.Org_.Repo_.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Repo.Org_.Repo_.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Dash_Secrets_Engine__Repo_Org__Repo_ |> List.map Page |> toCommands @@ -3281,7 +3335,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Dash_Secrets_Engine__Repo_Org__Repo__Add params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Repo.Org_.Repo_.Add.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Repo.Org_.Repo_.Add.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Dash_Secrets_Engine__Repo_Org__Repo__Add |> List.map Page |> toCommands @@ -3291,7 +3345,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Dash_Secrets_Engine__Repo_Org__Repo__Name_ params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Repo.Org_.Repo_.Name_.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Repo.Org_.Repo_.Name_.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Dash_Secrets_Engine__Repo_Org__Repo__Name_ |> List.map Page |> toCommands @@ -3301,7 +3355,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Dash_Secrets_Engine__Shared_Org__Team_ params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Shared.Org_.Team_.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Shared.Org_.Team_.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Dash_Secrets_Engine__Shared_Org__Team_ |> List.map Page |> toCommands @@ -3311,7 +3365,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Dash_Secrets_Engine__Shared_Org__Team__Add params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Shared.Org_.Team_.Add.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Shared.Org_.Team_.Add.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Dash_Secrets_Engine__Shared_Org__Team__Add |> List.map Page |> toCommands @@ -3321,7 +3375,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Dash_Secrets_Engine__Shared_Org__Team__Name_ params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Shared.Org_.Team_.Name_.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Dash.Secrets.Engine_.Shared.Org_.Team_.Name_.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Dash_Secrets_Engine__Shared_Org__Team__Name_ |> List.map Page |> toCommands @@ -3331,7 +3385,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Dashboards pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Dashboards.page user model.shared (Route.fromUrl () model.url)) + Page.toUrlMessages routes (Pages.Dashboards.page user model.shared (Route.fromUrl () model.url)) |> List.map Main.Pages.Msg.Dashboards |> List.map Page |> toCommands @@ -3341,7 +3395,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Dashboards_Dashboard_ params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Dashboards.Dashboard_.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Dashboards.Dashboard_.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Dashboards_Dashboard_ |> List.map Page |> toCommands @@ -3351,7 +3405,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Status_Workers pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Status.Workers.page user model.shared (Route.fromUrl () model.url)) + Page.toUrlMessages routes (Pages.Status.Workers.page user model.shared (Route.fromUrl () model.url)) |> List.map Main.Pages.Msg.Status_Workers |> List.map Page |> toCommands @@ -3361,7 +3415,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Org_ params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Org_.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org_ |> List.map Page |> toCommands @@ -3371,7 +3425,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Org__Builds params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Org_.Builds.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.Builds.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org__Builds |> List.map Page |> toCommands @@ -3381,7 +3435,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Org__Repo_ params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Org_.Repo_.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.Repo_.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org__Repo_ |> List.map Page |> toCommands @@ -3391,7 +3445,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Org__Repo__Deployments params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Org_.Repo_.Deployments.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.Repo_.Deployments.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org__Repo__Deployments |> List.map Page |> toCommands @@ -3401,7 +3455,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Org__Repo__Deployments_Add params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Org_.Repo_.Deployments.Add.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.Repo_.Deployments.Add.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org__Repo__Deployments_Add |> List.map Page |> toCommands @@ -3411,15 +3465,25 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Org__Repo__Hooks params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Org_.Repo_.Hooks.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.Repo_.Hooks.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org__Repo__Hooks |> List.map Page |> toCommands ) (Auth.onPageLoad model.shared (Route.fromUrl () model.url)) + Main.Pages.Model.Org__Repo__Insights params pageModel -> + Auth.Action.command + (\user -> + Page.toUrlMessages routes (Pages.Org_.Repo_.Insights.page user model.shared (Route.fromUrl params model.url)) + |> List.map Main.Pages.Msg.Org__Repo__Insights + |> List.map Page + |> toCommands + ) + (Auth.onPageLoad model.shared (Route.fromUrl () model.url)) + Main.Pages.Model.Org__Repo__Pulls params pageModel -> - Page.toUrlMessages routes (Pages.Org_.Repo_.Pulls.page model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.Repo_.Pulls.page model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org__Repo__Pulls |> List.map Page |> toCommands @@ -3427,7 +3491,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Org__Repo__Schedules params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Org_.Repo_.Schedules.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.Repo_.Schedules.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org__Repo__Schedules |> List.map Page |> toCommands @@ -3437,7 +3501,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Org__Repo__Schedules_Add params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Org_.Repo_.Schedules.Add.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.Repo_.Schedules.Add.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org__Repo__Schedules_Add |> List.map Page |> toCommands @@ -3447,7 +3511,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Org__Repo__Schedules_Name_ params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Org_.Repo_.Schedules.Name_.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.Repo_.Schedules.Name_.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org__Repo__Schedules_Name_ |> List.map Page |> toCommands @@ -3457,7 +3521,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Org__Repo__Settings params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Org_.Repo_.Settings.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.Repo_.Settings.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org__Repo__Settings |> List.map Page |> toCommands @@ -3465,7 +3529,7 @@ toPageUrlHookCmd model routes = (Auth.onPageLoad model.shared (Route.fromUrl () model.url)) Main.Pages.Model.Org__Repo__Tags params pageModel -> - Page.toUrlMessages routes (Pages.Org_.Repo_.Tags.page model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.Repo_.Tags.page model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org__Repo__Tags |> List.map Page |> toCommands @@ -3473,7 +3537,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Org__Repo__Build_ params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Org_.Repo_.Build_.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.Repo_.Build_.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org__Repo__Build_ |> List.map Page |> toCommands @@ -3483,7 +3547,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Org__Repo__Build__Graph params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Org_.Repo_.Build_.Graph.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.Repo_.Build_.Graph.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org__Repo__Build__Graph |> List.map Page |> toCommands @@ -3493,7 +3557,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Org__Repo__Build__Pipeline params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Org_.Repo_.Build_.Pipeline.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.Repo_.Build_.Pipeline.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org__Repo__Build__Pipeline |> List.map Page |> toCommands @@ -3503,7 +3567,7 @@ toPageUrlHookCmd model routes = Main.Pages.Model.Org__Repo__Build__Services params pageModel -> Auth.Action.command (\user -> - Page.toUrlMessages routes (Pages.Org_.Repo_.Build_.Services.page user model.shared (Route.fromUrl params model.url)) + Page.toUrlMessages routes (Pages.Org_.Repo_.Build_.Services.page user model.shared (Route.fromUrl params model.url)) |> List.map Main.Pages.Msg.Org__Repo__Build__Services |> List.map Page |> toCommands @@ -3511,7 +3575,7 @@ toPageUrlHookCmd model routes = (Auth.onPageLoad model.shared (Route.fromUrl () model.url)) Main.Pages.Model.NotFound_ pageModel -> - Page.toUrlMessages routes (Pages.NotFound_.page model.shared (Route.fromUrl () model.url)) + Page.toUrlMessages routes (Pages.NotFound_.page model.shared (Route.fromUrl () model.url)) |> List.map Main.Pages.Msg.NotFound_ |> List.map Page |> toCommands @@ -3559,13 +3623,13 @@ toLayoutUrlHookCmd oldModel model routes = in Cmd.batch [ Layout.toUrlMessages routes (Layouts.Default.layout defaultProps model.shared route) - |> List.map Main.Layouts.Msg.Default - |> List.map Layout - |> toCommands + |> List.map Main.Layouts.Msg.Default + |> List.map Layout + |> toCommands , Layout.toUrlMessages routes (Layouts.Default.Admin.layout props model.shared route) - |> List.map Main.Layouts.Msg.Default_Admin - |> List.map Layout - |> toCommands + |> List.map Main.Layouts.Msg.Default_Admin + |> List.map Layout + |> toCommands ] ( Just (Layouts.Default_Build props), Just (Main.Layouts.Model.Default_Build layoutModel) ) -> @@ -3576,13 +3640,13 @@ toLayoutUrlHookCmd oldModel model routes = in Cmd.batch [ Layout.toUrlMessages routes (Layouts.Default.layout defaultProps model.shared route) - |> List.map Main.Layouts.Msg.Default - |> List.map Layout - |> toCommands + |> List.map Main.Layouts.Msg.Default + |> List.map Layout + |> toCommands , Layout.toUrlMessages routes (Layouts.Default.Build.layout props model.shared route) - |> List.map Main.Layouts.Msg.Default_Build - |> List.map Layout - |> toCommands + |> List.map Main.Layouts.Msg.Default_Build + |> List.map Layout + |> toCommands ] ( Just (Layouts.Default_Org props), Just (Main.Layouts.Model.Default_Org layoutModel) ) -> @@ -3593,13 +3657,13 @@ toLayoutUrlHookCmd oldModel model routes = in Cmd.batch [ Layout.toUrlMessages routes (Layouts.Default.layout defaultProps model.shared route) - |> List.map Main.Layouts.Msg.Default - |> List.map Layout - |> toCommands + |> List.map Main.Layouts.Msg.Default + |> List.map Layout + |> toCommands , Layout.toUrlMessages routes (Layouts.Default.Org.layout props model.shared route) - |> List.map Main.Layouts.Msg.Default_Org - |> List.map Layout - |> toCommands + |> List.map Main.Layouts.Msg.Default_Org + |> List.map Layout + |> toCommands ] ( Just (Layouts.Default_Repo props), Just (Main.Layouts.Model.Default_Repo layoutModel) ) -> @@ -3610,13 +3674,13 @@ toLayoutUrlHookCmd oldModel model routes = in Cmd.batch [ Layout.toUrlMessages routes (Layouts.Default.layout defaultProps model.shared route) - |> List.map Main.Layouts.Msg.Default - |> List.map Layout - |> toCommands + |> List.map Main.Layouts.Msg.Default + |> List.map Layout + |> toCommands , Layout.toUrlMessages routes (Layouts.Default.Repo.layout props model.shared route) - |> List.map Main.Layouts.Msg.Default_Repo - |> List.map Layout - |> toCommands + |> List.map Main.Layouts.Msg.Default_Repo + |> List.map Layout + |> toCommands ] _ -> @@ -3742,6 +3806,9 @@ isAuthProtected routePath = Route.Path.Org__Repo__Hooks _ -> True + Route.Path.Org__Repo__Insights _ -> + True + Route.Path.Org__Repo__Pulls _ -> False diff --git a/src/elm/Main/Pages/Model.elm b/src/elm/Main/Pages/Model.elm index 48ef00adf..83e6319d3 100644 --- a/src/elm/Main/Pages/Model.elm +++ b/src/elm/Main/Pages/Model.elm @@ -5,6 +5,7 @@ SPDX-License-Identifier: Apache-2.0 module Main.Pages.Model exposing (Model(..)) +import Pages.Home_ import Pages.Account.Authenticate import Pages.Account.Login import Pages.Account.Logout @@ -22,25 +23,25 @@ import Pages.Dash.Secrets.Engine_.Shared.Org_.Team_.Add import Pages.Dash.Secrets.Engine_.Shared.Org_.Team_.Name_ import Pages.Dashboards import Pages.Dashboards.Dashboard_ -import Pages.Home_ -import Pages.NotFound_ +import Pages.Status.Workers import Pages.Org_ import Pages.Org_.Builds import Pages.Org_.Repo_ -import Pages.Org_.Repo_.Build_ -import Pages.Org_.Repo_.Build_.Graph -import Pages.Org_.Repo_.Build_.Pipeline -import Pages.Org_.Repo_.Build_.Services import Pages.Org_.Repo_.Deployments import Pages.Org_.Repo_.Deployments.Add import Pages.Org_.Repo_.Hooks +import Pages.Org_.Repo_.Insights import Pages.Org_.Repo_.Pulls import Pages.Org_.Repo_.Schedules import Pages.Org_.Repo_.Schedules.Add import Pages.Org_.Repo_.Schedules.Name_ import Pages.Org_.Repo_.Settings import Pages.Org_.Repo_.Tags -import Pages.Status.Workers +import Pages.Org_.Repo_.Build_ +import Pages.Org_.Repo_.Build_.Graph +import Pages.Org_.Repo_.Build_.Pipeline +import Pages.Org_.Repo_.Build_.Services +import Pages.NotFound_ import View exposing (View) @@ -70,6 +71,7 @@ type Model | Org__Repo__Deployments { org : String, repo : String } Pages.Org_.Repo_.Deployments.Model | Org__Repo__Deployments_Add { org : String, repo : String } Pages.Org_.Repo_.Deployments.Add.Model | Org__Repo__Hooks { org : String, repo : String } Pages.Org_.Repo_.Hooks.Model + | Org__Repo__Insights { org : String, repo : String } Pages.Org_.Repo_.Insights.Model | Org__Repo__Pulls { org : String, repo : String } Pages.Org_.Repo_.Pulls.Model | Org__Repo__Schedules { org : String, repo : String } Pages.Org_.Repo_.Schedules.Model | Org__Repo__Schedules_Add { org : String, repo : String } Pages.Org_.Repo_.Schedules.Add.Model diff --git a/src/elm/Main/Pages/Msg.elm b/src/elm/Main/Pages/Msg.elm index 5e123569c..096c41913 100644 --- a/src/elm/Main/Pages/Msg.elm +++ b/src/elm/Main/Pages/Msg.elm @@ -5,6 +5,7 @@ SPDX-License-Identifier: Apache-2.0 module Main.Pages.Msg exposing (Msg(..)) +import Pages.Home_ import Pages.Account.Authenticate import Pages.Account.Login import Pages.Account.Logout @@ -22,25 +23,25 @@ import Pages.Dash.Secrets.Engine_.Shared.Org_.Team_.Add import Pages.Dash.Secrets.Engine_.Shared.Org_.Team_.Name_ import Pages.Dashboards import Pages.Dashboards.Dashboard_ -import Pages.Home_ -import Pages.NotFound_ +import Pages.Status.Workers import Pages.Org_ import Pages.Org_.Builds import Pages.Org_.Repo_ -import Pages.Org_.Repo_.Build_ -import Pages.Org_.Repo_.Build_.Graph -import Pages.Org_.Repo_.Build_.Pipeline -import Pages.Org_.Repo_.Build_.Services import Pages.Org_.Repo_.Deployments import Pages.Org_.Repo_.Deployments.Add import Pages.Org_.Repo_.Hooks +import Pages.Org_.Repo_.Insights import Pages.Org_.Repo_.Pulls import Pages.Org_.Repo_.Schedules import Pages.Org_.Repo_.Schedules.Add import Pages.Org_.Repo_.Schedules.Name_ import Pages.Org_.Repo_.Settings import Pages.Org_.Repo_.Tags -import Pages.Status.Workers +import Pages.Org_.Repo_.Build_ +import Pages.Org_.Repo_.Build_.Graph +import Pages.Org_.Repo_.Build_.Pipeline +import Pages.Org_.Repo_.Build_.Services +import Pages.NotFound_ type Msg @@ -69,6 +70,7 @@ type Msg | Org__Repo__Deployments Pages.Org_.Repo_.Deployments.Msg | Org__Repo__Deployments_Add Pages.Org_.Repo_.Deployments.Add.Msg | Org__Repo__Hooks Pages.Org_.Repo_.Hooks.Msg + | Org__Repo__Insights Pages.Org_.Repo_.Insights.Msg | Org__Repo__Pulls Pages.Org_.Repo_.Pulls.Msg | Org__Repo__Schedules Pages.Org_.Repo_.Schedules.Msg | Org__Repo__Schedules_Add Pages.Org_.Repo_.Schedules.Add.Msg diff --git a/src/elm/Pages/Org_/Repo_.elm b/src/elm/Pages/Org_/Repo_.elm index 135e40b04..3c06e6ec0 100644 --- a/src/elm/Pages/Org_/Repo_.elm +++ b/src/elm/Pages/Org_/Repo_.elm @@ -110,6 +110,7 @@ init shared route () = , pageNumber = Dict.get "page" route.query |> Maybe.andThen String.toInt , perPage = Dict.get "perPage" route.query |> Maybe.andThen String.toInt , maybeEvent = Dict.get "event" route.query + , maybeAfter = Dict.get "after" route.query |> Maybe.andThen String.toInt , org = route.params.org , repo = route.params.repo } @@ -156,6 +157,7 @@ update shared route msg model = , pageNumber = Dict.get "page" route.query |> Maybe.andThen String.toInt , perPage = Dict.get "perPage" route.query |> Maybe.andThen String.toInt , maybeEvent = options.to + , maybeAfter = Dict.get "after" route.query |> Maybe.andThen String.toInt , org = route.params.org , repo = route.params.repo } @@ -197,6 +199,7 @@ update shared route msg model = , pageNumber = Just pageNumber , perPage = Dict.get "perPage" route.query |> Maybe.andThen String.toInt , maybeEvent = Dict.get "event" route.query + , maybeAfter = Dict.get "after" route.query |> Maybe.andThen String.toInt , org = route.params.org , repo = route.params.repo } @@ -238,6 +241,7 @@ update shared route msg model = , pageNumber = Dict.get "page" route.query |> Maybe.andThen String.toInt , perPage = Dict.get "perPage" route.query |> Maybe.andThen String.toInt , maybeEvent = Dict.get "event" route.query + , maybeAfter = Dict.get "after" route.query |> Maybe.andThen String.toInt , org = route.params.org , repo = route.params.repo } @@ -281,6 +285,7 @@ update shared route msg model = , pageNumber = Dict.get "page" route.query |> Maybe.andThen String.toInt , perPage = Dict.get "perPage" route.query |> Maybe.andThen String.toInt , maybeEvent = Dict.get "event" route.query + , maybeAfter = Dict.get "after" route.query |> Maybe.andThen String.toInt , org = route.params.org , repo = route.params.repo } @@ -324,6 +329,7 @@ update shared route msg model = , pageNumber = Dict.get "page" route.query |> Maybe.andThen String.toInt , perPage = Dict.get "perPage" route.query |> Maybe.andThen String.toInt , maybeEvent = Dict.get "event" route.query + , maybeAfter = Dict.get "after" route.query |> Maybe.andThen String.toInt , org = route.params.org , repo = route.params.repo } @@ -392,6 +398,7 @@ update shared route msg model = , pageNumber = Nothing , perPage = Dict.get "perPage" route.query |> Maybe.andThen String.toInt , maybeEvent = maybeEvent + , maybeAfter = Dict.get "after" route.query |> Maybe.andThen String.toInt , org = route.params.org , repo = route.params.repo } @@ -411,6 +418,7 @@ update shared route msg model = , pageNumber = Dict.get "page" route.query |> Maybe.andThen String.toInt , perPage = Dict.get "perPage" route.query |> Maybe.andThen String.toInt , maybeEvent = Dict.get "event" route.query + , maybeAfter = Dict.get "after" route.query |> Maybe.andThen String.toInt , org = route.params.org , repo = route.params.repo } diff --git a/src/elm/Pages/Org_/Repo_/Insights.elm b/src/elm/Pages/Org_/Repo_/Insights.elm new file mode 100644 index 000000000..3d3f6d556 --- /dev/null +++ b/src/elm/Pages/Org_/Repo_/Insights.elm @@ -0,0 +1,688 @@ +{-- +SPDX-License-Identifier: Apache-2.0 +--} + + +module Pages.Org_.Repo_.Insights exposing (Model, Msg, page) + +import Auth +import Chart +import Chart.Attributes +import Chart.Events +import Chart.Item +import Components.Loading exposing (viewSmallLoader) +import Dict exposing (Dict) +import Effect exposing (Effect) +import Float.Extra +import Html exposing (Html, div, em, h1, h2, h3, p, section, strong, text) +import Html.Attributes exposing (class) +import Http +import Http.Detailed +import Layouts +import List exposing (sort) +import List.Extra +import Page exposing (Page) +import RemoteData exposing (WebData) +import Route exposing (Route) +import Route.Path +import Shared +import Time +import Utils.Errors as Errors +import Utils.Helpers as Helpers +import Vela +import View exposing (View) + + +page : Auth.User -> Shared.Model -> Route { org : String, repo : String } -> Page Model Msg +page user shared route = + Page.new + { init = init shared route + , update = update shared route + , subscriptions = subscriptions + , view = view shared route + } + |> Page.withLayout (toLayout user route) + + + +-- LAYOUT + + +{-| toLayout : takes user, route, model, and passes the deployments page info to Layouts. +-} +toLayout : Auth.User -> Route { org : String, repo : String } -> Model -> Layouts.Layout Msg +toLayout user route model = + Layouts.Default_Repo + { navButtons = [] + , utilButtons = [] + , helpCommands = [] + , crumbs = + [ ( "Overview", Just Route.Path.Home_ ) + , ( route.params.org, Just <| Route.Path.Org_ { org = route.params.org } ) + , ( route.params.repo, Nothing ) + ] + , org = route.params.org + , repo = route.params.repo + } + + + +-- INIT + + +type alias Metrics = + { overall : OverallMetrics + , byStatus : Dict String StatusMetrics + } + + +type alias StatusMetrics = + { averageRuntime : Float + , medianRuntime : Float + , buildFrequency : Int + , longestRuntime : Int + , eventBranchMetrics : Dict ( String, String ) EventBranchMetrics + } + + +type alias OverallMetrics = + { failureRate : Float + , averageQueueTime : Float + , averageRuntime : Float + , timeUsedOnFailedBuilds : Float + , successRate : Float + , medianQueueTime : Float + , medianRuntime : Float + , buildFrequency : Int + , averageTimeToRecovery : Float + , longestQueueTime : Int + , longestRuntime : Int + , eventBranchMetrics : Dict ( String, String ) EventBranchMetrics + } + + +type alias EventBranchMetrics = + { medianRuntime : Float + , buildTimesOverTime : List TimeSeriesData + + -- Add other metrics as needed + } + + +type alias TimeSeriesData = + { timestamp : Int + , value : Float + } + + +type alias Model = + { builds : WebData (List Vela.Build) + , metrics : Maybe Metrics + , hovering : List (Chart.Item.One TimeSeriesData Chart.Item.Dot) + } + + +init : Shared.Model -> Route { org : String, repo : String } -> () -> ( Model, Effect Msg ) +init shared route () = + let + currentTimeInSeconds = + Time.posixToMillis shared.time // 1000 + + sevenDaysInSeconds = + 7 * 24 * 60 * 60 + + timeMinusSevenDaysInSeconds : Int + timeMinusSevenDaysInSeconds = + currentTimeInSeconds - sevenDaysInSeconds + in + ( { builds = RemoteData.Loading + , metrics = Nothing + , hovering = [] + } + , Effect.getAllBuilds + { baseUrl = shared.velaAPIBaseURL + , session = shared.session + , onResponse = GetRepoBuildsResponse + , after = timeMinusSevenDaysInSeconds + , org = route.params.org + , repo = route.params.repo + } + ) + + + +-- UPDATE + + +type Msg + = GetRepoBuildsResponse (Result (Http.Detailed.Error String) ( Http.Metadata, List Vela.Build )) + | OnHover (List (Chart.Item.One TimeSeriesData Chart.Item.Dot)) + + +update : Shared.Model -> Route { org : String, repo : String } -> Msg -> Model -> ( Model, Effect Msg ) +update shared route msg model = + case msg of + OnHover hovering -> + ( { model | hovering = hovering } + , Effect.none + ) + + GetRepoBuildsResponse response -> + case response of + Ok ( meta, builds ) -> + let + metrics = + calculateMetrics builds + in + ( { model + | builds = RemoteData.succeed builds + , metrics = metrics + } + , Effect.none + ) + + Err error -> + ( { model | builds = Errors.toFailure error } + , Effect.handleHttpError + { error = error + , shouldShowAlertFn = Errors.showAlertAlways + } + ) + + +calculateMetrics : List Vela.Build -> Maybe Metrics +calculateMetrics builds = + if List.isEmpty builds then + Nothing + + else + let + failureRate = + calculateFailureRate builds + + averageQueueTime = + calculateAverageQueueTime builds + + averageRuntime = + calculateAverageRuntime builds + + timeUsedOnFailedBuilds = + calculateTimeUsedOnFailedBuilds builds + + successRate = + calculateSuccessRate builds + + medianQueueTime = + calculateMedianQueueTime builds + + medianRuntime = + calculateMedianRuntime builds + + buildFrequency = + calculateBuildFrequency builds + + averageTimeToRecovery = + calculateAverageTimeToRecovery builds + + longestQueueTime = + calculateLongestQueueTime builds + + longestRuntime = + calculateLongestRuntime builds + + eventBranchMetrics = + calculateEventBranchMetrics builds + + byStatus = + calculateMetricsByStatus builds + in + Just + { overall = + { failureRate = failureRate + , averageQueueTime = averageQueueTime + , averageRuntime = averageRuntime + , timeUsedOnFailedBuilds = timeUsedOnFailedBuilds + , successRate = successRate + , medianQueueTime = medianQueueTime + , medianRuntime = medianRuntime + , buildFrequency = buildFrequency + , averageTimeToRecovery = averageTimeToRecovery + , longestQueueTime = longestQueueTime + , longestRuntime = longestRuntime + , eventBranchMetrics = eventBranchMetrics + } + , byStatus = byStatus + } + + +calculateLongestQueueTime : List Vela.Build -> Int +calculateLongestQueueTime builds = + let + queueTimes = + List.map (\build -> build.started - build.enqueued) builds + in + if List.isEmpty queueTimes then + 0 + + else + List.maximum queueTimes |> Maybe.withDefault 0 + + +calculateMedianRuntime : List Vela.Build -> Float +calculateMedianRuntime builds = + let + runTimes = + List.map (\build -> toFloat (build.finished - build.started)) builds + in + calculateMedian runTimes + + +calculateMedianQueueTime : List Vela.Build -> Float +calculateMedianQueueTime builds = + let + queueTimes = + List.map (\build -> toFloat (build.started - build.enqueued)) builds + in + calculateMedian queueTimes + + +calculateSuccessRate : List Vela.Build -> Float +calculateSuccessRate builds = + let + total = + List.length builds + + succeeded = + List.length (List.filter (\build -> build.status == Vela.Success) builds) + in + if total == 0 then + 0 + + else + (toFloat succeeded / toFloat total) * 100 + + +calculateMetricsByStatus : List Vela.Build -> Dict String StatusMetrics +calculateMetricsByStatus builds = + let + -- Group builds by status + groupedBuilds = + List.foldl + (\build acc -> + let + key = + Vela.statusToString build.status + in + Dict.update key (Maybe.map (\lst -> Just (build :: lst)) >> Maybe.withDefault (Just [ build ])) acc + ) + Dict.empty + builds + + calculateMetricsForGroup b = + let + buildTimes = + List.map (\build -> toFloat (build.finished - build.started)) b + + medianRuntime = + calculateMedian buildTimes + + averageRuntime = + calculateAverageRuntime b + + buildFrequency = + calculateBuildFrequency b + + longestRuntime = + calculateLongestRuntime b + + eventBranchMetrics = + calculateEventBranchMetrics b + in + { averageRuntime = averageRuntime + , medianRuntime = medianRuntime + , buildFrequency = buildFrequency + , longestRuntime = longestRuntime + , eventBranchMetrics = eventBranchMetrics + } + in + Dict.map (\_ buildss -> calculateMetricsForGroup buildss) groupedBuilds + + +calculateAverageTimeToRecovery : List Vela.Build -> Float +calculateAverageTimeToRecovery builds = + let + -- Filter the builds to get only failed and successful builds + failedBuilds = + List.filter (\build -> build.status == Vela.Failure) builds + + successfulBuilds = + List.filter (\build -> build.status == Vela.Success) builds + + -- Group builds by branch + groupByBranch b = + List.foldl + (\build acc -> + Dict.update build.branch (Maybe.map (\lst -> Just (build :: lst)) >> Maybe.withDefault (Just [ build ])) acc + ) + Dict.empty + b + + groupedFailedBuilds = + groupByBranch failedBuilds + + groupedSuccessfulBuilds = + groupByBranch successfulBuilds + + -- Find pairs of failed and subsequent successful builds within each branch + findRecoveryTimes f s = + case ( f, s ) of + ( [], _ ) -> + [] + + ( _, [] ) -> + [] + + ( failed :: restFailed, success :: restSuccess ) -> + if success.created > failed.created then + (success.created - failed.created) :: findRecoveryTimes restFailed restSuccess + + else + findRecoveryTimes f restSuccess + + -- Calculate the time differences for each branch + calculateBranchRecoveryTimes branch = + let + f = + Dict.get branch groupedFailedBuilds |> Maybe.withDefault [] + + s = + Dict.get branch groupedSuccessfulBuilds |> Maybe.withDefault [] + in + findRecoveryTimes (List.sortBy .created f) (List.sortBy .created s) + + -- Aggregate recovery times across all branches + allRecoveryTimes = + Dict.keys groupedFailedBuilds + |> List.concatMap calculateBranchRecoveryTimes + + -- Compute the average of the time differences + totalRecoveryTime = + List.sum allRecoveryTimes + + count = + List.length allRecoveryTimes + in + if count == 0 then + 0 + + else + toFloat totalRecoveryTime / toFloat count + + +calculateLongestRuntime : List Vela.Build -> Int +calculateLongestRuntime builds = + builds + |> List.map (\build -> build.finished - build.started) + |> List.maximum + |> Maybe.withDefault 0 + + +calculateBuildFrequency : List Vela.Build -> Int +calculateBuildFrequency builds = + let + sortedByCreated = + List.sortBy .created builds + + firstBuildTime = + List.head sortedByCreated |> Maybe.map .created |> Maybe.withDefault 0 + + lastBuildTime = + List.reverse sortedByCreated |> List.head |> Maybe.map .created |> Maybe.withDefault 0 + + totalSeconds = + lastBuildTime - firstBuildTime + + totalDays = + max 1 (totalSeconds // (24 * 60 * 60)) + + totalBuilds = + List.length builds + in + if totalDays == 0 then + 0 + + else + totalBuilds // totalDays + + +calculateMedian : List Float -> Float +calculateMedian list = + let + sorted = + List.sort list + + len = + List.length sorted + in + if len == 0 then + 0 + + else if Basics.remainderBy 2 len == 1 then + List.Extra.getAt (len // 2) sorted |> Maybe.withDefault 0 + + else + let + mid1 = + List.Extra.getAt (len // 2 - 1) sorted |> Maybe.withDefault 0 + + mid2 = + List.Extra.getAt (len // 2) sorted |> Maybe.withDefault 0 + in + (mid1 + mid2) / 2 + + +calculateEventBranchMetrics : List Vela.Build -> Dict ( String, String ) EventBranchMetrics +calculateEventBranchMetrics builds = + let + -- Group builds by (event, branch) + groupedBuilds = + List.foldl + (\build acc -> + let + key = + ( build.event, build.branch ) + in + Dict.update key (Maybe.map (\lst -> Just (build :: lst)) >> Maybe.withDefault (Just [ build ])) acc + ) + Dict.empty + builds + + -- Calculate metrics for each group + calculateMetricsForGroup b = + let + buildTimes = + List.map (\build -> toFloat (build.finished - build.started)) b + + medianRuntime = + calculateMedian buildTimes + + buildTimesOverTime = + List.foldl + (\build acc -> + { timestamp = build.created, value = toFloat (build.finished - build.started) } :: acc + ) + [] + b + in + { medianRuntime = medianRuntime + , buildTimesOverTime = buildTimesOverTime + } + in + Dict.map (\_ buildss -> calculateMetricsForGroup buildss) groupedBuilds + + +calculateAverageRuntime : List Vela.Build -> Float +calculateAverageRuntime builds = + let + legitBuilds = + builds + |> List.filter (\build -> build.status /= Vela.Pending) + |> List.filter (\build -> build.status /= Vela.Running) + + total = + legitBuilds + |> List.foldl (\build acc -> acc + (build.finished - build.started)) 0 + + count = + List.length legitBuilds + in + if count == 0 then + toFloat 0 + + else + toFloat (total // count) + + +calculateAverageQueueTime : List Vela.Build -> Float +calculateAverageQueueTime builds = + let + total = + builds |> List.filter (\build -> build.started > 0) |> List.foldl (\build acc -> acc + (build.started - build.enqueued)) 0 + + count = + List.length builds + in + if count == 0 then + toFloat 0 + + else + toFloat (total // count) + + +calculateFailureRate : List Vela.Build -> Float +calculateFailureRate builds = + let + totalFailures = + builds |> List.filter (\build -> build.status == Vela.Failure) |> List.length + + count = + List.length builds + in + if count == 0 then + 0 + + else + toFloat totalFailures / toFloat count * 100 + + +calculateTimeUsedOnFailedBuilds : List Vela.Build -> Float +calculateTimeUsedOnFailedBuilds builds = + builds + |> List.filter (\build -> build.status == Vela.Failure) + |> List.foldl (\build acc -> acc + (build.finished - build.started)) 0 + |> toFloat + + + +-- SUBSCRIPTIONS + + +subscriptions : Model -> Sub Msg +subscriptions model = + Sub.none + + + +-- VIEW + + +view : Shared.Model -> Route { org : String, repo : String } -> Model -> View Msg +view shared route model = + { title = "Pages.Org_.Repo_.Insights" + , body = + case model.builds of + RemoteData.Loading -> + [ viewSmallLoader ] + + RemoteData.NotAsked -> + viewEmpty + + RemoteData.Failure _ -> + viewError + + RemoteData.Success builds -> + case builds of + [] -> + viewEmpty + + _ -> + viewOverallMetrics model shared.zone + } + + +viewOverallMetrics : Model -> Time.Zone -> List (Html Msg) +viewOverallMetrics model time = + case model.metrics of + Nothing -> + [ h1 [] [ text "No metrics" ] ] + + Just m -> + let + data = + m.overall.eventBranchMetrics + |> Dict.values + |> List.concatMap .buildTimesOverTime + in + List.concat + [ [ h2 [] [ text "Performance Insights (Last 7 Days)" ] ] + , viewMetric "Failure Rate" (Float.Extra.toFixedDecimalPlaces 2 m.overall.failureRate ++ "%") "Percentage of failed builds" + , viewMetric "Average Queue Time" (Helpers.formatTimeFromFloat m.overall.averageQueueTime) "Average time builds spend in queue" + , viewMetric "Average Runtime" (Helpers.formatTimeFromFloat m.overall.averageRuntime) "Average time builds take to complete" + , viewMetric "Time Used on Failed Builds" (Helpers.formatTimeFromFloat m.overall.timeUsedOnFailedBuilds) "Total time spent on failed builds" + , viewMetric "Success Rate" (Float.Extra.toFixedDecimalPlaces 2 m.overall.successRate ++ "%") "Percentage of successful builds" + , viewMetric "Median Queue Time" (Helpers.formatTimeFromFloat m.overall.medianQueueTime) "Median time builds spend in queue" + , viewMetric "Median Runtime" (Helpers.formatTimeFromFloat m.overall.medianRuntime) "Median time builds take to complete" + , viewMetric "Build Frequency" (String.fromInt m.overall.buildFrequency) "Number of builds over the last 7 days" + , viewMetric "Average Time to Recovery" (Helpers.formatTimeFromFloat m.overall.averageTimeToRecovery) "Average time to recover from failures" + , viewMetric "Longest Queue Time" (Helpers.formatTimeFromInt m.overall.longestQueueTime) "Longest time a build spent in queue" + , viewMetric "Longest Runtime" (Helpers.formatTimeFromInt m.overall.longestRuntime) "Longest time a build took to complete" + , [ div [ class "chart-container" ] + [ Chart.chart + [ Chart.Attributes.height 200 + , Chart.Attributes.width 400 + , Chart.Events.onMouseMove OnHover (Chart.Events.getNearest Chart.Item.dots) + , Chart.Events.onMouseLeave (OnHover []) + ] + [ Chart.xLabels [ Chart.Attributes.times time ] + , Chart.yLabels [ Chart.Attributes.withGrid ] + , Chart.series (.timestamp >> toFloat) + [ Chart.interpolated .value [] [ Chart.Attributes.circle, Chart.Attributes.size 3 ] + ] + data + , Chart.each model.hovering <| + \p item -> + [ Chart.tooltip item [] [] [] ] + ] + ] + ] + ] + + +viewMetric : String -> String -> String -> List (Html msg) +viewMetric title value description = + [ section [ class "metric" ] + [ h3 [ class "metric-title" ] [ text title ] + , strong [ class "metric-value" ] [ text value ] + , em [ class "metric-description" ] [ text description ] + ] + ] + + +viewEmpty : List (Html msg) +viewEmpty = + [ h1 [] [ text "No builds" ] ] + + +viewError : List (Html msg) +viewError = + [ h1 [] [ text "Error" ] ] diff --git a/src/elm/Route.elm b/src/elm/Route.elm index 9468bbafb..aaa807a92 100644 --- a/src/elm/Route.elm +++ b/src/elm/Route.elm @@ -44,6 +44,6 @@ toString route = [ Route.Path.toString route.path , Route.Query.toString route.query , route.hash - |> Maybe.map (String.append "#") - |> Maybe.withDefault "" + |> Maybe.map (String.append "#") + |> Maybe.withDefault "" ] diff --git a/src/elm/Route/Path.elm b/src/elm/Route/Path.elm index 4a32b6c13..92886b6eb 100644 --- a/src/elm/Route/Path.elm +++ b/src/elm/Route/Path.elm @@ -37,6 +37,7 @@ type Path | Org__Repo__Deployments { org : String, repo : String } | Org__Repo__Deployments_Add { org : String, repo : String } | Org__Repo__Hooks { org : String, repo : String } + | Org__Repo__Insights { org : String, repo : String } | Org__Repo__Pulls { org : String, repo : String } | Org__Repo__Schedules { org : String, repo : String } | Org__Repo__Schedules_Add { org : String, repo : String } @@ -211,6 +212,13 @@ fromString urlPath = } |> Just + org_ :: repo_ :: "insights" :: [] -> + Org__Repo__Insights + { org = org_ + , repo = repo_ + } + |> Just + org_ :: repo_ :: "pulls" :: [] -> Org__Repo__Pulls { org = org_ @@ -376,6 +384,9 @@ toString path = Org__Repo__Hooks params -> [ params.org, params.repo, "hooks" ] + Org__Repo__Insights params -> + [ params.org, params.repo, "insights" ] + Org__Repo__Pulls params -> [ params.org, params.repo, "pulls" ] diff --git a/src/elm/Route/Query.elm b/src/elm/Route/Query.elm index 0cfabb738..d7ecd4991 100644 --- a/src/elm/Route/Query.elm +++ b/src/elm/Route/Query.elm @@ -7,8 +7,8 @@ module Route.Query exposing (fromUrl, toString) import Dict exposing (Dict) import Url exposing (Url) -import Url.Builder exposing (QueryParameter) import Url.Parser exposing (query) +import Url.Builder exposing (QueryParameter) fromUrl : Url -> Dict String String @@ -28,7 +28,7 @@ fromUrl url = |> Dict.fromList -queryPiecesToTuple : List String -> Maybe ( String, String ) +queryPiecesToTuple : List String -> Maybe (String, String) queryPiecesToTuple pieces = case pieces of [] -> @@ -55,6 +55,6 @@ toString queryParameterList = |> Url.Builder.toQuery -tupleToQueryPiece : ( String, String ) -> QueryParameter +tupleToQueryPiece : (String, String) -> QueryParameter tupleToQueryPiece ( key, value ) = Url.Builder.string key value diff --git a/src/elm/Shared/Msg.elm b/src/elm/Shared/Msg.elm index 1392ba7ce..564ba5225 100644 --- a/src/elm/Shared/Msg.elm +++ b/src/elm/Shared/Msg.elm @@ -54,7 +54,7 @@ type Msg | AddFavorites { favorites : List { org : String, maybeRepo : Maybe String } } | AddFavoritesResponse { favorites : List { org : String, maybeRepo : Maybe String } } (Result (Http.Detailed.Error String) ( Http.Metadata, Vela.User )) -- BUILDS - | GetRepoBuilds { org : String, repo : String, pageNumber : Maybe Int, perPage : Maybe Int, maybeEvent : Maybe String } + | GetRepoBuilds { org : String, repo : String, pageNumber : Maybe Int, perPage : Maybe Int, maybeEvent : Maybe String, maybeAfter : Maybe Int } | GetRepoBuildsResponse (Result (Http.Detailed.Error String) ( Http.Metadata, List Vela.Build )) -- HOOKS | GetRepoHooks { org : String, repo : String, pageNumber : Maybe Int, perPage : Maybe Int, maybeEvent : Maybe String } diff --git a/src/elm/Utils/Helpers.elm b/src/elm/Utils/Helpers.elm index 6b3b8f532..98c3cbd98 100644 --- a/src/elm/Utils/Helpers.elm +++ b/src/elm/Utils/Helpers.elm @@ -22,6 +22,8 @@ module Utils.Helpers exposing , formatFilesize , formatRunTime , formatTestTag + , formatTimeFromFloat + , formatTimeFromInt , getNameFromRef , humanReadableDateTimeFormatter , humanReadableDateTimeWithDefault @@ -216,6 +218,54 @@ noSomeSecondsAgo _ = "just now" +formatTimeFromInt : Int -> String +formatTimeFromInt number = + formatTime number + + +formatTimeFromFloat : Float -> String +formatTimeFromFloat number = + number + |> floor + |> formatTime + + +formatTime : Int -> String +formatTime totalSeconds = + let + hours = + totalSeconds // 3600 + + remainingSeconds = + Basics.remainderBy 3600 totalSeconds + + minutes = + remainingSeconds // 60 + + seconds = + Basics.remainderBy 60 remainingSeconds + + hoursString = + if hours > 0 then + String.fromInt hours ++ "h " + + else + "" + + minutesString = + if minutes > 0 then + String.fromInt minutes ++ "m " + + else + "" + in + if totalSeconds == 0 then + "0s" + + else + hoursString ++ minutesString ++ String.fromInt seconds ++ "s" + + {-| formatRunTime : calculates build runtime using current application time and build times. -} formatRunTime : Posix -> Int -> Int -> String diff --git a/src/scss/_main.scss b/src/scss/_main.scss index 161127bad..54ff0d019 100644 --- a/src/scss/_main.scss +++ b/src/scss/_main.scss @@ -1781,3 +1781,27 @@ code.shell { content: '$'; } } + +.metric { + display: inline-block; + width: 25rem; + margin: 1rem; + padding: 1rem 1rem; + + background: var(--color-bg-dark); +} + +.metric > * { + margin: 0; +} + +.metric-value { + display: block; + + font-size: xxx-large; +} + +.chart-container { + max-width: 10rem; + margin: 1rem 3rem; +}