diff --git a/cypress/fixtures/repositories_10a.json b/cypress/fixtures/repositories_10a.json new file mode 100644 index 000000000..7b7167c1f --- /dev/null +++ b/cypress/fixtures/repositories_10a.json @@ -0,0 +1,222 @@ +[ + { + "id": 0, + "user_id": 15, + "org": "vela", + "name": "bjajzltmfr", + "full_name": "vela/bjajzltmfr", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 1, + "user_id": 74, + "org": "vela", + "name": "epcuczo", + "full_name": "vela/epcuczo", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 2, + "user_id": 27, + "org": "vela", + "name": "pncrdovo", + "full_name": "vela/pncrdovo", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 3, + "user_id": 20, + "org": "vela", + "name": "sfhshmiwwyk", + "full_name": "vela/sfhshmiwwyk", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 4, + "user_id": 66, + "org": "vela", + "name": "fvxrjqwqr", + "full_name": "vela/fvxrjqwqr", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 5, + "user_id": 93, + "org": "vela", + "name": "uamaip", + "full_name": "vela/uamaip", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 6, + "user_id": 7, + "org": "vela", + "name": "yaumkvhd", + "full_name": "vela/yaumkvhd", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 7, + "user_id": 87, + "org": "vela", + "name": "isxkgjbves", + "full_name": "vela/isxkgjbves", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 8, + "user_id": 36, + "org": "vela", + "name": "qwunbamrun", + "full_name": "vela/qwunbamrun", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 9, + "user_id": 10, + "org": "vela", + "name": "atclrzel", + "full_name": "vela/atclrzel", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + } +] diff --git a/cypress/fixtures/repositories_10b.json b/cypress/fixtures/repositories_10b.json new file mode 100644 index 000000000..e7f0d0c85 --- /dev/null +++ b/cypress/fixtures/repositories_10b.json @@ -0,0 +1,222 @@ +[ + { + "id": 10, + "user_id": 89, + "org": "vela", + "name": "gkgdajuj", + "full_name": "vela/gkgdajuj", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 11, + "user_id": 61, + "org": "vela", + "name": "slcuueozw", + "full_name": "vela/slcuueozw", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 12, + "user_id": 23, + "org": "vela", + "name": "knsrbirh", + "full_name": "vela/knsrbirh", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 13, + "user_id": 44, + "org": "vela", + "name": "twlvuybol", + "full_name": "vela/twlvuybol", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 14, + "user_id": 48, + "org": "vela", + "name": "cceptb", + "full_name": "vela/cceptb", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 15, + "user_id": 36, + "org": "vela", + "name": "biumnadx", + "full_name": "vela/biumnadx", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 16, + "user_id": 75, + "org": "vela", + "name": "kjwlvk", + "full_name": "vela/kjwlvk", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 17, + "user_id": 64, + "org": "vela", + "name": "guemqmucei", + "full_name": "vela/guemqmucei", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 18, + "user_id": 55, + "org": "vela", + "name": "syvdpeb", + "full_name": "vela/syvdpeb", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + }, + { + "id": 19, + "user_id": 44, + "org": "vela", + "name": "svjzhodm", + "full_name": "vela/svjzhodm", + "link": "", + "clone": "", + "branch": "master", + "timeout": 30, + "counter": 0, + "visibility": "public", + "private": false, + "trusted": true, + "active": true, + "allow_pull": false, + "allow_push": true, + "allow_deploy": false, + "allow_tag": false, + "allow_comment": false, + "pipeline_type": "yaml" + } +] diff --git a/cypress/integration/org.spec.js b/cypress/integration/org.spec.js new file mode 100644 index 000000000..647aae771 --- /dev/null +++ b/cypress/integration/org.spec.js @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2021 Target Brands, Inc. All rights reserved. + * Use of this source code is governed by the LICENSE file in this repository. + */ + +context('Org', () => { + context('Tabs', () => { + beforeEach(() => { + cy.server(); + cy.route({ + method: 'GET', + url: '*api/v1/repos/vela', + response: 'fixture:repositories_5.json', + }); + cy.login('/vela'); + }); + + it('should show 3 tabs', () => { + cy.get('[data-test=jump-Repositories]').should('be.visible'); + cy.get('[data-test=jump-Builds]').should('be.visible'); + cy.get('[data-test=jump-Secrets]').should('be.visible'); + }); + }); + + context('Repositories Tab', () => { + context('logged in and server returning 5 repos', () => { + beforeEach(() => { + cy.server(); + cy.route({ + method: 'GET', + url: '*api/v1/repos/vela', + response: 'fixture:repositories_5.json', + }); + cy.login('/vela'); + + cy.get('[data-test=repo-item]').as('repos'); + }); + + it('should show 5 repos', () => { + cy.get('@repos').should('have.length', 5); + }); + + it('should show 4 action buttons for each item', () => { + cy.get('@repos').each(($repo, i, $list) => { + cy.wrap($repo) + .find('.button') + .should('have.length', 4) + .should('be.visible'); + }); + }); + }); + + context('logged in and server returning > 10 repos', () => { + beforeEach(() => { + cy.server(); + cy.stubRepos(); + cy.login('/vela'); + + cy.get('[data-test=repo-item]').as('repos'); + }); + + it('should show the repos', () => { + cy.get('@repos').should('be.visible'); + }); + + it('should show the pager', () => { + cy.get('[data-test=pager-previous]') + .should('have.length', 2) + .should('be.visible') + .should('be.disabled'); + + cy.get('[data-test=pager-next]') + .should('have.length', 2) + .should('be.visible') + .should('not.be.disabled'); + }); + + it('should contain the page number on page 2', () => { + cy.visit('/vela?page=2'); + cy.title().should('include', 'page 2'); + }); + + it('should still show the pager on page 2', () => { + cy.visit('/vela?page=2'); + cy.get('[data-test=pager-previous]') + .should('have.length', 2) + .should('be.visible') + .should('not.be.disabled'); + + cy.get('[data-test=pager-next]') + .should('have.length', 2) + .should('be.visible') + .should('be.disabled'); + }); + }); + }); + + context('Builds Tab', () => { + context('logged in and returning 5 builds', () => { + beforeEach(() => { + cy.server(); + cy.route({ + method: 'GET', + url: '*api/v1/repos/vela/builds*', + response: 'fixture:builds_5.json', + }); + cy.login('/vela/builds'); + }); + + it('should show 5 builds', () => { + cy.get('[data-test=builds]').should('be.visible'); + }); + + it('should show the filter control', () => { + cy.get('[data-test=build-filter]').should('be.visible'); + }); + }); + + context('logged in and returning 20 builds', () => { + beforeEach(() => { + cy.server(); + cy.stubOrgBuilds(); + cy.login('/vela/builds'); + }); + + it('should show builds', () => { + cy.get('[data-test=builds]').should('be.visible'); + }); + + it('should show the pager', () => { + cy.get('[data-test=pager-previous]') + .should('have.length', 2) + .should('be.visible') + .should('be.disabled'); + + cy.get('[data-test=pager-next]') + .should('have.length', 2) + .should('be.visible') + .should('not.be.disabled'); + }); + + it('should update page title for page 2', () => { + cy.visit('/vela/builds?page=2'); + cy.title().should('include', 'page 2'); + }); + }); + }); + + context('Secrets Tab', () => { + beforeEach(() => { + cy.server(); + cy.route({ + method: 'GET', + url: '*api/v1/repos/vela', + response: 'fixture:repositories_5.json', + }); + cy.login('/vela'); + }); + + it('should navigate to the org secrets page', () => { + cy.get('[data-test=jump-Secrets').click(); + + // just testing navigation, secrets specific tests should cover this route + cy.location('pathname').should('eq', '/-/secrets/native/org/vela'); + }); + }); +}); diff --git a/cypress/support/commands.js b/cypress/support/commands.js index ea5a45f6d..e611b6703 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -98,6 +98,7 @@ Cypress.Commands.add('stubBuilds', () => { cy.server(); cy.fixture('builds_10a.json').as('buildsPage1'); cy.fixture('builds_10b.json').as('buildsPage2'); + cy.route({ method: 'GET', url: '*api/v1/repos/*/*/builds*', @@ -116,6 +117,51 @@ Cypress.Commands.add('stubBuilds', () => { }); }); +Cypress.Commands.add('stubOrgBuilds', () => { + cy.server(); + cy.fixture('builds_10a.json').as('buildsPage1'); + cy.fixture('builds_10b.json').as('buildsPage2'); + + cy.route({ + method: 'GET', + url: '*api/v1/repos/vela/builds*', + headers: { + link: `; rel="next", ; rel="last",`, + }, + response: '@buildsPage1', + }); + cy.route({ + method: 'GET', + url: '*api/v1/repos/vela/builds?page=2*', + headers: { + link: `; rel="first", ; rel="prev",`, + }, + response: '@buildsPage2', + }); +}); + +Cypress.Commands.add('stubRepos', () => { + cy.server(); + cy.fixture('repositories_10a.json').as('reposPage1'); + cy.fixture('repositories_10b.json').as('reposPage2'); + cy.route({ + method: 'GET', + url: '*api/v1/repos/vela*', + headers: { + link: `; rel="next", ; rel="last",`, + }, + response: '@reposPage1', + }); + cy.route({ + method: 'GET', + url: '*api/v1/repos/vela?page=2*', + headers: { + link: `; rel="first", ; rel="prev",`, + }, + response: '@reposPage2', + }); +}); + Cypress.Commands.add('stubBuildsFilter', () => { cy.server(); cy.fixture('builds_all.json').as('buildsAll'); diff --git a/src/elm/Api.elm b/src/elm/Api.elm index 113501ccc..e0554f409 100644 --- a/src/elm/Api.elm +++ b/src/elm/Api.elm @@ -463,11 +463,11 @@ getRepo model org repo = |> withAuth model.session -{-| getOrgRepositories : fetches single repo by org and repo name +{-| getOrgRepositories : fetches repos by org -} -getOrgRepositories : PartialModel a -> Org -> Request (List Repository) -getOrgRepositories model org = - get model.velaAPI (Endpoint.OrgRepositories org) decodeRepositories +getOrgRepositories : PartialModel a -> Maybe Pagination.Page -> Maybe Pagination.PerPage -> Org -> Request (List Repository) +getOrgRepositories model maybePage maybePerPage org = + get model.velaAPI (Endpoint.OrgRepositories maybePage maybePerPage org) decodeRepositories |> withAuth model.session diff --git a/src/elm/Api/Endpoint.elm b/src/elm/Api/Endpoint.elm index 4dc82501c..a9ca3b9da 100644 --- a/src/elm/Api/Endpoint.elm +++ b/src/elm/Api/Endpoint.elm @@ -44,7 +44,7 @@ type Endpoint | Token | Repositories (Maybe Pagination.Page) (Maybe Pagination.PerPage) | Repository Org Repo - | OrgRepositories Org + | OrgRepositories (Maybe Pagination.Page) (Maybe Pagination.PerPage) Org | RepositoryChown Org Repo | RepositoryRepair Org Repo | UserSourceRepositories @@ -87,8 +87,8 @@ toUrl api endpoint = Repository org repo -> url api [ "repos", org, repo ] [] - OrgRepositories org -> - url api [ "repos", org ] [] + OrgRepositories maybePage maybePerPage org -> + url api [ "repos", org ] <| Pagination.toQueryParams maybePage maybePerPage RepositoryChown org repo -> url api [ "repos", org, repo, "chown" ] [] diff --git a/src/elm/Crumbs.elm b/src/elm/Crumbs.elm index 67cafe8ae..1f240a5bd 100644 --- a/src/elm/Crumbs.elm +++ b/src/elm/Crumbs.elm @@ -98,7 +98,7 @@ toPath page = Pages.SourceRepositories -> [ overviewPage, accountPage, sourceRepositoriesPage ] - Pages.OrgRepositories org -> + Pages.OrgRepositories org _ _ -> let organizationPage = ( org, Nothing ) @@ -108,7 +108,7 @@ toPath page = Pages.Hooks org repo _ _ -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) currentRepo = ( repo, Nothing ) @@ -121,7 +121,7 @@ toPath page = Pages.RepoSettings org repo -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) currentRepo = ( repo, Nothing ) @@ -141,7 +141,7 @@ toPath page = Pages.RepoSecrets _ org repo _ _ -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) currentRepo = ( repo, Nothing ) @@ -151,7 +151,7 @@ toPath page = Pages.SharedSecrets _ org team maybePage _ -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) teamPage = ( team, Nothing ) @@ -164,7 +164,7 @@ toPath page = Pages.AddOrgSecret engine org -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) orgSecrets = ( "Secrets", Just <| Pages.OrgSecrets engine org Nothing Nothing ) @@ -174,7 +174,7 @@ toPath page = Pages.AddRepoSecret engine org repo -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) currentRepo = ( repo, Just <| Pages.RepoSecrets engine org repo Nothing Nothing ) @@ -184,7 +184,7 @@ toPath page = Pages.AddDeployment org repo -> let orgPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) currentRepo = ( repo, Just <| Pages.RepositoryDeployments org repo Nothing Nothing ) @@ -194,7 +194,7 @@ toPath page = Pages.PromoteDeployment org repo _ -> let orgPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) currentRepo = ( repo, Just <| Pages.RepositoryDeployments org repo Nothing Nothing ) @@ -204,7 +204,7 @@ toPath page = Pages.AddSharedSecret engine org team -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) teamPage = ( team, Nothing ) @@ -217,7 +217,7 @@ toPath page = Pages.OrgSecret engine org name -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) orgSecrets = ( "Secrets", Just <| Pages.OrgSecrets engine org Nothing Nothing ) @@ -230,7 +230,7 @@ toPath page = Pages.RepoSecret engine org repo name -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) currentRepo = ( repo, Just <| Pages.RepoSecrets engine org repo Nothing Nothing ) @@ -243,7 +243,7 @@ toPath page = Pages.SharedSecret engine org team name -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) teamPage = ( team, Nothing ) @@ -266,21 +266,21 @@ toPath page = Pages.RepositoryBuilds org repo maybePage maybePerPage maybeEvent -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) in [ overviewPage, organizationPage, ( repo, Just <| Pages.RepositoryBuilds org repo maybePage maybePerPage maybeEvent ) ] Pages.RepositoryDeployments org repo maybePage maybePerPage -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) in [ overviewPage, organizationPage, ( repo, Just <| Pages.RepositoryDeployments org repo maybePage maybePerPage ) ] Pages.Build org repo buildNumber _ -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) in [ overviewPage , organizationPage @@ -291,7 +291,7 @@ toPath page = Pages.BuildServices org repo buildNumber _ -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) in [ overviewPage , organizationPage @@ -302,7 +302,7 @@ toPath page = Pages.BuildPipeline org repo buildNumber _ _ _ -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) repoBuildsPage = ( repo, Just <| Pages.RepositoryBuilds org repo Nothing Nothing Nothing ) @@ -316,7 +316,7 @@ toPath page = Pages.Pipeline org repo _ _ _ -> let organizationPage = - ( org, Just <| Pages.OrgRepositories org ) + ( org, Just <| Pages.OrgRepositories org Nothing Nothing ) repoBuildsPage = ( repo, Just <| Pages.RepositoryBuilds org repo Nothing Nothing Nothing ) diff --git a/src/elm/Help/Commands.elm b/src/elm/Help/Commands.elm index d11637c42..1b4f817f5 100644 --- a/src/elm/Help/Commands.elm +++ b/src/elm/Help/Commands.elm @@ -85,16 +85,15 @@ commands page = [ listFavorites ] Pages.SourceRepositories -> - [ listFavorites ] + [] - Pages.OrgRepositories _ -> - [ listFavorites ] + Pages.OrgRepositories _ _ _ -> + [] Pages.Hooks org repo _ _ -> [ validate, listHooks org repo, viewHook org repo ] Pages.OrgBuilds _ _ _ _ -> - -- TODO: any way to do this in the cli? [] Pages.RepositoryBuilds org repo _ _ _ -> @@ -781,7 +780,7 @@ resourceLoaded args = Pages.SourceRepositories -> args.sourceRepos.success - Pages.OrgRepositories _ -> + Pages.OrgRepositories _ _ _ -> args.orgRepos.success Pages.OrgBuilds _ _ _ _ -> @@ -871,7 +870,7 @@ resourceLoading args = Pages.SourceRepositories -> args.sourceRepos.loading - Pages.OrgRepositories _ -> + Pages.OrgRepositories _ _ _ -> args.sourceRepos.loading Pages.OrgBuilds _ _ _ _ -> diff --git a/src/elm/Main.elm b/src/elm/Main.elm index 334154d66..926a4440e 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -21,7 +21,16 @@ import Errors exposing (Error, addErrorString, detailedErrorToString, toFailure) import Favorites exposing (toFavorite, updateFavorites) import FeatherIcons import File.Download as Download -import Focus exposing (ExpandTemplatesQuery, Fragment, RefQuery, focusFragmentToFocusId, lineRangeId, parseFocusFragment, resourceFocusFragment) +import Focus + exposing + ( ExpandTemplatesQuery + , Fragment + , RefQuery + , focusFragmentToFocusId + , lineRangeId + , parseFocusFragment + , resourceFocusFragment + ) import Help.Commands import Help.View import Html @@ -209,6 +218,9 @@ import Vela , updateHooksPager , updateHooksPerPage , updateOrgRepo + , updateOrgReposPage + , updateOrgReposPager + , updateOrgReposPerPage , updateOrgRepositories , updateRepo , updateRepoCounter @@ -572,6 +584,11 @@ update msg model = , Navigation.pushUrl model.navigationKey <| Routes.routeToUrl <| Routes.OrgBuilds org (Just pageNumber) maybePerPage maybeEvent ) + Pages.OrgRepositories org _ maybePerPage -> + ( { model | repo = updateOrgRepositories Loading rm } + , Navigation.pushUrl model.navigationKey <| Routes.routeToUrl <| Routes.OrgRepositories org (Just pageNumber) maybePerPage + ) + Pages.RepositoryBuilds org repo _ maybePerPage maybeEvent -> ( { model | repo = updateBuilds Loading rm } , Navigation.pushUrl model.navigationKey <| Routes.routeToUrl <| Routes.RepositoryBuilds org repo (Just pageNumber) maybePerPage maybeEvent @@ -1201,8 +1218,15 @@ update msg model = OrgRepositoriesResponse response -> case response of - Ok ( _, repoResponse ) -> - ( { model | repo = updateOrgRepositories (RemoteData.succeed repoResponse) rm }, Cmd.none ) + Ok ( meta, repoResponse ) -> + ( { model + | repo = + rm + |> updateOrgRepositories (RemoteData.succeed repoResponse) + |> updateOrgReposPager (Pagination.get meta.headers) + } + , Cmd.none + ) Err error -> ( { model | repo = updateOrgRepositories (toFailure error) rm }, addError error ) @@ -2277,23 +2301,17 @@ viewContent model = sourceReposMsgs ) - Pages.OrgRepositories org -> - ( org - , lazy2 Pages.Organization.viewOrgRepos org model.repo.orgRepos + Pages.OrgRepositories org maybePage _ -> + ( org ++ Util.pageToString maybePage + , div [] + [ Pager.view model.repo.orgRepos.pager Pager.prevNextLabels GotoPage + , lazy2 Pages.Organization.viewOrgRepos org model.repo.orgRepos + , Pager.view model.repo.orgRepos.pager Pager.prevNextLabels GotoPage + ] ) Pages.Hooks org repo maybePage _ -> - let - page : String - page = - case maybePage of - Nothing -> - "" - - Just p -> - " (page " ++ String.fromInt p ++ ")" - in - ( String.join "/" [ org, repo ] ++ " hooks" ++ page + ( String.join "/" [ org, repo ] ++ " hooks" ++ Util.pageToString maybePage , div [] [ Pager.view model.repo.hooks.pager Pager.defaultLabels GotoPage , lazy Pages.Hooks.view @@ -2318,29 +2336,19 @@ viewContent model = ) Pages.OrgSecrets engine org maybePage _ -> - let - page : String - page = - case maybePage of - Nothing -> - "" - - Just p -> - " (page " ++ String.fromInt p ++ ")" - in - ( String.join "/" [ org ] ++ " " ++ engine ++ " org secrets" ++ page + ( String.join "/" [ org ] ++ " " ++ engine ++ " org secrets" ++ Util.pageToString maybePage , div [] [ Html.map (\_ -> NoOp) <| lazy3 Pages.Secrets.View.viewOrgSecrets model False True - , Pager.view model.secretsModel.orgSecretsPager { previousLabel = "prev", nextLabel = "next" } GotoPage + , Pager.view model.secretsModel.orgSecretsPager Pager.prevNextLabels GotoPage ] ) Pages.SharedSecrets engine org team _ _ -> ( String.join "/" [ org, team ] ++ " " ++ engine ++ " shared secrets" , div [] - [ Pager.view model.secretsModel.sharedSecretsPager { previousLabel = "prev", nextLabel = "next" } GotoPage + [ Pager.view model.secretsModel.sharedSecretsPager Pager.prevNextLabels GotoPage , Html.map (\_ -> NoOp) <| lazy Pages.Secrets.View.viewSharedSecrets model - , Pager.view model.secretsModel.sharedSecretsPager { previousLabel = "prev", nextLabel = "next" } GotoPage + , Pager.view model.secretsModel.sharedSecretsPager Pager.prevNextLabels GotoPage ] ) @@ -2385,17 +2393,7 @@ viewContent model = ) Pages.RepositoryDeployments org repo maybePage _ -> - let - page : String - page = - case maybePage of - Nothing -> - "" - - Just p -> - " (page " ++ String.fromInt p ++ ")" - in - ( String.join "/" [ org, repo ] ++ " deployments" ++ page + ( String.join "/" [ org, repo ] ++ " deployments" ++ Util.pageToString maybePage , div [] [ lazy5 Pages.Deployments.View.viewDeployments model.repo.deployments model.time model.zone org repo , Pager.view model.repo.deployments.pager Pager.defaultLabels GotoPage @@ -2407,15 +2405,6 @@ viewContent model = repo = "" - page : String - page = - case maybePage of - Nothing -> - "" - - Just p -> - " (page " ++ String.fromInt p ++ ")" - shouldRenderFilter : Bool shouldRenderFilter = case ( model.repo.builds.builds, maybeEvent ) of @@ -2431,7 +2420,7 @@ viewContent model = _ -> False in - ( String.join "/" [ org ] ++ " builds" ++ page + ( org ++ " builds" ++ Util.pageToString maybePage , div [] [ viewBuildsFilter shouldRenderFilter org repo maybeEvent , Pager.view model.repo.builds.pager Pager.defaultLabels GotoPage @@ -2442,15 +2431,6 @@ viewContent model = Pages.RepositoryBuilds org repo maybePage _ maybeEvent -> let - page : String - page = - case maybePage of - Nothing -> - "" - - Just p -> - " (page " ++ String.fromInt p ++ ")" - shouldRenderFilter : Bool shouldRenderFilter = case ( model.repo.builds.builds, maybeEvent ) of @@ -2466,7 +2446,7 @@ viewContent model = _ -> False in - ( String.join "/" [ org, repo ] ++ " builds" ++ page + ( String.join "/" [ org, repo ] ++ " builds" ++ Util.pageToString maybePage , div [] [ viewBuildsFilter shouldRenderFilter org repo maybeEvent , Pager.view model.repo.builds.pager Pager.defaultLabels GotoPage @@ -2660,7 +2640,7 @@ helpArgs : Model -> Help.Commands.Model Msg helpArgs model = { user = helpArg model.user , sourceRepos = helpArg model.sourceRepos - , orgRepos = helpArg model.repo.orgRepos + , orgRepos = helpArg model.repo.orgRepos.orgRepos , builds = helpArg model.repo.builds.builds , deployments = helpArg model.repo.deployments.deployments , build = helpArg model.repo.build.build @@ -2738,8 +2718,8 @@ setNewPage route model = ( Routes.SourceRepositories, Authenticated _ ) -> loadSourceReposPage model - ( Routes.OrgRepositories org, Authenticated _ ) -> - loadOrgReposPage model org + ( Routes.OrgRepositories org maybePage maybePerPage, Authenticated _ ) -> + loadOrgReposPage model org maybePage maybePerPage ( Routes.Hooks org repo maybePage maybePerPage, Authenticated _ ) -> loadHooksPage model org repo maybePage maybePerPage @@ -2845,21 +2825,26 @@ loadSourceReposPage model = ( { model | page = Pages.SourceRepositories }, getCurrentUser model ) -loadOrgReposPage : Model -> Org -> ( Model, Cmd Msg ) -loadOrgReposPage model org = - case model.repo.orgRepos of +loadOrgReposPage : Model -> Org -> Maybe Pagination.Page -> Maybe Pagination.PerPage -> ( Model, Cmd Msg ) +loadOrgReposPage model org maybePage maybePerPage = + case model.repo.orgRepos.orgRepos of NotAsked -> - ( { model | page = Pages.OrgRepositories org } - , Api.try OrgRepositoriesResponse <| Api.getOrgRepositories model org + ( { model | page = Pages.OrgRepositories org maybePage maybePerPage } + , Api.try OrgRepositoriesResponse <| Api.getOrgRepositories model maybePage maybePerPage org ) Failure _ -> - ( { model | page = Pages.OrgRepositories org } - , Api.try OrgRepositoriesResponse <| Api.getOrgRepositories model org + ( { model | page = Pages.OrgRepositories org maybePage maybePerPage } + , Api.try OrgRepositoriesResponse <| Api.getOrgRepositories model maybePage maybePerPage org ) _ -> - ( { model | page = Pages.OrgRepositories org }, getCurrentUser model ) + ( { model | page = Pages.OrgRepositories org maybePage maybePerPage } + , Cmd.batch + [ getCurrentUser model + , Api.try OrgRepositoriesResponse <| Api.getOrgRepositories model maybePage maybePerPage org + ] + ) loadOverviewPage : Model -> ( Model, Cmd Msg ) @@ -2923,6 +2908,11 @@ loadOrgSubPage model org toPage = -- update builds pagination |> (\rm_ -> case toPage of + Pages.OrgRepositories _ maybePage maybePerPage -> + rm_ + |> updateOrgReposPage maybePage + |> updateOrgReposPerPage maybePerPage + Pages.OrgBuilds _ maybePage maybePerPage maybeEvent -> rm_ |> updateBuildsPage maybePage @@ -2934,12 +2924,16 @@ loadOrgSubPage model org toPage = |> updateBuildsPage Nothing |> updateBuildsPerPage Nothing |> updateBuildsEvent Nothing + |> updateOrgReposPage Nothing + |> updateOrgReposPerPage Nothing ) } , Cmd.batch [ getCurrentUser model - , getOrgRepos model org , case toPage of + Pages.OrgRepositories o maybePage maybePerPage -> + getOrgRepos model o maybePage maybePerPage + Pages.OrgBuilds o maybePage maybePerPage maybeEvent -> getOrgBuilds model o maybePage maybePerPage maybeEvent @@ -4133,9 +4127,9 @@ getRepo model org repo = Api.try RepoResponse <| Api.getRepo model org repo -getOrgRepos : Model -> Org -> Cmd Msg -getOrgRepos model org = - Api.try OrgRepositoriesResponse <| Api.getOrgRepositories model org +getOrgRepos : Model -> Org -> Maybe Pagination.Page -> Maybe Pagination.PerPage -> Cmd Msg +getOrgRepos model org maybePage maybePerPage = + Api.try OrgRepositoriesResponse <| Api.getOrgRepositories model maybePage maybePerPage org getOrgBuilds : Model -> Org -> Maybe Pagination.Page -> Maybe Pagination.PerPage -> Maybe Event -> Cmd Msg diff --git a/src/elm/Nav.elm b/src/elm/Nav.elm index abbad50d1..c23f341f6 100644 --- a/src/elm/Nav.elm +++ b/src/elm/Nav.elm @@ -104,7 +104,7 @@ navButtons model { fetchSourceRepos, toggleFavorite, restartBuild, cancelBuild } ] [ text "Source Repositories" ] - Pages.OrgRepositories _ -> + Pages.OrgRepositories _ _ _ -> a [ class "button" , class "-outline" @@ -195,7 +195,7 @@ viewUtil model = Pages.OrgSecrets _ org _ _ -> viewOrgTabs rm org model.page - Pages.OrgRepositories org -> + Pages.OrgRepositories org _ _ -> viewOrgTabs rm org model.page Pages.RepositoryBuilds org repo _ _ _ -> @@ -290,7 +290,7 @@ viewOrgTabs : RepoModel -> Org -> Page -> Html msg viewOrgTabs rm org currentPage = let tabs = - [ Tab "Repositories" currentPage (Pages.OrgRepositories org) False + [ Tab "Repositories" currentPage (Pages.OrgRepositories org Nothing Nothing) False , Tab "Builds" currentPage (Pages.OrgBuilds org rm.builds.maybePage rm.builds.maybePerPage rm.builds.maybeEvent) False , Tab "Secrets" currentPage (Pages.OrgSecrets "native" org Nothing Nothing) False ] diff --git a/src/elm/Pager.elm b/src/elm/Pager.elm index 85908292d..f6713a5e0 100644 --- a/src/elm/Pager.elm +++ b/src/elm/Pager.elm @@ -4,7 +4,7 @@ Use of this source code is governed by the LICENSE file in this repository. --} -module Pager exposing (defaultLabels, view) +module Pager exposing (defaultLabels, prevNextLabels, view) import Api.Pagination as Pagination import FeatherIcons @@ -28,6 +28,13 @@ defaultLabels = } +prevNextLabels : Labels +prevNextLabels = + { previousLabel = "prev" + , nextLabel = "next" + } + + {-| view : renders pager controls -} view : List WebLink -> Labels -> (Pagination.Page -> msg) -> Html msg diff --git a/src/elm/Pages.elm b/src/elm/Pages.elm index caade3f4d..876dec30e 100644 --- a/src/elm/Pages.elm +++ b/src/elm/Pages.elm @@ -15,7 +15,7 @@ import Vela exposing (Build, BuildNumber, Engine, Event, FocusFragment, Name, Or type Page = Overview | SourceRepositories - | OrgRepositories Org + | OrgRepositories Org (Maybe Pagination.Page) (Maybe Pagination.PerPage) | Hooks Org Repo (Maybe Pagination.Page) (Maybe Pagination.PerPage) | OrgSecrets Engine Org (Maybe Pagination.Page) (Maybe Pagination.PerPage) | RepoSecrets Engine Org Repo (Maybe Pagination.Page) (Maybe Pagination.PerPage) @@ -58,8 +58,8 @@ toRoute page = SourceRepositories -> Routes.SourceRepositories - OrgRepositories org -> - Routes.OrgRepositories org + OrgRepositories org maybePage maybePerPage -> + Routes.OrgRepositories org maybePage maybePerPage Hooks org repo maybePage maybePerPage -> Routes.Hooks org repo maybePage maybePerPage @@ -149,8 +149,8 @@ strip page = SourceRepositories -> SourceRepositories - OrgRepositories org -> - OrgRepositories org + OrgRepositories org _ _ -> + OrgRepositories org Nothing Nothing Hooks org repo _ _ -> Hooks org repo Nothing Nothing diff --git a/src/elm/Pages/Organization.elm b/src/elm/Pages/Organization.elm index af91fa7be..df59e0e15 100644 --- a/src/elm/Pages/Organization.elm +++ b/src/elm/Pages/Organization.elm @@ -7,7 +7,6 @@ Use of this source code is governed by the LICENSE file in this repository. module Pages.Organization exposing (..) import Errors exposing (viewResourceError) -import Favorites exposing (ToggleFavorite, starToggle) import Html exposing ( Html @@ -24,11 +23,11 @@ import Html ) import Html.Attributes exposing (class, href) import Pages.Build.View exposing (viewPreview) -import RemoteData exposing (RemoteData(..), WebData) +import RemoteData exposing (RemoteData(..)) import Routes import Time exposing (Posix, Zone) import Util exposing (largeLoader) -import Vela exposing (BuildsModel, Event, Favorites, Org, Repo, Repository) +import Vela exposing (BuildsModel, Event, Org, OrgReposModel, Repository) {-| view : takes org and renders build previews @@ -86,11 +85,11 @@ viewBuilds buildsModel now zone org maybeEvent = viewResourceError { resourceLabel = "builds for this org", testLabel = "builds" } -{-| viewOrgRepos : takes favorites, user search input and favorite action and renders favorites +{-| viewOrgRepos : renders repositories for the provided org -} -viewOrgRepos : Org -> WebData (List Repository) -> Html msg +viewOrgRepos : Org -> OrgReposModel -> Html msg viewOrgRepos org repos = - case repos of + case repos.orgRepos of Success r -> if List.length r == 0 then div [] @@ -108,21 +107,17 @@ viewOrgRepos org repos = else div [] (List.map (viewOrgRepo org) r) - _ -> - div [] - [ h1 [] [ text "No Repositories are enabled for this Organization!" ] - , p [] [ text "Enable repositories" ] - , a - [ class "button" - , class "-outline" - , Util.testAttribute "source-repos" - , Routes.href <| Routes.SourceRepositories - ] - [ text "Source Repositories" ] - ] + Loading -> + largeLoader + + NotAsked -> + largeLoader + + Failure _ -> + viewResourceError { resourceLabel = "repos for this org", testLabel = "repos" } -{-| viewOrgRepo : takes favorites and favorite action and renders single favorite +{-| viewOrgRepo : renders row of repos with action buttons -} viewOrgRepo : Org -> Repository -> Html msg viewOrgRepo org repo = diff --git a/src/elm/Routes.elm b/src/elm/Routes.elm index 503f36cc3..1d4bb2f7e 100644 --- a/src/elm/Routes.elm +++ b/src/elm/Routes.elm @@ -24,7 +24,7 @@ import Vela exposing (AuthParams, BuildNumber, Engine, Event, FocusFragment, Nam type Route = Overview | SourceRepositories - | OrgRepositories Org + | OrgRepositories Org (Maybe Pagination.Page) (Maybe Pagination.PerPage) | Hooks Org Repo (Maybe Pagination.Page) (Maybe Pagination.PerPage) | OrgSecrets Engine Org (Maybe Pagination.Page) (Maybe Pagination.PerPage) | RepoSecrets Engine Org Repo (Maybe Pagination.Page) (Maybe Pagination.PerPage) @@ -61,7 +61,7 @@ routes = oneOf [ map Overview top , map SourceRepositories (s "account" s "source-repos") - , map OrgRepositories string + , map OrgRepositories (string Query.int "page" Query.int "per_page") , map Login (s "account" s "login") , map Logout (s "account" s "logout") , map Settings (s "account" s "settings") @@ -121,8 +121,8 @@ routeToUrl route = SourceRepositories -> "/account/source-repos" - OrgRepositories org -> - "/" ++ org + OrgRepositories org maybePage maybePerPage -> + "/" ++ org ++ UB.toQuery (Pagination.toQueryParams maybePage maybePerPage) RepoSettings org repo -> "/" ++ org ++ "/" ++ repo ++ "/settings" diff --git a/src/elm/Vela.elm b/src/elm/Vela.elm index 8fd561504..3316fa61f 100644 --- a/src/elm/Vela.elm +++ b/src/elm/Vela.elm @@ -40,6 +40,7 @@ module Vela exposing , Logs , Name , Org + , OrgReposModel , PipelineConfig , PipelineModel , PipelineTemplates @@ -145,6 +146,9 @@ module Vela exposing , updateHooksPager , updateHooksPerPage , updateOrgRepo + , updateOrgReposPage + , updateOrgReposPager + , updateOrgReposPerPage , updateOrgRepositories , updateRepo , updateRepoCounter @@ -348,7 +352,7 @@ type alias RepoModel = { org : Org , name : Repo , repo : WebData Repository - , orgRepos : WebData (List Repository) + , orgRepos : OrgReposModel , hooks : HooksModel , builds : BuildsModel , deployments : DeploymentsModel @@ -357,6 +361,21 @@ type alias RepoModel = } +{-| OrgReposModel : model to contain repositories belonging to an org crucial for rendering the repositories tab on the org page +-} +type alias OrgReposModel = + { orgRepos : WebData (List Repository) + , pager : List WebLink + , maybePage : Maybe Pagination.Page + , maybePerPage : Maybe Pagination.PerPage + } + + +defaultOrgReposModel : OrgReposModel +defaultOrgReposModel = + OrgReposModel RemoteData.NotAsked [] Nothing Nothing + + {-| BuildModel : model to contain build information that is crucial for rendering a pipeline -} type alias BuildModel = @@ -390,7 +409,7 @@ defaultBuildModel = defaultRepoModel : RepoModel defaultRepoModel = - RepoModel "" "" NotAsked NotAsked defaultHooks defaultBuilds defaultDeployments defaultBuildModel False + RepoModel "" "" NotAsked defaultOrgReposModel defaultHooks defaultBuilds defaultDeployments defaultBuildModel False defaultStepsModel : StepsModel @@ -420,7 +439,11 @@ updateRepo update rm = updateOrgRepositories : WebData (List Repository) -> RepoModel -> RepoModel updateOrgRepositories update rm = - { rm | orgRepos = update } + let + orm = + rm.orgRepos + in + { rm | orgRepos = { orm | orgRepos = update } } updateRepoTimeout : Maybe Int -> RepoModel -> RepoModel @@ -579,6 +602,33 @@ updateDeploymentsPerPage maybePerPage rm = { rm | deployments = { dm | maybePerPage = maybePerPage } } +updateOrgReposPage : Maybe Pagination.Page -> RepoModel -> RepoModel +updateOrgReposPage maybePage rm = + let + orm = + rm.orgRepos + in + { rm | orgRepos = { orm | maybePage = maybePage } } + + +updateOrgReposPerPage : Maybe Pagination.PerPage -> RepoModel -> RepoModel +updateOrgReposPerPage maybePerPage rm = + let + orm = + rm.orgRepos + in + { rm | orgRepos = { orm | maybePerPage = maybePerPage } } + + +updateOrgReposPager : List WebLink -> RepoModel -> RepoModel +updateOrgReposPager update rm = + let + orm = + rm.orgRepos + in + { rm | orgRepos = { orm | pager = update } } + + updateBuildsPage : Maybe Pagination.Page -> RepoModel -> RepoModel updateBuildsPage maybePage rm = let diff --git a/src/scss/_main.scss b/src/scss/_main.scss index 94d18174e..a192d9ec7 100644 --- a/src/scss/_main.scss +++ b/src/scss/_main.scss @@ -249,7 +249,7 @@ nav { display: flex; align-items: center; justify-content: space-between; - margin: 0.5rem 0 0 0; + margin: 0.5rem 0; padding: 1rem; background-color: var(--color-bg-dark); diff --git a/tests/RoutesTest.elm b/tests/RoutesTest.elm index 78bdcc964..5c31daedf 100644 --- a/tests/RoutesTest.elm +++ b/tests/RoutesTest.elm @@ -26,7 +26,7 @@ testMatch : Test testMatch = describe "route gets matched as intended for given url" [ testUrl "/account/login" Login - , testUrl "/asdf" (OrgRepositories "asdf") + , testUrl "/asdf" (OrgRepositories "asdf" Nothing Nothing) , testUrl "/" Overview ]