From 3b38032cfb0dd6691eaf19ec80ded0be0105586d Mon Sep 17 00:00:00 2001 From: Kelly Merrick Date: Fri, 13 Sep 2024 14:14:01 -0500 Subject: [PATCH 01/12] enh(dashboards): mvp for dashboards view --- src/elm/Layouts/Default/Org.elm | 7 +++ src/elm/Pages/Dashboards.elm | 83 +++++++++++++++++++++++++++------ src/elm/Pages/Home_.elm | 7 +++ src/elm/Vela.elm | 4 +- 4 files changed, 86 insertions(+), 15 deletions(-) diff --git a/src/elm/Layouts/Default/Org.elm b/src/elm/Layouts/Default/Org.elm index 933f5a370..44f5f2c39 100644 --- a/src/elm/Layouts/Default/Org.elm +++ b/src/elm/Layouts/Default/Org.elm @@ -135,6 +135,13 @@ view props shared route { toContentMsg, model, content } = { buttons = props.navButtons ++ [ a + [ class "button" + , class "-outline" + , Util.testAttribute "dashboards-button" + , Route.Path.href Route.Path.Dashboards + ] + [ text "Dashboards" ] + , a [ class "button" , class "-outline" , Util.testAttribute "source-repos" diff --git a/src/elm/Pages/Dashboards.elm b/src/elm/Pages/Dashboards.elm index 09c63b37f..34cb37c43 100644 --- a/src/elm/Pages/Dashboards.elm +++ b/src/elm/Pages/Dashboards.elm @@ -9,14 +9,17 @@ import Auth import Components.Crumbs import Components.Nav import Effect exposing (Effect) -import Html exposing (code, h1, h2, main_, p, text) +import Html exposing (Html, a, code, div, h1, h2, li, main_, p, text, ul) import Html.Attributes exposing (class) import Layouts import Page exposing (Page) +import RemoteData import Route exposing (Route) import Route.Path import Shared +import Time import Utils.Helpers as Util +import Utils.Interval as Interval import View exposing (View) @@ -82,7 +85,7 @@ type alias Model = init : Shared.Model -> Route () -> () -> ( Model, Effect Msg ) init shared route () = ( {} - , Effect.none + , Effect.getCurrentUserShared {} ) @@ -94,6 +97,8 @@ init shared route () = -} type Msg = NoOp + -- REFRESH + | Tick { time : Time.Posix, interval : Interval.Interval } {-| update : takes current model, message, and returns an updated model and effect. @@ -106,6 +111,12 @@ update shared route msg model = , Effect.none ) + -- REFRESH + Tick options -> + ( model + , Effect.none + ) + -- SUBSCRIPTIONS @@ -115,7 +126,7 @@ update shared route msg model = -} subscriptions : Model -> Sub Msg subscriptions model = - Sub.none + Interval.tickEveryFiveSeconds Tick @@ -140,17 +151,61 @@ view shared route model = { buttons = [] , crumbs = Components.Crumbs.view route.path crumbs } - , main_ [ class "content-wrap", Util.testAttribute "dashboards" ] - [ h1 [] [ text "Welcome to dashboards!" ] - , h2 [] [ text "โœจ Want to create a new dashboard?" ] - , p [] [ text "Use the Vela CLI to add a new dashboard:" ] - , code [ class "shell" ] [ text "vela add dashboard --help" ] - , h2 [] [ text "๐Ÿš€ Already have a dashboard?" ] - , p [] [ text "Check your available dashboards with:" ] - , code [ class "shell" ] [ text "vela get dashboards" ] - , p [] [ text "Take note of your dashboard ID you are interested in and and add it to the current URL to view it." ] - , h2 [] [ text "๐Ÿ’ฌ Got Feedback?" ] - , p [] [ text "Follow the link in the top right to let us know your thoughts and ideas." ] + , main_ [ class "content-wrap" ] + [ div [ Util.testAttribute "dashboards" ] <| + case shared.user of + RemoteData.Success u -> + if List.length u.dashboards > 0 then + [ div [] + [ h1 [] [ text "BETA something" ] + , h2 [] [ text "Dashboards" ] + , p [] [ text "UI Dashboard functionality is very minimal in this Vela version." ] + , ul [] + [ li [] + [ text "Manage dashboards with the CLI or API" + ] + , li [] + [ text "Dashboard names do not display on this page yet" + ] + , li [] + [ text "You'll only see dashboards you created" + ] + , li [] + [ text "You won't see dashboards that were shared with you, or you were added to as an admin; so you might want to save those links!" + ] + ] + , h2 [] [ text "๐Ÿ’ฌ Got Feedback?" ] + , p [] [ text "Follow the feedback link in the top right to let us know your thoughts and ideas. We really need your feedback on the whole dashboard experience to prioritize what we'll focus on for the next version." ] + , viewDashboards u.dashboards + ] + ] + + else + [ div [ class "dashboards" ] + [ h1 [] [ text "Welcome to dashboards!" ] + , h2 [] [ text "โœจ Want to create a new dashboard?" ] + , p [] [ text "Use the Vela CLI to add a new dashboard:" ] + , code [ class "shell" ] [ text "vela add dashboard --help" ] + , h2 [] [ text "๐Ÿš€ Already have a dashboard?" ] + , p [] [ text "Check your available dashboards with:" ] + , code [ class "shell" ] [ text "vela get dashboards" ] + , p [] [ text "Take note of your dashboard ID you are interested in and and add it to the current URL to view it." ] + , h2 [] [ text "๐Ÿ’ฌ Got Feedback?" ] + , p [] [ text "Follow the link in the top right to let us know your thoughts and ideas." ] + ] + ] + + _ -> + [ div [] [ text "no dashboards" ] + ] ] ] } + + +{-| viewDashboards : renders a list of dashboard id links. +-} +viewDashboards : List String -> Html Msg +viewDashboards dashboards = + div [] + (List.map (\dashboard -> div [] [ a [ Route.Path.href <| Route.Path.Dashboards_Dashboard_ { dashboard = dashboard } ] [ text dashboard ] ]) dashboards) diff --git a/src/elm/Pages/Home_.elm b/src/elm/Pages/Home_.elm index 972bac422..72754f9c9 100644 --- a/src/elm/Pages/Home_.elm +++ b/src/elm/Pages/Home_.elm @@ -172,6 +172,13 @@ view shared route model = route { buttons = [ a + [ class "button" + , class "-outline" + , Util.testAttribute "dashboards-button" + , Route.Path.href Route.Path.Dashboards + ] + [ text "Dashboards" ] + , a [ class "button" , class "-outline" , Util.testAttribute "source-repos" diff --git a/src/elm/Vela.elm b/src/elm/Vela.elm index d7e91d96d..063b6d33f 100644 --- a/src/elm/Vela.elm +++ b/src/elm/Vela.elm @@ -259,6 +259,7 @@ type alias User = { id : Int , name : String , favorites : List String + , dashboards : List String , active : Bool , admin : Bool } @@ -270,13 +271,14 @@ decodeUser = |> required "id" int |> required "name" string |> optional "favorites" (Json.Decode.list string) [] + |> optional "dashboards" (Json.Decode.list string) [] |> required "active" bool |> optional "admin" bool False emptyUser : User emptyUser = - { id = -1, name = "", favorites = [], active = False, admin = False } + { id = -1, name = "", favorites = [], dashboards = [], active = False, admin = False } type alias UpdateUserPayload = From 1557317baba9e9953220bf8c19d6274c29f43b87 Mon Sep 17 00:00:00 2001 From: wass3rw3rk <49894298+wass3rw3rk@users.noreply.github.com> Date: Mon, 16 Sep 2024 14:43:59 -0500 Subject: [PATCH 02/12] switch to use user/dashboards endpoint --- src/elm/Api/Endpoint.elm | 4 ++ src/elm/Api/Operations.elm | 14 +++++ src/elm/Effect.elm | 18 +++++- src/elm/Pages/Dashboards.elm | 79 +++++++++++++++++++------ src/elm/Pages/Dashboards/Dashboard_.elm | 1 - src/elm/Vela.elm | 6 ++ 6 files changed, 102 insertions(+), 20 deletions(-) diff --git a/src/elm/Api/Endpoint.elm b/src/elm/Api/Endpoint.elm index 225bd70ea..581a71c81 100644 --- a/src/elm/Api/Endpoint.elm +++ b/src/elm/Api/Endpoint.elm @@ -26,6 +26,7 @@ type Endpoint | Logout | CurrentUser | Dashboard String + | Dashboards | Deployment Vela.Org Vela.Repo (Maybe String) | Deployments (Maybe Pagination.Page) (Maybe Pagination.PerPage) Vela.Org Vela.Repo | Token @@ -164,6 +165,9 @@ toUrl api endpoint = Deployments maybePage maybePerPage org repo -> url api [ "deployments", org, repo ] <| Pagination.toQueryParams maybePage maybePerPage + Dashboards -> + url api [ "user", "dashboards" ] [] + Dashboard dashboard -> url api [ "dashboards", dashboard ] [] diff --git a/src/elm/Api/Operations.elm b/src/elm/Api/Operations.elm index 8581a5ab3..a807775c6 100644 --- a/src/elm/Api/Operations.elm +++ b/src/elm/Api/Operations.elm @@ -30,6 +30,7 @@ module Api.Operations exposing , getBuildSteps , getCurrentUser , getDashboard + , getDashboards , getOrgBuilds , getOrgRepos , getOrgSecret @@ -1316,3 +1317,16 @@ getDashboard baseUrl session options = ) Vela.decodeDashboard |> withAuth session + + +{-| getDashboards : retrieves the dashboards for the current user. +-} +getDashboards : + String + -> Session + -> Request (List Vela.Dashboard) +getDashboards baseUrl session = + get baseUrl + Api.Endpoint.Dashboards + Vela.decodeDashboards + |> withAuth session diff --git a/src/elm/Effect.elm b/src/elm/Effect.elm index 5a89b5b36..0e1678869 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, 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, 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 ) {-| @@ -1384,3 +1384,19 @@ getDashboard options = options ) |> sendCmd + + +getDashboards : + { baseUrl : String + , session : Auth.Session.Session + , onResponse : Result (Http.Detailed.Error String) ( Http.Metadata, List Vela.Dashboard ) -> msg + } + -> Effect msg +getDashboards options = + Api.try + options.onResponse + (Api.Operations.getDashboards + options.baseUrl + options.session + ) + |> sendCmd diff --git a/src/elm/Pages/Dashboards.elm b/src/elm/Pages/Dashboards.elm index 34cb37c43..8caa91eae 100644 --- a/src/elm/Pages/Dashboards.elm +++ b/src/elm/Pages/Dashboards.elm @@ -7,19 +7,24 @@ module Pages.Dashboards exposing (Model, Msg, page) import Auth import Components.Crumbs +import Components.Loading import Components.Nav import Effect exposing (Effect) -import Html exposing (Html, a, code, div, h1, h2, li, main_, p, text, ul) +import Html exposing (Html, a, code, div, h1, h2, li, main_, p, span, text, ul) import Html.Attributes exposing (class) +import Http +import Http.Detailed import Layouts import Page exposing (Page) -import RemoteData +import RemoteData exposing (WebData) import Route exposing (Route) import Route.Path import Shared import Time +import Utils.Errors as Errors import Utils.Helpers as Util import Utils.Interval as Interval +import Vela import View exposing (View) @@ -77,15 +82,19 @@ toLayout user route model = {-| Model : alias for a model object for the dashboards page. -} type alias Model = - {} + { dashboards : WebData (List Vela.Dashboard) } {-| init : takes shared model and initializes dashboards page input arguments. -} init : Shared.Model -> Route () -> () -> ( Model, Effect Msg ) init shared route () = - ( {} - , Effect.getCurrentUserShared {} + ( { dashboards = RemoteData.Loading } + , Effect.getDashboards + { baseUrl = shared.velaAPIBaseURL + , session = shared.session + , onResponse = GetDashboardsResponse + } ) @@ -96,7 +105,7 @@ init shared route () = {-| Msg : custom type with possible messages. -} type Msg - = NoOp + = GetDashboardsResponse (Result (Http.Detailed.Error String) ( Http.Metadata, List Vela.Dashboard )) -- REFRESH | Tick { time : Time.Posix, interval : Interval.Interval } @@ -106,10 +115,20 @@ type Msg update : Shared.Model -> Route () -> Msg -> Model -> ( Model, Effect Msg ) update shared route msg model = case msg of - NoOp -> - ( model - , Effect.none - ) + GetDashboardsResponse response -> + case response of + Ok ( _, dashboards ) -> + ( { model | dashboards = RemoteData.Success dashboards } + , Effect.none + ) + + Err error -> + ( { model | dashboards = Errors.toFailure error } + , Effect.handleHttpError + { error = error + , shouldShowAlertFn = Errors.showAlertAlways + } + ) -- REFRESH Tick options -> @@ -153,9 +172,9 @@ view shared route model = } , main_ [ class "content-wrap" ] [ div [ Util.testAttribute "dashboards" ] <| - case shared.user of - RemoteData.Success u -> - if List.length u.dashboards > 0 then + case model.dashboards of + RemoteData.Success dashboards -> + if List.length dashboards > 0 then [ div [] [ h1 [] [ text "BETA something" ] , h2 [] [ text "Dashboards" ] @@ -176,7 +195,7 @@ view shared route model = ] , h2 [] [ text "๐Ÿ’ฌ Got Feedback?" ] , p [] [ text "Follow the feedback link in the top right to let us know your thoughts and ideas. We really need your feedback on the whole dashboard experience to prioritize what we'll focus on for the next version." ] - , viewDashboards u.dashboards + , viewDashboards dashboards ] ] @@ -195,9 +214,25 @@ view shared route model = ] ] - _ -> - [ div [] [ text "no dashboards" ] + RemoteData.Failure error -> + [ span [] + [ text <| + case error of + Http.BadStatus statusCode -> + case statusCode of + 401 -> + "Unauthorized to retrieve dashboards" + + _ -> + "No dashboards found, there was an error with the server" + + _ -> + "No dashboards found, there was an error with the server" + ] ] + + _ -> + [ Components.Loading.viewSmallLoader ] ] ] } @@ -205,7 +240,15 @@ view shared route model = {-| viewDashboards : renders a list of dashboard id links. -} -viewDashboards : List String -> Html Msg +viewDashboards : List Vela.Dashboard -> Html Msg viewDashboards dashboards = div [] - (List.map (\dashboard -> div [] [ a [ Route.Path.href <| Route.Path.Dashboards_Dashboard_ { dashboard = dashboard } ] [ text dashboard ] ]) dashboards) + (List.map + (\dashboard -> + div [] + [ a [ Route.Path.href <| Route.Path.Dashboards_Dashboard_ { dashboard = dashboard.dashboard.id } ] + [ text dashboard.dashboard.name ] + ] + ) + dashboards + ) diff --git a/src/elm/Pages/Dashboards/Dashboard_.elm b/src/elm/Pages/Dashboards/Dashboard_.elm index 4d32587e3..1f37abfdf 100644 --- a/src/elm/Pages/Dashboards/Dashboard_.elm +++ b/src/elm/Pages/Dashboards/Dashboard_.elm @@ -36,7 +36,6 @@ import Route.Path import Shared import Time import Utils.Errors as Errors -import Utils.Favicons as Favicons import Utils.Helpers as Util import Utils.Interval as Interval import Vela diff --git a/src/elm/Vela.elm b/src/elm/Vela.elm index 063b6d33f..a3462b547 100644 --- a/src/elm/Vela.elm +++ b/src/elm/Vela.elm @@ -59,6 +59,7 @@ module Vela exposing , decodeBuildGraph , decodeBuilds , decodeDashboard + , decodeDashboards , decodeDeployment , decodeDeployments , decodeGraphInteraction @@ -220,6 +221,11 @@ decodeDashboard = |> optional "repos" (Json.Decode.list decodeDashboardRepoCard) [] +decodeDashboards : Decoder (List Dashboard) +decodeDashboards = + Json.Decode.list decodeDashboard + + decodeDashboardItem : Decoder DashboardItem decodeDashboardItem = Json.Decode.succeed DashboardItem From 68607afd5186b07f6d8b57523eaa11cef8bec341 Mon Sep 17 00:00:00 2001 From: wass3rw3rk <49894298+wass3rw3rk@users.noreply.github.com> Date: Mon, 16 Sep 2024 15:03:00 -0500 Subject: [PATCH 03/12] we can route to dashboards page now --- src/elm/Pages/Dashboards/Dashboard_.elm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/elm/Pages/Dashboards/Dashboard_.elm b/src/elm/Pages/Dashboards/Dashboard_.elm index 1f37abfdf..30335ba02 100644 --- a/src/elm/Pages/Dashboards/Dashboard_.elm +++ b/src/elm/Pages/Dashboards/Dashboard_.elm @@ -201,7 +201,7 @@ view shared route model = crumbs = [ ( "Overview", Just Route.Path.Home_ ) - , ( "Dashboards", Nothing ) + , ( "Dashboards", Just Route.Path.Dashboards ) , ( dashboardName, Nothing ) ] in From e0c3ce97790be4f3ae83e9c634159357abea7d75 Mon Sep 17 00:00:00 2001 From: wass3rw3rk <49894298+wass3rw3rk@users.noreply.github.com> Date: Mon, 16 Sep 2024 15:03:35 -0500 Subject: [PATCH 04/12] borrow styles from repos page --- src/elm/Pages/Dashboards.elm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/elm/Pages/Dashboards.elm b/src/elm/Pages/Dashboards.elm index 8caa91eae..8f0c5a822 100644 --- a/src/elm/Pages/Dashboards.elm +++ b/src/elm/Pages/Dashboards.elm @@ -10,7 +10,7 @@ import Components.Crumbs import Components.Loading import Components.Nav import Effect exposing (Effect) -import Html exposing (Html, a, code, div, h1, h2, li, main_, p, span, text, ul) +import Html exposing (Html, a, code, div, h1, h2, hr, li, main_, p, span, text, ul) import Html.Attributes exposing (class) import Http import Http.Detailed @@ -175,7 +175,7 @@ view shared route model = case model.dashboards of RemoteData.Success dashboards -> if List.length dashboards > 0 then - [ div [] + [ div [ class "dashboards" ] [ h1 [] [ text "BETA something" ] , h2 [] [ text "Dashboards" ] , p [] [ text "UI Dashboard functionality is very minimal in this Vela version." ] @@ -183,9 +183,6 @@ view shared route model = [ li [] [ text "Manage dashboards with the CLI or API" ] - , li [] - [ text "Dashboard names do not display on this page yet" - ] , li [] [ text "You'll only see dashboards you created" ] @@ -242,12 +239,15 @@ view shared route model = -} viewDashboards : List Vela.Dashboard -> Html Msg viewDashboards dashboards = - div [] + div [ class "repo-list" ] (List.map (\dashboard -> - div [] + div [ class "item" ] [ a [ Route.Path.href <| Route.Path.Dashboards_Dashboard_ { dashboard = dashboard.dashboard.id } ] [ text dashboard.dashboard.name ] + , div [ class "buttons" ] + [ a [ class "button", Route.Path.href <| Route.Path.Dashboards_Dashboard_ { dashboard = dashboard.dashboard.id } ] [ text "View" ] + ] ] ) dashboards From 67109c32e6ffe06aaf9a6e60aa66a30a005c8b1e Mon Sep 17 00:00:00 2001 From: wass3rw3rk <49894298+wass3rw3rk@users.noreply.github.com> Date: Mon, 16 Sep 2024 15:56:26 -0500 Subject: [PATCH 05/12] words --- src/elm/Pages/Dashboards.elm | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/elm/Pages/Dashboards.elm b/src/elm/Pages/Dashboards.elm index 8f0c5a822..091b45b29 100644 --- a/src/elm/Pages/Dashboards.elm +++ b/src/elm/Pages/Dashboards.elm @@ -176,36 +176,26 @@ view shared route model = RemoteData.Success dashboards -> if List.length dashboards > 0 then [ div [ class "dashboards" ] - [ h1 [] [ text "BETA something" ] - , h2 [] [ text "Dashboards" ] - , p [] [ text "UI Dashboard functionality is very minimal in this Vela version." ] + [ h1 [] [ text "Dashboards (beta)" ] + , viewDashboards dashboards + , h2 [] [ text "๐Ÿงช Beta Limitations" ] + , p [] [ text "This is an early version of Dashboards. Please be aware of the following:" ] , ul [] - [ li [] - [ text "Manage dashboards with the CLI or API" - ] - , li [] - [ text "You'll only see dashboards you created" - ] - , li [] - [ text "You won't see dashboards that were shared with you, or you were added to as an admin; so you might want to save those links!" - ] + [ li [] [ text "You have to use CLI/API to manage dashboards" ] + , li [] [ text "You can only list dashboards you created" ] + , li [] [ text "Bookmark or save links to dashboards you didn't create" ] ] , h2 [] [ text "๐Ÿ’ฌ Got Feedback?" ] - , p [] [ text "Follow the feedback link in the top right to let us know your thoughts and ideas. We really need your feedback on the whole dashboard experience to prioritize what we'll focus on for the next version." ] - , viewDashboards dashboards + , p [] [ text "Help us shape Dashboards. What do you want to see? Use the \"feedback\" link in the top right!" ] ] ] else [ div [ class "dashboards" ] - [ h1 [] [ text "Welcome to dashboards!" ] + [ h1 [] [ text "Welcome to Dashboards (beta)!" ] , h2 [] [ text "โœจ Want to create a new dashboard?" ] , p [] [ text "Use the Vela CLI to add a new dashboard:" ] , code [ class "shell" ] [ text "vela add dashboard --help" ] - , h2 [] [ text "๐Ÿš€ Already have a dashboard?" ] - , p [] [ text "Check your available dashboards with:" ] - , code [ class "shell" ] [ text "vela get dashboards" ] - , p [] [ text "Take note of your dashboard ID you are interested in and and add it to the current URL to view it." ] , h2 [] [ text "๐Ÿ’ฌ Got Feedback?" ] , p [] [ text "Follow the link in the top right to let us know your thoughts and ideas." ] ] From 5e0c5668844a959c0be573ca6cbc502aaa8956f9 Mon Sep 17 00:00:00 2001 From: wass3rw3rk <49894298+wass3rw3rk@users.noreply.github.com> Date: Tue, 17 Sep 2024 16:00:50 -0500 Subject: [PATCH 06/12] some wip work - getting closer --- src/elm/Pages/Dashboards.elm | 67 ++++++++++++++++++++++++------------ src/elm/Vela.elm | 2 ++ src/scss/_dashboards.scss | 33 ++++++++++++++++++ 3 files changed, 80 insertions(+), 22 deletions(-) diff --git a/src/elm/Pages/Dashboards.elm b/src/elm/Pages/Dashboards.elm index 091b45b29..b5259cf6a 100644 --- a/src/elm/Pages/Dashboards.elm +++ b/src/elm/Pages/Dashboards.elm @@ -133,7 +133,11 @@ update shared route msg model = -- REFRESH Tick options -> ( model - , Effect.none + , Effect.getDashboards + { baseUrl = shared.velaAPIBaseURL + , session = shared.session + , onResponse = GetDashboardsResponse + } ) @@ -176,28 +180,30 @@ view shared route model = RemoteData.Success dashboards -> if List.length dashboards > 0 then [ div [ class "dashboards" ] - [ h1 [] [ text "Dashboards (beta)" ] - , viewDashboards dashboards - , h2 [] [ text "๐Ÿงช Beta Limitations" ] - , p [] [ text "This is an early version of Dashboards. Please be aware of the following:" ] - , ul [] - [ li [] [ text "You have to use CLI/API to manage dashboards" ] - , li [] [ text "You can only list dashboards you created" ] - , li [] [ text "Bookmark or save links to dashboards you didn't create" ] - ] - , h2 [] [ text "๐Ÿ’ฌ Got Feedback?" ] - , p [] [ text "Help us shape Dashboards. What do you want to see? Use the \"feedback\" link in the top right!" ] - ] + (h1 [] [ text "Dashboards", span [ class "beta" ] [ text "beta" ] ] + :: viewDashboards dashboards + ++ [ h2 [] [ text "๐Ÿงช Beta Limitations" ] + , p [] [ text "This is an early version of Dashboards. Please be aware of the following:" ] + , ul [] + [ li [] [ text "You have to use CLI/API to manage (add, edit, etc) dashboards" ] + , li [] [ text "This page will only show dashboards you created" ] + , li [] [ text "Bookmark or save links to dashboards you didn't create" ] + ] + , h2 [] [ text "๐Ÿ’ฌ Got Feedback?" ] + , p [] [ text "Help us shape Dashboards. What do you want to see? Use the \"feedback\" link in the top right!" ] + ] + ) ] else [ div [ class "dashboards" ] - [ h1 [] [ text "Welcome to Dashboards (beta)!" ] + [ h1 [] [ text "Welcome to Dashboards", span [ class "beta" ] [ text "beta" ] ] , h2 [] [ text "โœจ Want to create a new dashboard?" ] , p [] [ text "Use the Vela CLI to add a new dashboard:" ] , code [ class "shell" ] [ text "vela add dashboard --help" ] + , p [] [ text "Once you added dashboards, they will show on this page." ] , h2 [] [ text "๐Ÿ’ฌ Got Feedback?" ] - , p [] [ text "Follow the link in the top right to let us know your thoughts and ideas." ] + , p [] [ text "Follow the \"feedback\" link in the top right to let us know your thoughts and ideas." ] ] ] @@ -225,20 +231,37 @@ view shared route model = } -{-| viewDashboards : renders a list of dashboard id links. +{-| viewDashboards : renders a list of dashboard links. -} -viewDashboards : List Vela.Dashboard -> Html Msg +viewDashboards : List Vela.Dashboard -> List (Html Msg) viewDashboards dashboards = - div [ class "repo-list" ] - (List.map + dashboards + |> List.map (\dashboard -> + let + dashboardLink = + Route.Path.Dashboards_Dashboard_ { dashboard = dashboard.dashboard.id } + |> Route.Path.href + in div [ class "item" ] - [ a [ Route.Path.href <| Route.Path.Dashboards_Dashboard_ { dashboard = dashboard.dashboard.id } ] + [ a [ dashboardLink ] [ text dashboard.dashboard.name ] , div [ class "buttons" ] - [ a [ class "button", Route.Path.href <| Route.Path.Dashboards_Dashboard_ { dashboard = dashboard.dashboard.id } ] [ text "View" ] + [ a [ class "button", dashboardLink ] [ text "View" ] ] + , viewDashboardRepos dashboard.repos ] ) - dashboards + + +{-| viewDashboards : renders a list of repos belonging to a dashboard. +-} +viewDashboardRepos : List Vela.DashboardRepoCard -> Html Msg +viewDashboardRepos repos = + div [ class "dashboard-repos" ] + (repos + |> List.map + (\repo -> + div [ class "dashboard-repos-item" ] [ text (repo.org ++ "/" ++ repo.name ++ " (" ++ String.fromInt (List.length repo.builds) ++ ")") ] + ) ) diff --git a/src/elm/Vela.elm b/src/elm/Vela.elm index a3462b547..8f7d61f86 100644 --- a/src/elm/Vela.elm +++ b/src/elm/Vela.elm @@ -210,6 +210,7 @@ type alias DashboardRepoCard = { org : String , name : String , counter : Int + , active : Bool , builds : List Build } @@ -245,6 +246,7 @@ decodeDashboardRepoCard = |> optional "org" string "" |> optional "name" string "" |> optional "counter" int -1 + |> optional "active" bool False |> optional "builds" (Json.Decode.list decodeBuild) [] diff --git a/src/scss/_dashboards.scss b/src/scss/_dashboards.scss index a7eaeda9b..ab6425558 100644 --- a/src/scss/_dashboards.scss +++ b/src/scss/_dashboards.scss @@ -2,6 +2,39 @@ // styles for the dashboard pages +.beta { + margin-left: 0.5rem; + padding: 0.25rem 0.4rem; + + font-size: 0.8rem; + vertical-align: top; + + background-color: var(--color-green-dark); +} + +.dashboards .item { + flex-wrap: wrap; +} + +.dashboard-repos { + flex-basis: 100%; + margin-top: 1rem; + padding: 1rem 1rem 0 0; + + border-top: 2px dotted var(--color-bg-light); +} + +.dashboard-repos-item { + display: inline-block; + margin-right: 1rem; + margin-bottom: .5rem; + padding: .25rem .5rem; + + font-size: .8rem; + + background-color: var(--color-bg-darkest); +} + .dashboard-title { border-bottom: var(--line-width) solid var(--color-secondary); } From 8451e0859aedc4a051959cabde9defa89701ae4b Mon Sep 17 00:00:00 2001 From: wass3rw3rk <49894298+wass3rw3rk@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:55:24 -0500 Subject: [PATCH 07/12] add status icon and id + tweak repo item css --- src/elm/Pages/Dashboards.elm | 26 +++++++++++++---- src/scss/_dashboards.scss | 55 ++++++++++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 8 deletions(-) diff --git a/src/elm/Pages/Dashboards.elm b/src/elm/Pages/Dashboards.elm index b5259cf6a..ec95e853c 100644 --- a/src/elm/Pages/Dashboards.elm +++ b/src/elm/Pages/Dashboards.elm @@ -9,8 +9,9 @@ import Auth import Components.Crumbs import Components.Loading import Components.Nav +import Components.Svgs import Effect exposing (Effect) -import Html exposing (Html, a, code, div, h1, h2, hr, li, main_, p, span, text, ul) +import Html exposing (Html, a, code, div, h1, h2, li, main_, p, span, text, ul) import Html.Attributes exposing (class) import Http import Http.Detailed @@ -244,8 +245,10 @@ viewDashboards dashboards = |> Route.Path.href in div [ class "item" ] - [ a [ dashboardLink ] - [ text dashboard.dashboard.name ] + [ span [ class "dashboard-item-title" ] + [ a [ dashboardLink ] [ text dashboard.dashboard.name ] + , code [] [ text dashboard.dashboard.id ] + ] , div [ class "buttons" ] [ a [ class "button", dashboardLink ] [ text "View" ] ] @@ -254,7 +257,7 @@ viewDashboards dashboards = ) -{-| viewDashboards : renders a list of repos belonging to a dashboard. +{-| viewDashboardRepos : renders a list of repos belonging to a dashboard. -} viewDashboardRepos : List Vela.DashboardRepoCard -> Html Msg viewDashboardRepos repos = @@ -262,6 +265,19 @@ viewDashboardRepos repos = (repos |> List.map (\repo -> - div [ class "dashboard-repos-item" ] [ text (repo.org ++ "/" ++ repo.name ++ " (" ++ String.fromInt (List.length repo.builds) ++ ")") ] + let + statusIcon = + case List.head repo.builds of + Just build -> + Components.Svgs.recentBuildStatusToIcon build.status 0 + + Nothing -> + Components.Svgs.recentBuildStatusToIcon Vela.Pending 0 + in + div + [ class "dashboard-repos-item" ] + [ statusIcon + , text (repo.org ++ "/" ++ repo.name ++ " (" ++ String.fromInt (List.length repo.builds) ++ ")") + ] ) ) diff --git a/src/scss/_dashboards.scss b/src/scss/_dashboards.scss index ab6425558..9d2417b77 100644 --- a/src/scss/_dashboards.scss +++ b/src/scss/_dashboards.scss @@ -17,22 +17,71 @@ } .dashboard-repos { + display: flex; flex-basis: 100%; + flex-wrap: wrap; + gap: 1rem; margin-top: 1rem; padding: 1rem 1rem 0 0; border-top: 2px dotted var(--color-bg-light); } +.dashboard-item-title code { + margin-left: 1rem; + + color: var(--color-bg-light); + font-size: 1rem; +} + .dashboard-repos-item { - display: inline-block; - margin-right: 1rem; - margin-bottom: .5rem; + display: flex; + gap: .5rem; + align-items: center; padding: .25rem .5rem; font-size: .8rem; background-color: var(--color-bg-darkest); + + .-icon { + width: 1rem; + height: 1rem; + + fill: none; + + &.-running { + background-color: var(--color-yellow); + + stroke: var(--color-bg); + } + + &.-failure, + &.-error { + background-color: var(--color-red); + + stroke: var(--color-bg); + } + + &.-canceled { + background-color: var(--color-cyan-dark); + + stroke: var(--color-bg); + } + + &.-success { + background-color: var(--color-green); + + stroke: var(--color-bg); + } + + &.-pending { + background-color: var(--color-bg-light); + + fill: var(--color-bg); + stroke: var(--color-bg); + } + } } .dashboard-title { From 8df00924534a7244e914416899bc96e70d1016d6 Mon Sep 17 00:00:00 2001 From: wass3rw3rk <49894298+wass3rw3rk@users.noreply.github.com> Date: Wed, 18 Sep 2024 15:59:01 -0500 Subject: [PATCH 08/12] lint fix --- src/scss/_dashboards.scss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scss/_dashboards.scss b/src/scss/_dashboards.scss index 9d2417b77..a5bb7250e 100644 --- a/src/scss/_dashboards.scss +++ b/src/scss/_dashboards.scss @@ -36,11 +36,11 @@ .dashboard-repos-item { display: flex; - gap: .5rem; + gap: 0.5rem; align-items: center; - padding: .25rem .5rem; + padding: 0.25rem 0.5rem; - font-size: .8rem; + font-size: 0.8rem; background-color: var(--color-bg-darkest); From e334fe30fbe35dcf9d9af28022890ade71e9c667 Mon Sep 17 00:00:00 2001 From: wass3rw3rk <49894298+wass3rw3rk@users.noreply.github.com> Date: Thu, 19 Sep 2024 10:47:14 -0500 Subject: [PATCH 09/12] add tests --- cypress/fixtures/user_dashboards.json | 63 ++++++++++++++++++++++++++ cypress/integration/dashboards.spec.js | 54 ++++++++++++++++++++++ src/elm/Pages/Dashboards.elm | 51 +++++++++++---------- 3 files changed, 145 insertions(+), 23 deletions(-) create mode 100644 cypress/fixtures/user_dashboards.json diff --git a/cypress/fixtures/user_dashboards.json b/cypress/fixtures/user_dashboards.json new file mode 100644 index 000000000..98db5215d --- /dev/null +++ b/cypress/fixtures/user_dashboards.json @@ -0,0 +1,63 @@ +[ + { + "dashboard": { + "id": "6e26a6d0-2fc3-4531-a04d-678a58135288", + "name": "demo dashboard", + "created_at": 1726757028, + "created_by": "CookieCat", + "updated_at": 1726757028, + "updated_by": "CookieCat", + "admins": [ + { + "id": 1, + "name": "CookieCat", + "active": true + } + ], + "repos": [ + { + "id": 1, + "name": "github/repo1" + } + ] + }, + "repos": [ + { + "org": "github", + "name": "repo1", + "counter": 1, + "active": true, + "builds": [ + { + "number": 1, + "started": 1726757097, + "sender": "CookieCat", + "ref": "refs/heads/main", + "status": "running", + "event": "push", + "branch": "master", + "link": "http://vela.example.com/github/repo1/1" + } + ] + } + ] + }, + { + "dashboard": { + "id": "c4e8f563-4784-4b4b-9534-3007d579dc2a", + "name": "another demo dashboard", + "created_at": 1726757636, + "created_by": "CookieCat", + "updated_at": 1726757636, + "updated_by": "CookieCat", + "admins": [ + { + "id": 1, + "name": "CookieCat", + "active": true + } + ], + "repos": [] + } + } +] diff --git a/cypress/integration/dashboards.spec.js b/cypress/integration/dashboards.spec.js index 2ca8896b7..9345be58b 100644 --- a/cypress/integration/dashboards.spec.js +++ b/cypress/integration/dashboards.spec.js @@ -3,6 +3,60 @@ */ context('Dashboards', () => { + context('main dashboards page shows message', () => { + beforeEach(() => { + cy.server(); + cy.route( + 'GET', + '*api/v1/user/dashboards', + 'fixture:user_dashboards.json', + ); + cy.login('/dashboards'); + }); + + it('shows the welcome message', () => { + cy.get('[data-test=dashboards]').contains('Dashboards'); + }); + + it('shows the list of dashboards', () => { + cy.get('[data-test=dashboard-item]').should('have.length', 2); + }); + + it('shows the repos within a dashboard', () => { + cy.get('[data-test=dashboard-repos]').first().contains('github/repo1'); + }); + + it('shows a message when there are no repos', () => { + cy.get('[data-test=dashboard-repos]') + .eq(1) + .contains('No repositories in this dashboard'); + }); + + it('clicking dashoard name navigates to dashboard page', () => { + cy.get('[data-test=dashboard-item]') + .first() + .within(() => { + cy.get('a').first().click(); + cy.location('pathname').should( + 'eq', + '/dashboards/6e26a6d0-2fc3-4531-a04d-678a58135288', + ); + }); + }); + }); + + context('main dashboards page shows message', () => { + beforeEach(() => { + cy.server(); + cy.route( + 'GET', + '*api/v1/user/dashboards', + 'fixture:user_dashboards.json', + ); + cy.login('/dashboards'); + }); + }); + context('server returns dashboard with 3 cards, one without builds', () => { beforeEach(() => { cy.server(); diff --git a/src/elm/Pages/Dashboards.elm b/src/elm/Pages/Dashboards.elm index ec95e853c..6c404395c 100644 --- a/src/elm/Pages/Dashboards.elm +++ b/src/elm/Pages/Dashboards.elm @@ -244,7 +244,7 @@ viewDashboards dashboards = Route.Path.Dashboards_Dashboard_ { dashboard = dashboard.dashboard.id } |> Route.Path.href in - div [ class "item" ] + div [ class "item", Util.testAttribute "dashboard-item" ] [ span [ class "dashboard-item-title" ] [ a [ dashboardLink ] [ text dashboard.dashboard.name ] , code [] [ text dashboard.dashboard.id ] @@ -252,32 +252,37 @@ viewDashboards dashboards = , div [ class "buttons" ] [ a [ class "button", dashboardLink ] [ text "View" ] ] - , viewDashboardRepos dashboard.repos + , viewDashboardRepos dashboard.repos dashboard.dashboard.id ] ) {-| viewDashboardRepos : renders a list of repos belonging to a dashboard. -} -viewDashboardRepos : List Vela.DashboardRepoCard -> Html Msg -viewDashboardRepos repos = - div [ class "dashboard-repos" ] - (repos - |> List.map - (\repo -> - let - statusIcon = - case List.head repo.builds of - Just build -> - Components.Svgs.recentBuildStatusToIcon build.status 0 - - Nothing -> - Components.Svgs.recentBuildStatusToIcon Vela.Pending 0 - in - div - [ class "dashboard-repos-item" ] - [ statusIcon - , text (repo.org ++ "/" ++ repo.name ++ " (" ++ String.fromInt (List.length repo.builds) ++ ")") - ] - ) +viewDashboardRepos : List Vela.DashboardRepoCard -> String -> Html Msg +viewDashboardRepos repos dashboardId = + div [ class "dashboard-repos", Util.testAttribute "dashboard-repos" ] + (if List.length repos > 0 then + repos + |> List.map + (\repo -> + let + statusIcon = + case List.head repo.builds of + Just build -> + Components.Svgs.recentBuildStatusToIcon build.status 0 + + Nothing -> + Components.Svgs.recentBuildStatusToIcon Vela.Pending 0 + in + div + [ class "dashboard-repos-item" ] + [ statusIcon + , text (repo.org ++ "/" ++ repo.name ++ " (" ++ String.fromInt (List.length repo.builds) ++ ")") + ] + ) + + else + [ text <| "โš ๏ธ No repositories in this dashboard. Use the CLI to add some: vela update dashboard --id " + ++ dashboardId ++ " --add-repos org/repo" ] ) From 02beb57c71386c36e1fd1be08aebcaaf94017448 Mon Sep 17 00:00:00 2001 From: wass3rw3rk <49894298+wass3rw3rk@users.noreply.github.com> Date: Thu, 19 Sep 2024 10:51:03 -0500 Subject: [PATCH 10/12] elm format --- src/elm/Pages/Dashboards.elm | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/elm/Pages/Dashboards.elm b/src/elm/Pages/Dashboards.elm index 6c404395c..89b54376e 100644 --- a/src/elm/Pages/Dashboards.elm +++ b/src/elm/Pages/Dashboards.elm @@ -281,8 +281,11 @@ viewDashboardRepos repos dashboardId = , text (repo.org ++ "/" ++ repo.name ++ " (" ++ String.fromInt (List.length repo.builds) ++ ")") ] ) - - else - [ text <| "โš ๏ธ No repositories in this dashboard. Use the CLI to add some: vela update dashboard --id " - ++ dashboardId ++ " --add-repos org/repo" ] + + else + [ text <| + "โš ๏ธ No repositories in this dashboard. Use the CLI to add some: vela update dashboard --id " + ++ dashboardId + ++ " --add-repos org/repo" + ] ) From fbad3233ee6233dfd93282e87145162f751560b9 Mon Sep 17 00:00:00 2001 From: wass3rw3rk <49894298+wass3rw3rk@users.noreply.github.com> Date: Thu, 19 Sep 2024 11:02:16 -0500 Subject: [PATCH 11/12] remove redundant test --- cypress/integration/dashboards.spec.js | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/cypress/integration/dashboards.spec.js b/cypress/integration/dashboards.spec.js index 9345be58b..e9cf985a9 100644 --- a/cypress/integration/dashboards.spec.js +++ b/cypress/integration/dashboards.spec.js @@ -3,7 +3,7 @@ */ context('Dashboards', () => { - context('main dashboards page shows message', () => { + context('main dashboards page', () => { beforeEach(() => { cy.server(); cy.route( @@ -14,10 +14,6 @@ context('Dashboards', () => { cy.login('/dashboards'); }); - it('shows the welcome message', () => { - cy.get('[data-test=dashboards]').contains('Dashboards'); - }); - it('shows the list of dashboards', () => { cy.get('[data-test=dashboard-item]').should('have.length', 2); }); @@ -166,15 +162,4 @@ context('Dashboards', () => { ); }); }); - - context('main dashboards page shows message', () => { - beforeEach(() => { - cy.server(); - cy.login('/dashboards'); - }); - - it('shows the welcome message', () => { - cy.get('[data-test=dashboards]').contains('Welcome to dashboards!'); - }); - }); }); From f37f5cbdf0afdffe25c78f53a5646c4122fc7f9a Mon Sep 17 00:00:00 2001 From: wass3rw3rk <49894298+wass3rw3rk@users.noreply.github.com> Date: Thu, 19 Sep 2024 15:05:57 -0500 Subject: [PATCH 12/12] remove build number --- src/elm/Pages/Dashboards.elm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/elm/Pages/Dashboards.elm b/src/elm/Pages/Dashboards.elm index 89b54376e..66617ad06 100644 --- a/src/elm/Pages/Dashboards.elm +++ b/src/elm/Pages/Dashboards.elm @@ -278,7 +278,7 @@ viewDashboardRepos repos dashboardId = div [ class "dashboard-repos-item" ] [ statusIcon - , text (repo.org ++ "/" ++ repo.name ++ " (" ++ String.fromInt (List.length repo.builds) ++ ")") + , text (repo.org ++ "/" ++ repo.name) ] )