diff --git a/src/__fixtures__/libraries.js b/src/__fixtures__/libraries.js
index ecc4635d..32db8e49 100644
--- a/src/__fixtures__/libraries.js
+++ b/src/__fixtures__/libraries.js
@@ -1,33 +1,24 @@
-import { config } from '~/src/config/config.js'
-
-const githubOrg = config.get('githubOrg')
-
-// TODO update fixture once we have libraries
// Response from portalBackendApi/libraries
const librariesFixture = {
message: 'success',
- libraries: [
- {
- id: 'cdp-node-frontend-library',
- description: 'Core delivery platform npm library',
- primaryLanguage: 'JavaScript',
- url: `https://github.com/${githubOrg}/cdp-npm-library`,
- isArchived: false,
- isLibrary: true,
- isPrivate: true,
- createdAt: '2023-04-26T15:27:09+00:00',
- teams: ['cdp-platform']
- },
+ repositories: [
{
- id: 'cdp-node-auth-library',
- description: 'Core delivery platform auth library',
+ id: 'hapi-tracing',
+ description: 'Git repository for hapi-tracing',
primaryLanguage: 'JavaScript',
- url: `https://github.com/${githubOrg}/cdp-auth-library`,
+ url: 'https://github.com/DEFRA/hapi-tracing',
isArchived: false,
- isLibrary: true,
- isPrivate: true,
- createdAt: '2022-04-26T15:27:10+00:00',
- teams: ['cdp-platform']
+ isTemplate: false,
+ isPrivate: false,
+ createdAt: '2024-12-09T13:08:51+00:00',
+ teams: [
+ {
+ github: 'cdp-platform',
+ teamId: 'aabe63e7-87ef-4beb-a596-c810631fc474',
+ name: 'Platform'
+ }
+ ],
+ topics: ['cdp', 'repository', 'library']
}
]
}
diff --git a/src/__fixtures__/library.js b/src/__fixtures__/library.js
index 558b11ff..e4fce731 100644
--- a/src/__fixtures__/library.js
+++ b/src/__fixtures__/library.js
@@ -1,21 +1,23 @@
-import { config } from '~/src/config/config.js'
-
-const githubOrg = config.get('githubOrg')
-
-// TODO update fixture once we have libraries
-// Response from portalBackendApi/libraries/cdp-node-frontend-library
+// Response from portalBackendApi/libraries/hapi-tracing
const libraryFixture = {
message: 'success',
- library: {
- id: 'cdp-node-frontend-library',
- description: 'Core delivery platform npm library',
+ repository: {
+ id: 'hapi-tracing',
+ description: 'Git repository for hapi-tracing',
primaryLanguage: 'JavaScript',
- url: `https://github.com/${githubOrg}/cdp-npm-library`,
+ url: 'https://github.com/DEFRA/hapi-tracing',
isArchived: false,
- isLibrary: true,
- isPrivate: true,
- createdAt: '2023-04-26T15:27:09+00:00',
- teams: ['cdp-platform']
+ isTemplate: false,
+ isPrivate: false,
+ createdAt: '2024-12-09T13:08:51+00:00',
+ teams: [
+ {
+ github: 'cdp-platform',
+ teamId: 'aabe63e7-87ef-4beb-a596-c810631fc474',
+ name: 'Platform'
+ }
+ ],
+ topics: ['cdp', 'repository', 'library']
}
}
diff --git a/src/__fixtures__/template.js b/src/__fixtures__/template.js
index 1b215dd4..a2025de0 100644
--- a/src/__fixtures__/template.js
+++ b/src/__fixtures__/template.js
@@ -1,26 +1,24 @@
-import { config } from '~/src/config/config.js'
-
-const githubOrg = config.get('githubOrg')
-
-// Response from portalBackendApi/templates/cdp-portal-frontend
+// Response from portalBackendApi/templates/cdp-dotnet-backend-template
const templateFixture = {
message: 'success',
- template: {
- id: 'cdp-portal-frontend',
- description: 'The Core Delivery Platform Portal.',
- primaryLanguage: 'JavaScript',
- url: `https://github.com/${githubOrg}/cdp-portal-frontend`,
+ repository: {
+ id: 'cdp-dotnet-backend-template',
+ description:
+ 'C# ASP.NET Minimial API template with MongoDB, FluentValidation, Swagger and Serilog logging',
+ primaryLanguage: 'C#',
+ url: 'https://github.com/DEFRA/cdp-dotnet-backend-template',
isArchived: false,
- isTemplate: false,
- isPrivate: true,
- createdAt: '2023-04-12T17:16:48+00:00',
+ isTemplate: true,
+ isPrivate: false,
+ createdAt: '2023-08-24T07:08:56+00:00',
teams: [
{
github: 'cdp-platform',
teamId: 'aabe63e7-87ef-4beb-a596-c810631fc474',
name: 'Platform'
}
- ]
+ ],
+ topics: ['backend', 'cdp', 'dotnet', 'template']
}
}
diff --git a/src/__fixtures__/templates.js b/src/__fixtures__/templates.js
index b082ea49..b93479bf 100644
--- a/src/__fixtures__/templates.js
+++ b/src/__fixtures__/templates.js
@@ -1,16 +1,49 @@
-import { config } from '~/src/config/config.js'
-
-const githubOrg = config.get('githubOrg')
-
// Response from portalBackendApi/templates
const templatesFixture = {
message: 'success',
- templates: [
+ repositories: [
+ {
+ id: 'cdp-dotnet-backend-template',
+ description:
+ 'C# ASP.NET Minimial API template with MongoDB, FluentValidation, Swagger and Serilog logging',
+ primaryLanguage: 'C#',
+ url: 'https://github.com/DEFRA/cdp-dotnet-backend-template',
+ isArchived: false,
+ isTemplate: true,
+ isPrivate: false,
+ createdAt: '2023-08-24T07:08:56+00:00',
+ teams: [
+ {
+ github: 'cdp-platform',
+ teamId: 'aabe63e7-87ef-4beb-a596-c810631fc474',
+ name: 'Platform'
+ }
+ ],
+ topics: ['backend', 'cdp', 'dotnet', 'template']
+ },
+ {
+ id: 'cdp-node-backend-template',
+ description: 'Core delivery platform Node.js Backend Template',
+ primaryLanguage: 'JavaScript',
+ url: 'https://github.com/DEFRA/cdp-node-backend-template',
+ isArchived: false,
+ isTemplate: true,
+ isPrivate: false,
+ createdAt: '2023-06-20T12:10:50+00:00',
+ teams: [
+ {
+ github: 'cdp-platform',
+ teamId: 'aabe63e7-87ef-4beb-a596-c810631fc474',
+ name: 'Platform'
+ }
+ ],
+ topics: ['cdp', 'template', 'backend', 'node']
+ },
{
id: 'cdp-node-frontend-template',
description: 'Core delivery platform Node.js Frontend Template',
primaryLanguage: 'JavaScript',
- url: `https://github.com/${githubOrg}/cdp-node-frontend-template`,
+ url: 'https://github.com/DEFRA/cdp-node-frontend-template',
isArchived: false,
isTemplate: true,
isPrivate: false,
@@ -21,42 +54,44 @@ const templatesFixture = {
teamId: 'aabe63e7-87ef-4beb-a596-c810631fc474',
name: 'Platform'
}
- ]
+ ],
+ topics: ['cdp', 'frontend', 'node', 'template']
},
{
- id: 'cdp-node-backend-template',
- description: 'Core delivery platform Node.js Backend Template',
+ id: 'cdp-node-journey-test-suite-template',
+ description: 'Git repository for cdp-node-env-test-suite-template',
primaryLanguage: 'JavaScript',
- url: `https://github.com/${githubOrg}/cdp-node-backend-template`,
+ url: 'https://github.com/DEFRA/cdp-node-journey-test-suite-template',
isArchived: false,
isTemplate: true,
isPrivate: false,
- createdAt: '2023-06-20T12:10:50+00:00',
+ createdAt: '2024-01-24T14:49:52+00:00',
teams: [
{
github: 'cdp-platform',
teamId: 'aabe63e7-87ef-4beb-a596-c810631fc474',
name: 'Platform'
}
- ]
+ ],
+ topics: ['cdp', 'template', 'test-suite', 'journey']
},
{
- id: 'cdp-dotnet-backend-template',
- description:
- 'C# ASP.NET Minimial API template with MongoDB, FluentValidation, Swagger and Serilog logging',
- primaryLanguage: 'C#',
- url: `https://github.com/${githubOrg}/cdp-dotnet-backend-template`,
+ id: 'cdp-perf-test-suite-template',
+ description: 'Git repository for cdp-perf-test-suite-template',
+ primaryLanguage: 'Shell',
+ url: 'https://github.com/DEFRA/cdp-perf-test-suite-template',
isArchived: false,
isTemplate: true,
isPrivate: false,
- createdAt: '2023-08-24T07:08:56+00:00',
+ createdAt: '2024-04-17T12:10:51+00:00',
teams: [
{
github: 'cdp-platform',
teamId: 'aabe63e7-87ef-4beb-a596-c810631fc474',
name: 'Platform'
}
- ]
+ ],
+ topics: ['cdp', 'repository', 'template', 'test-suite', 'performance']
}
]
}
diff --git a/src/server/admin/features/controllers/features-list.js b/src/server/admin/features/controllers/features-list.js
index f6d3ffbf..8fefaa35 100644
--- a/src/server/admin/features/controllers/features-list.js
+++ b/src/server/admin/features/controllers/features-list.js
@@ -4,10 +4,20 @@ import { transformFeaturesToEntityRows } from '~/src/server/admin/features/trans
const listFeaturesController = {
handler: async (request, h) => {
const featureToggles = await findAllFeatureToggles(request)
- const entityRows = transformFeaturesToEntityRows(featureToggles)
+ const rows = transformFeaturesToEntityRows(featureToggles)
+
return h.view('admin/features/views/features-list', {
pageTitle: 'Admin - Feature Toggles',
- entityRows
+ tableData: {
+ headers: [
+ { id: 'feature', text: 'Feature', width: '15' },
+ { id: 'status', text: 'Status', width: '10' },
+ { id: 'activated', text: 'Activated', width: '10' },
+ { id: 'actions', text: 'Actions', width: '20' }
+ ],
+ rows,
+ noResult: 'No feature flags found'
+ }
})
}
}
diff --git a/src/server/admin/features/transformers/transform-feature-to-entity-row.js b/src/server/admin/features/transformers/transform-feature-to-entity-row.js
index a4ec9c7f..1c0c0cef 100644
--- a/src/server/admin/features/transformers/transform-feature-to-entity-row.js
+++ b/src/server/admin/features/transformers/transform-feature-to-entity-row.js
@@ -8,41 +8,58 @@ function transformFeaturesToEntityRows(features) {
}
function transformFeatureToEntityRow(feature) {
- return [
- {
- kind: 'text',
- value: feature.title
- },
- {
- kind: 'text',
- value: feature.enabled ? 'Active' : 'Not active'
- },
- ...(feature.enabled
- ? [
- {
- kind: 'date',
- value: feature.created
- },
- {
- kind: 'button',
- value: 'Deactivate',
- url: feature.urlPrefix + '/delete',
- classes: 'app-button--small app-button--destructive'
- }
- ]
- : [
- {
- kind: 'text',
- value: noValue
- },
- {
- kind: 'button',
- value: 'Activate',
- url: feature.urlPrefix,
- classes: 'app-button--small'
- }
- ])
- ]
+ return {
+ cells: [
+ {
+ headers: 'feature',
+ entity: { kind: 'text', value: feature.title }
+ },
+ {
+ headers: 'status',
+ entity: {
+ kind: 'text',
+ value: feature.enabled ? 'Active' : 'Not active'
+ }
+ },
+ ...(feature.enabled
+ ? [
+ {
+ headers: 'activated',
+ entity: {
+ kind: 'date',
+ value: feature.created
+ }
+ },
+ {
+ headers: 'actions',
+ entity: {
+ kind: 'button',
+ value: 'Deactivate',
+ url: feature.urlPrefix + '/delete',
+ classes: 'app-button--small app-button--destructive'
+ }
+ }
+ ]
+ : [
+ {
+ headers: 'activated',
+ entity: {
+ kind: 'text',
+ value: noValue
+ }
+ },
+ {
+ headers: 'actions',
+ entity: {
+ kind: 'button',
+ value: 'Activate',
+ url: feature.urlPrefix,
+ classes: 'app-button--small'
+ }
+ }
+ ])
+ ]
+ }
}
export { transformFeaturesToEntityRows, transformFeatureToEntityRow }
diff --git a/src/server/admin/features/transformers/transform-feature-to-entity-row.test.js b/src/server/admin/features/transformers/transform-feature-to-entity-row.test.js
index debf2d0d..2a2b4455 100644
--- a/src/server/admin/features/transformers/transform-feature-to-entity-row.test.js
+++ b/src/server/admin/features/transformers/transform-feature-to-entity-row.test.js
@@ -2,7 +2,6 @@ import {
transformFeaturesToEntityRows,
transformFeatureToEntityRow
} from '~/src/server/admin/features/transformers/transform-feature-to-entity-row.js'
-import { noValue } from '~/src/server/common/constants/no-value.js'
describe('transformFeatureToEntityRow', () => {
test('Should return entity row for active feature', () => {
@@ -15,27 +14,40 @@ describe('transformFeatureToEntityRow', () => {
const result = transformFeatureToEntityRow(feature)
- expect(result).toHaveLength(4)
- expect(result).toEqual([
- {
- kind: 'text',
- value: 'Feature 1'
- },
- {
- kind: 'text',
- value: 'Active'
- },
- {
- kind: 'date',
- value: '2021-01-01'
- },
- {
- kind: 'button',
- value: 'Deactivate',
- url: '/some-url/delete',
- classes: 'app-button--small app-button--destructive'
- }
- ])
+ expect(result).toEqual({
+ cells: [
+ {
+ entity: {
+ kind: 'text',
+ value: 'Feature 1'
+ },
+ headers: 'feature'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'Active'
+ },
+ headers: 'status'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2021-01-01'
+ },
+ headers: 'activated'
+ },
+ {
+ entity: {
+ classes: 'app-button--small app-button--destructive',
+ kind: 'button',
+ url: '/some-url/delete',
+ value: 'Deactivate'
+ },
+ headers: 'actions'
+ }
+ ]
+ })
})
test('Should return entity row for inactive feature', () => {
@@ -47,27 +59,40 @@ describe('transformFeatureToEntityRow', () => {
const result = transformFeatureToEntityRow(feature)
- expect(result).toHaveLength(4)
- expect(result).toEqual([
- {
- kind: 'text',
- value: 'Feature 2'
- },
- {
- kind: 'text',
- value: 'Not active'
- },
- {
- kind: 'text',
- value: noValue
- },
- {
- kind: 'button',
- value: 'Activate',
- url: '/some-url',
- classes: 'app-button--small'
- }
- ])
+ expect(result).toEqual({
+ cells: [
+ {
+ entity: {
+ kind: 'text',
+ value: 'Feature 2'
+ },
+ headers: 'feature'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'Not active'
+ },
+ headers: 'status'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: '- - -'
+ },
+ headers: 'activated'
+ },
+ {
+ entity: {
+ classes: 'app-button--small',
+ kind: 'button',
+ url: '/some-url',
+ value: 'Activate'
+ },
+ headers: 'actions'
+ }
+ ]
+ })
})
})
@@ -89,12 +114,76 @@ describe('transformFeaturesToEntityRows', () => {
const result = transformFeaturesToEntityRows(features)
- expect(result).toHaveLength(2)
-
- expect(result[0][0].value).toBe('Feature 1')
- expect(result[0][1].value).toBe('Active')
- expect(result[1][0].value).toBe('Feature 2')
- expect(result[1][1].value).toBe('Not active')
+ expect(result).toEqual([
+ {
+ cells: [
+ {
+ entity: {
+ kind: 'text',
+ value: 'Feature 1'
+ },
+ headers: 'feature'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'Active'
+ },
+ headers: 'status'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2021-01-01'
+ },
+ headers: 'activated'
+ },
+ {
+ entity: {
+ classes: 'app-button--small app-button--destructive',
+ kind: 'button',
+ url: '/some-url/delete',
+ value: 'Deactivate'
+ },
+ headers: 'actions'
+ }
+ ]
+ },
+ {
+ cells: [
+ {
+ entity: {
+ kind: 'text',
+ value: 'Feature 2'
+ },
+ headers: 'feature'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'Not active'
+ },
+ headers: 'status'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: '- - -'
+ },
+ headers: 'activated'
+ },
+ {
+ entity: {
+ classes: 'app-button--small',
+ kind: 'button',
+ url: '/some-url',
+ value: 'Activate'
+ },
+ headers: 'actions'
+ }
+ ]
+ }
+ ])
})
test('Should return empty array when no features', () => {
diff --git a/src/server/admin/features/views/features-list.njk b/src/server/admin/features/views/features-list.njk
index 24fd14e1..c0d16573 100644
--- a/src/server/admin/features/views/features-list.njk
+++ b/src/server/admin/features/views/features-list.njk
@@ -4,19 +4,11 @@
{% call appSplitPane() %}
{{ appPageHeading({
- text: "Feature Toggles"
+ text: "Feature Toggles",
+ intro: "Portal wide feature toggles, to toggle features on/off"
}) }}
- {{ appEntityList({
- headings: [
- { text: "Feature", size: "large" },
- { text: "Status", size: "medium" },
- { text: "Activated", size: "medium" },
- { text: "Actions", size: "medium" }
- ],
- entityRows: entityRows,
- noResult: noResult
- }) }}
+ {{ appEntityTable(tableData) }}
{% endcall %}
{% endblock %}
diff --git a/src/server/admin/permissions/controllers/permissions-list.js b/src/server/admin/permissions/controllers/permissions-list.js
index b8a15acd..24e965b8 100644
--- a/src/server/admin/permissions/controllers/permissions-list.js
+++ b/src/server/admin/permissions/controllers/permissions-list.js
@@ -3,22 +3,36 @@ import { fetchScopes } from '~/src/server/admin/permissions/helpers/fetchers.js'
const permissionsListController = {
handler: async (request, h) => {
const { scopes } = await fetchScopes(request)
- const entityRows = scopes.map((scope) => [
- {
- kind: 'link',
- url: `/admin/permissions/${scope.scopeId}`,
- value: scope.value
- },
- {
- kind: 'text',
- value: scope.description
- }
- ])
+ const rows = scopes.map((scope) => ({
+ cells: [
+ {
+ headers: 'value',
+ entity: {
+ kind: 'link',
+ url: `/admin/permissions/${scope.scopeId}`,
+ value: scope.value
+ }
+ },
+ {
+ headers: 'description',
+ entity: {
+ kind: 'text',
+ value: scope.description
+ }
+ }
+ ]
+ }))
return h.view('admin/permissions/views/permissions-list', {
pageTitle: 'Permissions',
- heading: 'Permissions',
- entityRows
+ tableData: {
+ headers: [
+ { id: 'value', text: 'Value', width: '20' },
+ { id: 'description', text: 'Description', width: '80' }
+ ],
+ rows,
+ noResult: 'No permissions found'
+ }
})
}
}
diff --git a/src/server/admin/permissions/views/permissions-list.njk b/src/server/admin/permissions/views/permissions-list.njk
index 35465658..00683aa7 100644
--- a/src/server/admin/permissions/views/permissions-list.njk
+++ b/src/server/admin/permissions/views/permissions-list.njk
@@ -5,22 +5,15 @@
{{ appPageHeading({
text: "Permissions",
+ intro: "Portal wide permissions details, create, view and assign permissions to users and teams",
cta: {
text: "Create new permission",
href: routeLookup('admin/permission/create')
}
}) }}
- {{ appEntityList({
- headings: [
- { text: "Value", size: "medium" },
- { text: "Description", size: "gargantuan" }
- ],
- entityRows: entityRows,
- noResult: "Currently there are no permissions available"
- }) }}
+ {{ appEntityTable(tableData) }}
{% endcall %}
-
{% endblock %}
diff --git a/src/server/admin/teams/controllers/teams-list.js b/src/server/admin/teams/controllers/teams-list.js
index 833ec2ef..e41a35d7 100644
--- a/src/server/admin/teams/controllers/teams-list.js
+++ b/src/server/admin/teams/controllers/teams-list.js
@@ -4,12 +4,24 @@ import { transformTeamToEntityRow } from '~/src/server/admin/teams/transformers/
const teamsListController = {
handler: async (request, h) => {
const { teams } = await fetchCdpTeams()
- const entityRows = teams?.map(transformTeamToEntityRow)
+ const rows = teams?.map(transformTeamToEntityRow)
return h.view('admin/teams/views/teams-list', {
pageTitle: 'Teams',
- entityRows,
- noResult: 'Currently there are no teams'
+ tableData: {
+ headers: [
+ { id: 'name', text: 'Name', width: '15' },
+ { id: 'description', text: 'Description', width: '15' },
+ { id: 'github-team', text: 'GitHub team', width: '15' },
+ { id: 'service-codes', text: 'Service Codes', width: '5' },
+ { id: 'alert-emails', text: 'Alert Emails', width: '20' },
+ { id: 'members', text: 'Members', width: '10' },
+ { id: 'last-updated', text: 'Last Updated', width: '10' },
+ { id: 'created', text: 'Created', width: '10' }
+ ],
+ rows,
+ noResult: 'No teams found'
+ }
})
}
}
diff --git a/src/server/admin/teams/transformers/transform-team-to-entity-row.js b/src/server/admin/teams/transformers/transform-team-to-entity-row.js
index c090789e..c2bb0d38 100644
--- a/src/server/admin/teams/transformers/transform-team-to-entity-row.js
+++ b/src/server/admin/teams/transformers/transform-team-to-entity-row.js
@@ -3,35 +3,63 @@ import { config } from '~/src/config/config.js'
function transformTeamToEntityRow(team) {
const githubOrg = config.get('githubOrg')
- return [
- {
- kind: 'link',
- value: team.name,
- url: `/admin/teams/${team.teamId}`
- },
- {
- kind: 'text',
- value: team.description
- },
- {
- kind: 'link',
- value: team.github ? `@${team.github}` : null,
- url: `https://github.com/orgs/${githubOrg}/teams/${team.github}`,
- newWindow: true
- },
- {
- kind: 'text',
- value: team.serviceCodes
- },
- {
- kind: 'html',
- value: team.alertEmailAddresses?.join('
')
- },
- {
- kind: 'text',
- value: team.users.length
- }
- ]
+ return {
+ cells: [
+ {
+ headers: 'name',
+ entity: {
+ kind: 'link',
+ value: team.name,
+ url: `/admin/teams/${team.teamId}`
+ }
+ },
+ {
+ headers: 'description',
+ entity: {
+ kind: 'text',
+ value: team.description
+ }
+ },
+ {
+ headers: 'github-team',
+ entity: {
+ kind: 'link',
+ value: team.github ? `@${team.github}` : null,
+ url: `https://github.com/orgs/${githubOrg}/teams/${team.github}`,
+ newWindow: true
+ }
+ },
+ {
+ headers: 'service-codes',
+ entity: {
+ kind: 'text',
+ value: team.serviceCodes
+ }
+ },
+ {
+ headers: 'alert-emails',
+ entity: {
+ kind: 'html',
+ value: team.alertEmailAddresses?.join('
')
+ }
+ },
+ {
+ headers: 'members',
+ entity: {
+ kind: 'text',
+ value: team.users.length
+ }
+ },
+ {
+ headers: 'last-updated',
+ entity: { kind: 'date', value: team.updatedAt }
+ },
+ {
+ headers: 'created',
+ entity: { kind: 'date', value: team.createdAt }
+ }
+ ]
+ }
}
export { transformTeamToEntityRow }
diff --git a/src/server/admin/teams/transformers/transform-team-to-entity-row.test.js b/src/server/admin/teams/transformers/transform-team-to-entity-row.test.js
index 0c0d82c2..abe4e66d 100644
--- a/src/server/admin/teams/transformers/transform-team-to-entity-row.test.js
+++ b/src/server/admin/teams/transformers/transform-team-to-entity-row.test.js
@@ -1,39 +1,70 @@
-import { config } from '~/src/config/config.js'
import { cdpTeamFixture } from '~/src/__fixtures__/admin/cdp-team.js'
import { transformTeamToEntityRow } from '~/src/server/admin/teams/transformers/transform-team-to-entity-row.js'
-const githubOrg = config.get('githubOrg')
-
describe('#transformCdpTeamToEntityRow', () => {
test('Should provide expected team row transformation', () => {
- expect(transformTeamToEntityRow(cdpTeamFixture.team)).toEqual([
- {
- kind: 'link',
- url: '/admin/teams/aabe63e7-87ef-4beb-a596-c810631fc474',
- value: 'Platform'
- },
- {
- kind: 'text',
- value: 'The team that runs the platform'
- },
- {
- kind: 'link',
- newWindow: true,
- url: `https://github.com/orgs/${githubOrg}/teams/cdp-platform`,
- value: '@cdp-platform'
- },
- {
- kind: 'text',
- value: ['CDP']
- },
- {
- kind: 'html',
- value: 'alerts@cdp.com'
- },
- {
- kind: 'text',
- value: 2
- }
- ])
+ expect(transformTeamToEntityRow(cdpTeamFixture.team)).toEqual({
+ cells: [
+ {
+ entity: {
+ kind: 'link',
+ url: '/admin/teams/aabe63e7-87ef-4beb-a596-c810631fc474',
+ value: 'Platform'
+ },
+ headers: 'name'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'The team that runs the platform'
+ },
+ headers: 'description'
+ },
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: 'https://github.com/orgs/DEFRA/teams/cdp-platform',
+ value: '@cdp-platform'
+ },
+ headers: 'github-team'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: ['CDP']
+ },
+ headers: 'service-codes'
+ },
+ {
+ entity: {
+ kind: 'html',
+ value: 'alerts@cdp.com'
+ },
+ headers: 'alert-emails'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 2
+ },
+ headers: 'members'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2023-10-03T11:11:31.085Z'
+ },
+ headers: 'last-updated'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2023-09-28T12:52:14.673Z'
+ },
+ headers: 'created'
+ }
+ ]
+ })
})
})
diff --git a/src/server/admin/teams/views/teams-list.njk b/src/server/admin/teams/views/teams-list.njk
index a56c7390..4f6deeb9 100644
--- a/src/server/admin/teams/views/teams-list.njk
+++ b/src/server/admin/teams/views/teams-list.njk
@@ -5,26 +5,15 @@
{{ appPageHeading({
text: "Teams",
+ intro: "Portal teams details, create, edit, view and add/remove users or permissions to teams",
cta: {
text: "Create new team",
href: routeLookup('admin/teams/create')
}
}) }}
- {{ appEntityList({
- headings: [
- { text: "Name", size: "medium" },
- { text: "Description", size: "massive" },
- { text: "GitHub team", size: "medium" },
- { text: "Service Codes", size: "small" },
- { text: "Alert Emails", size: "large" },
- { text: "Members", size: "small" }
- ],
- entityRows: entityRows,
- noResult: noResult
- }) }}
+ {{ appEntityTable(tableData) }}
{% endcall %}
-
{% endblock %}
diff --git a/src/server/admin/users/controllers/users-list.js b/src/server/admin/users/controllers/users-list.js
index 5c7a02cc..19ee21dd 100644
--- a/src/server/admin/users/controllers/users-list.js
+++ b/src/server/admin/users/controllers/users-list.js
@@ -4,13 +4,21 @@ import { transformUserToEntityRow } from '~/src/server/admin/users/transformers/
const usersListController = {
handler: async (request, h) => {
const { users } = await fetchCdpUsers()
-
- const entityRows = users?.map(transformUserToEntityRow)
+ const rows = users?.map(transformUserToEntityRow)
return h.view('admin/users/views/users-list', {
pageTitle: 'Users',
- entityRows,
- noResult: 'Currently there are no users'
+ tableData: {
+ headers: [
+ { id: 'name', text: 'Name', width: '15' },
+ { id: 'email', text: 'Email', width: '15' },
+ { id: 'github-user', text: 'GitHub user', width: '15' },
+ { id: 'last-updated', text: 'Last Updated', width: '10' },
+ { id: 'created', text: 'Created', width: '10' }
+ ],
+ rows,
+ noResult: 'No users found'
+ }
})
}
}
diff --git a/src/server/admin/users/transformers/transform-user-to-entity-row.js b/src/server/admin/users/transformers/transform-user-to-entity-row.js
index 84983b1e..81e5bb91 100644
--- a/src/server/admin/users/transformers/transform-user-to-entity-row.js
+++ b/src/server/admin/users/transformers/transform-user-to-entity-row.js
@@ -3,32 +3,43 @@ import { config } from '~/src/config/config.js'
function transformUserToEntityRow(user) {
const githubOrg = config.get('githubOrg')
- return [
- {
- kind: 'link',
- value: user.name ? user.name : null,
- url: `/admin/users/${user.userId}`
- },
- {
- kind: 'link',
- value: user.email,
- url: `mailto:${user.email}`
- },
- {
- kind: 'link',
- value: user.github ? `@${user.github}` : null,
- url: `https://github.com/orgs/${githubOrg}/people/${user.github}`,
- newWindow: true
- },
- {
- kind: 'text',
- value: user.defraAwsId
- },
- {
- kind: 'text',
- value: user.defraVpnId
- }
- ]
+ return {
+ cells: [
+ {
+ headers: 'name',
+ entity: {
+ kind: 'link',
+ value: user.name ? user.name : null,
+ url: `/admin/users/${user.userId}`
+ }
+ },
+ {
+ headers: 'email',
+ entity: {
+ kind: 'link',
+ value: user.email,
+ url: `mailto:${user.email}`
+ }
+ },
+ {
+ headers: 'github-user',
+ entity: {
+ kind: 'link',
+ value: user.github ? `@${user.github}` : null,
+ url: `https://github.com/orgs/${githubOrg}/people/${user.github}`,
+ newWindow: true
+ }
+ },
+ {
+ headers: 'last-updated',
+ entity: { kind: 'date', value: user.updatedAt }
+ },
+ {
+ headers: 'created',
+ entity: { kind: 'date', value: user.createdAt }
+ }
+ ]
+ }
}
export { transformUserToEntityRow }
diff --git a/src/server/admin/users/transformers/transform-user-to-entity-row.test.js b/src/server/admin/users/transformers/transform-user-to-entity-row.test.js
index 38fab12e..a1d7eeb4 100644
--- a/src/server/admin/users/transformers/transform-user-to-entity-row.test.js
+++ b/src/server/admin/users/transformers/transform-user-to-entity-row.test.js
@@ -1,36 +1,50 @@
-import { config } from '~/src/config/config.js'
import { cdpUserFixture } from '~/src/__fixtures__/admin/cdp-user.js'
import { transformUserToEntityRow } from '~/src/server/admin/users/transformers/transform-user-to-entity-row.js'
-const githubOrg = config.get('githubOrg')
-
describe('#transformUserToEntityRow', () => {
test('Should provide expected user entity row transformation', () => {
- expect(transformUserToEntityRow(cdpUserFixture.user)).toEqual([
- {
- kind: 'link',
- url: '/admin/users/1398fa86-98a2-4ee8-84bb-2468cc71d0ec',
- value: 'B. A. Baracus'
- },
- {
- kind: 'link',
- url: 'mailto:B.A.Baracus@defradev.onmicrosoft.com',
- value: 'B.A.Baracus@defradev.onmicrosoft.com'
- },
- {
- kind: 'link',
- newWindow: true,
- url: `https://github.com/orgs/${githubOrg}/people/BABaracus`,
- value: '@BABaracus'
- },
- {
- kind: 'text',
- value: 'FGHyu-232342-234234'
- },
- {
- kind: 'text',
- value: '345345-345345'
- }
- ])
+ expect(transformUserToEntityRow(cdpUserFixture.user)).toEqual({
+ cells: [
+ {
+ entity: {
+ kind: 'link',
+ url: '/admin/users/1398fa86-98a2-4ee8-84bb-2468cc71d0ec',
+ value: 'B. A. Baracus'
+ },
+ headers: 'name'
+ },
+ {
+ entity: {
+ kind: 'link',
+ url: 'mailto:B.A.Baracus@defradev.onmicrosoft.com',
+ value: 'B.A.Baracus@defradev.onmicrosoft.com'
+ },
+ headers: 'email'
+ },
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: 'https://github.com/orgs/DEFRA/people/BABaracus',
+ value: '@BABaracus'
+ },
+ headers: 'github-user'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2023-08-24T15:31:52.259Z'
+ },
+ headers: 'last-updated'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2023-08-23T16:17:57.883Z'
+ },
+ headers: 'created'
+ }
+ ]
+ })
})
})
diff --git a/src/server/admin/users/views/users-list.njk b/src/server/admin/users/views/users-list.njk
index 47f20f13..d02a2d84 100644
--- a/src/server/admin/users/views/users-list.njk
+++ b/src/server/admin/users/views/users-list.njk
@@ -1,31 +1,19 @@
{% extends "layouts/page.njk" %}
{% block content %}
-
{% call appSplitPane() %}
{{ appPageHeading({
text: "Users",
+ intro: "Portal users details, create, edit, view or delete users",
cta: {
text: "Create new user",
href: routeLookup('admin/users/create')
}
}) }}
- {{ appEntityList({
- headings: [
- { text: "Name", size: "large" },
- { text: "Email", size: "massive" },
- { text: "GitHub user", size: "medium" },
- { text: "Defra AWS ID", size: "medium" },
- { text: "Defra VPN ID", size: "medium" }
- ],
- entityRows: entityRows,
- noResult: noResult
- }) }}
-
+ {{ appEntityTable(tableData) }}
{% endcall %}
-
{% endblock %}
diff --git a/src/server/common/components/entity-table/_entity-table.scss b/src/server/common/components/entity-table/_entity-table.scss
index 10badf32..73d2567b 100644
--- a/src/server/common/components/entity-table/_entity-table.scss
+++ b/src/server/common/components/entity-table/_entity-table.scss
@@ -10,7 +10,6 @@
border-spacing: 0;
padding: 0;
width: 100%;
- margin-top: -8px;
text-align: left;
empty-cells: show;
@@ -53,6 +52,11 @@
}
}
+.app-entity-table__cell--centered {
+ text-align: center;
+ vertical-align: middle;
+}
+
.app-entity-table__cell--slim {
padding: 0;
}
@@ -61,6 +65,7 @@
color: govuk-colour("dark-grey");
}
-.app-entity-table__cell--20-fixed {
+.app-entity-table__cell--owned {
width: 20px;
+ padding: 0 govuk-spacing(2);
}
diff --git a/src/server/common/components/entity-table/template.njk b/src/server/common/components/entity-table/template.njk
index 50e4cfcf..0104141a 100644
--- a/src/server/common/components/entity-table/template.njk
+++ b/src/server/common/components/entity-table/template.njk
@@ -8,10 +8,15 @@
{% for header in params.headers %}
{% endfor %}
@@ -21,8 +26,12 @@
{% for cell in row.cells %}
- {% set cellClasses = ["app-entity-table__cell", cell.classes if cell.classes,
- "app-entity-table__cell--slim" if cell.isSlim] | join(" ") | trim %}
+ {% set cellClasses = [
+ "app-entity-table__cell",
+ cell.classes if cell.classes,
+ "app-entity-table__cell--slim" if cell.isSlim,
+ "app-entity-table__cell--centered" if cell.isCentered
+ ] | join(" ") | trim %}
diff --git a/src/server/common/components/entity/_entity.scss b/src/server/common/components/entity/_entity.scss
index 61b73706..803739f1 100644
--- a/src/server/common/components/entity/_entity.scss
+++ b/src/server/common/components/entity/_entity.scss
@@ -22,6 +22,11 @@
@extend %govuk-list--bullet;
}
+.app-entity__group {
+ display: flex;
+ align-items: center;
+}
+
.app-entity__list-item {
@include govuk-text-colour;
margin: 0;
diff --git a/src/server/common/components/entity/template.njk b/src/server/common/components/entity/template.njk
index 4fc4a64c..63c2f1ec 100644
--- a/src/server/common/components/entity/template.njk
+++ b/src/server/common/components/entity/template.njk
@@ -77,11 +77,13 @@ data-testid="app-entity{% if params.index %}-{{ params.index }}{% endif %}">
{% elseif params.kind === "group" %}
- {% for entity in params.value %}
- {{ appEntity(entity) }}
- {% else %}
- {{ noValue }}
- {% endfor %}
+
+ {% for entity in params.value %}
+ {{ appEntity(entity) }}
+ {% else %}
+ {{ noValue }}
+ {% endfor %}
+
{% endif %}
diff --git a/src/server/common/components/filters/_filters.scss b/src/server/common/components/filters/_filters.scss
index 32f10594..2f67af2f 100644
--- a/src/server/common/components/filters/_filters.scss
+++ b/src/server/common/components/filters/_filters.scss
@@ -16,7 +16,7 @@
.app-filters-form {
padding: govuk-spacing(4) govuk-spacing(2);
- margin: govuk-spacing(4) govuk-spacing(-2) govuk-spacing(2);
+ margin: govuk-spacing(4) govuk-spacing(-2) 0;
background-color: $app-light-grey;
border-radius: $app-border-radius;
border-top: 1px solid $app-mid-grey;
diff --git a/src/server/common/components/page-heading/_page-heading.scss b/src/server/common/components/page-heading/_page-heading.scss
index 8517a670..9168ea49 100644
--- a/src/server/common/components/page-heading/_page-heading.scss
+++ b/src/server/common/components/page-heading/_page-heading.scss
@@ -9,6 +9,10 @@
margin: 0;
}
+.app-page-heading--intro {
+ margin: govuk-spacing(2) 0 govuk-spacing(4);
+}
+
.app-page-heading--cta {
margin: govuk-spacing(3) 0 govuk-spacing(6);
}
diff --git a/src/server/common/components/page-heading/template.njk b/src/server/common/components/page-heading/template.njk
index 874eaf35..f23c194f 100644
--- a/src/server/common/components/page-heading/template.njk
+++ b/src/server/common/components/page-heading/template.njk
@@ -6,6 +6,12 @@
{{ params.text }}
+ {% if params.intro %}
+
+ {{ params.intro }}
+
+ {% endif %}
+
{% if params.cta %}
-
+
Deployed
diff --git a/src/server/common/helpers/decorators/repositories.js b/src/server/common/helpers/decorators/repositories.js
index fb766f01..a095a9e6 100644
--- a/src/server/common/helpers/decorators/repositories.js
+++ b/src/server/common/helpers/decorators/repositories.js
@@ -1,7 +1,7 @@
import { repositoryDecorator } from '~/src/server/common/helpers/decorators/repository.js'
function repositoriesDecorator(repositories) {
- return function addDetail(service) {
+ return (service) => {
let repository
if (service.githubUrl) {
diff --git a/src/server/common/helpers/sort/sort-by-owner.js b/src/server/common/helpers/sort/sort-by-owner.js
index c73f3c78..bca3a9c4 100644
--- a/src/server/common/helpers/sort/sort-by-owner.js
+++ b/src/server/common/helpers/sort/sort-by-owner.js
@@ -1,12 +1,14 @@
-function sortByOwner(a, b) {
- if (a.userOwnsService && !b.userOwnsService) {
- return -1
- }
- if (!a.userOwnsService && b.userOwnsService) {
- return 1
- }
+function sortByOwner(prop) {
+ return (a, b) => {
+ if (a.isOwner && !b.isOwner) {
+ return -1
+ }
+ if (!a.isOwner && b.isOwner) {
+ return 1
+ }
- return a.serviceName.localeCompare(b.serviceName)
+ return a[prop].localeCompare(b[prop])
+ }
}
export { sortByOwner }
diff --git a/src/server/common/helpers/sort/sort-by-owner.test.js b/src/server/common/helpers/sort/sort-by-owner.test.js
index 8ff4400f..abb2a1ab 100644
--- a/src/server/common/helpers/sort/sort-by-owner.test.js
+++ b/src/server/common/helpers/sort/sort-by-owner.test.js
@@ -1,30 +1,33 @@
import { config } from '~/src/config/config.js'
import { servicesFixture } from '~/src/__fixtures__/services/services.js'
import { sortByOwner } from '~/src/server/common/helpers/sort/sort-by-owner.js'
+import { librariesFixture } from '~/src/__fixtures__/libraries.js'
describe('#sortByOwner', () => {
const oidcAdminGroupId = config.get('oidcAdminGroupId')
const servicesWithOwner = servicesFixture.map((service) => ({
...service,
- userOwnsService: service.teams.some(
- (team) => team.teamId === oidcAdminGroupId
- )
+ isOwner: service.teams.some((team) => team.teamId === oidcAdminGroupId)
+ }))
+ const librariesWithOwner = librariesFixture.repositories.map((library) => ({
+ ...library,
+ isOwner: library.teams.some((team) => team.teamId === oidcAdminGroupId)
}))
describe('With owner information', () => {
test('Should sort owned teams first', () => {
- expect(servicesWithOwner.sort(sortByOwner)).toEqual([
+ expect(servicesWithOwner.sort(sortByOwner('serviceName'))).toEqual([
expect.objectContaining({
serviceName: 'cdp-portal-frontend',
- userOwnsService: true
+ isOwner: true
}),
expect.objectContaining({
serviceName: 'cdp-user-service-backend',
- userOwnsService: true
+ isOwner: true
}),
expect.objectContaining({
serviceName: 'forms-designer',
- userOwnsService: false
+ isOwner: false
})
])
})
@@ -32,7 +35,7 @@ describe('#sortByOwner', () => {
describe('Without owner information', () => {
test('Should sort alphabetically by service name', () => {
- expect(servicesFixture.sort(sortByOwner)).toEqual([
+ expect(servicesFixture.sort(sortByOwner('serviceName'))).toEqual([
expect.objectContaining({
serviceName: 'cdp-portal-frontend'
}),
@@ -45,4 +48,15 @@ describe('#sortByOwner', () => {
])
})
})
+
+ describe('With alternative prop', () => {
+ test('Should sort owned teams first', () => {
+ expect(librariesWithOwner.sort(sortByOwner('id'))).toEqual([
+ expect.objectContaining({
+ id: 'hapi-tracing',
+ isOwner: true
+ })
+ ])
+ })
+ })
})
diff --git a/src/server/documentation/views/documentation.njk b/src/server/documentation/views/documentation.njk
index c524f3b6..8db04f58 100644
--- a/src/server/documentation/views/documentation.njk
+++ b/src/server/documentation/views/documentation.njk
@@ -4,13 +4,10 @@
{% block content %}
{{ appPageHeading({
- text: "Documentation"
+ text: "Documentation",
+ intro: "All things Core Delivery Platform, Architecture, Onboarding, Services, Developer docs and more"
}) }}
-
- All things Core Delivery Platform, onboarding, test suites, services, and more.
-
-
{{ appDocumentation({ nav: nav, content: content, toc: toc }) }}
diff --git a/src/server/running-services/controllers/running-services-list.js b/src/server/running-services/controllers/running-services-list.js
index eae62b6f..db5a9c55 100644
--- a/src/server/running-services/controllers/running-services-list.js
+++ b/src/server/running-services/controllers/running-services-list.js
@@ -34,7 +34,7 @@ const runningServicesListController = {
tableData: {
headers: [
...(isAuthenticated
- ? [{ id: 'owner', text: null, size: '20-fixed' }]
+ ? [{ id: 'owner', classes: 'app-entity-table__cell--owned' }]
: []),
{ id: 'service', text: 'Service', width: '15' },
{ id: 'team', text: 'Team', width: '15' },
diff --git a/src/server/running-services/helpers/build-running-services-table-data.js b/src/server/running-services/helpers/build-running-services-table-data.js
index 004c64be..0d1d6dc5 100644
--- a/src/server/running-services/helpers/build-running-services-table-data.js
+++ b/src/server/running-services/helpers/build-running-services-table-data.js
@@ -79,8 +79,9 @@ async function buildRunningServicesTableData({ pre, query }) {
userScopeUUIDs
})
+ const ownerSorter = sortByOwner('serviceName')
const decorator = runningServiceToEntityRow(environments, isAuthenticated)
- const rows = services.toSorted(sortByOwner).map(decorator)
+ const rows = services.toSorted(ownerSorter).map(decorator)
return {
environments,
diff --git a/src/server/running-services/helpers/transformers/running-service-to-entity-row.js b/src/server/running-services/helpers/transformers/running-service-to-entity-row.js
index 81203945..05f3ebe3 100644
--- a/src/server/running-services/helpers/transformers/running-service-to-entity-row.js
+++ b/src/server/running-services/helpers/transformers/running-service-to-entity-row.js
@@ -4,7 +4,7 @@ import {
} from '~/src/server/common/helpers/nunjucks/render-component.js'
function runningServiceToEntityRow(allEnvironments, isAuthenticated) {
- return ({ serviceName, environments, teams, userOwnsService }) => {
+ return ({ serviceName, environments, teams, isOwner }) => {
const serviceTeams = teams
.filter((team) => team.teamId)
.map((team) => ({
@@ -13,7 +13,7 @@ function runningServiceToEntityRow(allEnvironments, isAuthenticated) {
url: `/teams/${team.teamId}`
}))
- const icon = userOwnsService
+ const icon = isOwner
? renderComponent(
'tool-tip',
{
@@ -53,6 +53,8 @@ function runningServiceToEntityRow(allEnvironments, isAuthenticated) {
? [
{
headers: 'owner',
+ isCentered: true,
+ classes: 'app-entity-table__cell--owned',
entity: { kind: 'html', value: icon }
}
]
diff --git a/src/server/running-services/helpers/transformers/running-service-to-entity-row.test.js b/src/server/running-services/helpers/transformers/running-service-to-entity-row.test.js
index 2679114c..165fa755 100644
--- a/src/server/running-services/helpers/transformers/running-service-to-entity-row.test.js
+++ b/src/server/running-services/helpers/transformers/running-service-to-entity-row.test.js
@@ -37,7 +37,9 @@ describe('#runningServiceToEntityRow', () => {
kind: 'html',
value: expect.stringContaining('app-star-icon')
},
- headers: 'owner'
+ headers: 'owner',
+ isCentered: true,
+ classes: 'app-entity-table__cell--owned'
},
{
entity: {
@@ -168,7 +170,9 @@ describe('#runningServiceToEntityRow', () => {
kind: 'html',
value: expect.stringContaining('app-star-icon')
},
- headers: 'owner'
+ headers: 'owner',
+ isCentered: true,
+ classes: 'app-entity-table__cell--owned'
},
{
entity: {
diff --git a/src/server/running-services/helpers/transformers/running-services.js b/src/server/running-services/helpers/transformers/running-services.js
index 0d32b2f2..879ef459 100644
--- a/src/server/running-services/helpers/transformers/running-services.js
+++ b/src/server/running-services/helpers/transformers/running-services.js
@@ -27,18 +27,18 @@ function transformRunningServices({
deployableService?.teams.filter((team) => team.teamId) ?? []
}
- if (!acc[rs.service].userOwnsService) {
- acc[rs.service].userOwnsService = acc[rs.service].teams.some((team) =>
+ if (!acc[rs.service].isOwner) {
+ acc[rs.service].isOwner = acc[rs.service].teams.some((team) =>
userScopeUUIDs.includes(team.teamId)
)
}
return acc
}, {})
- ).map(([serviceName, { envs, teams, userOwnsService }]) => {
+ ).map(([serviceName, { envs, teams, isOwner }]) => {
return {
serviceName,
- userOwnsService,
+ isOwner,
environments: envs,
teams
}
diff --git a/src/server/running-services/helpers/transformers/running-services.test.js b/src/server/running-services/helpers/transformers/running-services.test.js
index a68c4ab6..138404e9 100644
--- a/src/server/running-services/helpers/transformers/running-services.test.js
+++ b/src/server/running-services/helpers/transformers/running-services.test.js
@@ -65,7 +65,7 @@ describe('transformRunningServices', () => {
teamId: 'aabe63e7-87ef-4beb-a596-c810631fc474'
}
],
- userOwnsService: true
+ isOwner: true
},
{
environments: {
@@ -108,7 +108,7 @@ describe('transformRunningServices', () => {
},
serviceName: 'cdp-self-service-ops',
teams: [],
- userOwnsService: false
+ isOwner: false
},
{
environments: {
@@ -157,7 +157,7 @@ describe('transformRunningServices', () => {
teamId: 'aabe63e7-87ef-4beb-a596-c810631fc474'
}
],
- userOwnsService: true
+ isOwner: true
}
])
})
diff --git a/src/server/running-services/views/list.njk b/src/server/running-services/views/list.njk
index baa52451..e1fba6c6 100644
--- a/src/server/running-services/views/list.njk
+++ b/src/server/running-services/views/list.njk
@@ -4,7 +4,8 @@
{{ appPageHeading({
caption: "Whats running where?",
- text: "Running Services"
+ text: "Running Services",
+ intro: "All CDP running services, with microservice details and status per environment"
}) }}
{% call appFilters({
diff --git a/src/server/services/list/controller.js b/src/server/services/list/controller.js
index 657f47d1..36abf1cf 100644
--- a/src/server/services/list/controller.js
+++ b/src/server/services/list/controller.js
@@ -38,7 +38,7 @@ const serviceListController = {
tableData: {
headers: [
...(isAuthenticated
- ? [{ id: 'owner', text: null, size: '20-fixed' }]
+ ? [{ id: 'owner', classes: 'app-entity-table__cell--owned' }]
: []),
{ id: 'service', text: 'Service', width: '15' },
{ id: 'team', text: 'Team', width: '15' },
diff --git a/src/server/services/list/helpers/build-services-table-data.js b/src/server/services/list/helpers/build-services-table-data.js
index ac1a2e2b..c78afbb7 100644
--- a/src/server/services/list/helpers/build-services-table-data.js
+++ b/src/server/services/list/helpers/build-services-table-data.js
@@ -75,14 +75,15 @@ async function buildServicesTableData({
)
const rowDecorator = serviceToEntityRow(isAuthenticated)
+ const ownerSorter = sortByOwner('serviceName')
const rows = services
.map((serviceDetail) => ({
...serviceDetail,
- userOwnsService: serviceDetail.teams.some((team) =>
+ isOwner: serviceDetail.teams.some((team) =>
userScopeUUIDs.includes(team.teamId)
)
}))
- .sort(sortByOwner)
+ .toSorted(ownerSorter)
.map(rowDecorator)
return {
diff --git a/src/server/services/list/transformers/service-to-entity-row.js b/src/server/services/list/transformers/service-to-entity-row.js
index f549f92e..0a0d7fec 100644
--- a/src/server/services/list/transformers/service-to-entity-row.js
+++ b/src/server/services/list/transformers/service-to-entity-row.js
@@ -40,7 +40,7 @@ function serviceToEntityRow(isAuthenticated) {
entity: { kind: 'date', value: service.createdAt }
}
- const icon = service.userOwnsService
+ const icon = service.isOwner
? renderComponent(
'tool-tip',
{ text: 'Owned Service', classes: 'app-tool-tip--small' },
@@ -54,6 +54,8 @@ function serviceToEntityRow(isAuthenticated) {
? [
{
headers: 'owner',
+ isCentered: true,
+ classes: 'app-entity-table__cell--owned',
entity: { kind: 'html', value: icon }
}
]
diff --git a/src/server/services/list/transformers/service-to-entity-row.test.js b/src/server/services/list/transformers/service-to-entity-row.test.js
index 3b9349a0..e6f79b35 100644
--- a/src/server/services/list/transformers/service-to-entity-row.test.js
+++ b/src/server/services/list/transformers/service-to-entity-row.test.js
@@ -13,7 +13,9 @@ describe('#serviceToEntityRow', () => {
kind: 'html',
value: ''
},
- headers: 'owner'
+ headers: 'owner',
+ isCentered: true,
+ classes: 'app-entity-table__cell--owned'
},
{
entity: {
diff --git a/src/server/services/list/views/list.njk b/src/server/services/list/views/list.njk
index e060be1f..d92649bf 100644
--- a/src/server/services/list/views/list.njk
+++ b/src/server/services/list/views/list.njk
@@ -9,7 +9,8 @@
{% endset %}
{{ appPageHeading({
- text: "Services"
+ text: "Services",
+ intro: "Frontend and backend microservice details"
}) }}
{% call appFilters({
@@ -32,6 +33,7 @@
},
hiddenInputs: hiddenInputs
}) %}
+
{{ appAutocomplete({
id: "filters-service",
@@ -67,6 +69,7 @@
suggestions: teamFilters
}) }}
+
{% endcall %}
{% block xhrContent %}
diff --git a/src/server/services/secrets/views/environment.njk b/src/server/services/secrets/views/environment.njk
index dadaa14c..c4a6c8f9 100644
--- a/src/server/services/secrets/views/environment.njk
+++ b/src/server/services/secrets/views/environment.njk
@@ -107,6 +107,7 @@
{% endblock %}
{% block tabContent %}
+
{% call appSplitPane() %}
diff --git a/src/server/teams/controllers/teams-list.js b/src/server/teams/controllers/teams-list.js
index 2eeebb49..6a2b31df 100644
--- a/src/server/teams/controllers/teams-list.js
+++ b/src/server/teams/controllers/teams-list.js
@@ -1,14 +1,59 @@
+import { validate as uuidValidate } from 'uuid'
+
import { fetchTeams } from '~/src/server/teams/helpers/fetch/fetch-teams.js'
import { teamToEntityRow } from '~/src/server/teams/transformers/team-to-entity-row.js'
+import { provideAuthedUser } from '~/src/server/common/helpers/auth/pre/provide-authed-user.js'
+
+function belongsToTeam(userScopeUUIDs) {
+ return (team) => ({
+ isMemberOfTeam: userScopeUUIDs.includes(team.teamId),
+ ...team
+ })
+}
+
+function sortByTeam(a, b) {
+ if (a.isMemberOfTeam && !b.isMemberOfTeam) {
+ return -1
+ }
+ if (!a.isMemberOfTeam && b.isMemberOfTeam) {
+ return 1
+ }
+
+ return a.name.localeCompare(b.name)
+}
const teamsListController = {
+ options: {
+ pre: [provideAuthedUser]
+ },
handler: async (request, h) => {
+ const authedUser = request.pre.authedUser
+ const isAuthenticated = authedUser?.isAuthenticated
+ const userScopeUUIDs = authedUser?.scope.filter(uuidValidate) ?? []
+
const { teams } = await fetchTeams()
- const entityRows = teams?.map(teamToEntityRow)
+
+ const teamDecorator = belongsToTeam(userScopeUUIDs)
+ const rowBuilder = teamToEntityRow(isAuthenticated, userScopeUUIDs)
+ const rows =
+ teams?.map(teamDecorator).toSorted(sortByTeam).map(rowBuilder) ?? []
return h.view('teams/views/list', {
pageTitle: 'Teams',
- entityRows
+ tableData: {
+ headers: [
+ ...(isAuthenticated
+ ? [{ id: 'member', classes: 'app-entity-table__cell--owned' }]
+ : []),
+ { id: 'name', text: 'Name', width: '15' },
+ { id: 'github-team', text: 'GitHub Team', width: '15' },
+ { id: 'user-count', text: 'Members', width: '5' },
+ { id: 'updated', text: 'Last Updated', width: '30' },
+ { id: 'created', text: 'Created', width: '35' }
+ ],
+ rows,
+ noResult: 'No running services found'
+ }
})
}
}
diff --git a/src/server/teams/transformers/team-to-entity-row.js b/src/server/teams/transformers/team-to-entity-row.js
index 6d1d3bc5..28a17922 100644
--- a/src/server/teams/transformers/team-to-entity-row.js
+++ b/src/server/teams/transformers/team-to-entity-row.js
@@ -1,35 +1,79 @@
import { config } from '~/src/config/config.js'
+import {
+ renderComponent,
+ renderIcon
+} from '~/src/server/common/helpers/nunjucks/render-component.js'
-function teamToEntityRow(team) {
- const githubOrg = config.get('githubOrg')
+function teamToEntityRow(isAuthenticated) {
+ return (team) => {
+ const githubOrg = config.get('githubOrg')
- return [
- {
- kind: 'link',
- value: team.name,
- url: `/teams/${team.teamId}`
- },
- {
- kind: 'link',
- value: team?.github ? `@${team.github}` : null,
- url: team?.github
- ? `https://github.com/orgs/${githubOrg}/teams/${team.github}`
- : null,
- newWindow: true
- },
- {
- kind: 'text',
- value: team.users?.length
- },
- {
- kind: 'date',
- value: team.updatedAt
- },
- {
- kind: 'date',
- value: team.createdAt
+ const icon = team.isMemberOfTeam
+ ? renderComponent(
+ 'tool-tip',
+ {
+ text: 'My Team',
+ classes: 'app-tool-tip--small'
+ },
+ [renderIcon('star-icon', { classes: 'app-icon--tiny' })]
+ )
+ : ''
+
+ return {
+ cells: [
+ ...(isAuthenticated
+ ? [
+ {
+ headers: 'member',
+ isCentered: true,
+ classes: 'app-entity-table__cell--owned',
+ entity: { kind: 'html', value: icon }
+ }
+ ]
+ : []),
+ {
+ headers: 'name',
+ entity: {
+ kind: 'link',
+ value: team.name,
+ url: `/teams/${team.teamId}`
+ }
+ },
+ {
+ headers: 'github-team',
+ entity: {
+ kind: 'link',
+ value: team?.github ? `@${team.github}` : null,
+ url: team?.github
+ ? `https://github.com/orgs/${githubOrg}/teams/${team.github}`
+ : null,
+ newWindow: true
+ }
+ },
+ {
+ headers: 'members',
+ entity: {
+ kind: 'text',
+ value: team.users?.length
+ }
+ },
+ {
+ headers: 'updated',
+ entity: {
+ kind: 'date',
+ value: team.updatedAt
+ }
+ },
+ {
+ headers: 'created',
+ entity: {
+ kind: 'date',
+ value: team.createdAt
+ }
+ }
+ ]
}
- ]
+ }
}
export { teamToEntityRow }
diff --git a/src/server/teams/transformers/team-to-entity-row.test.js b/src/server/teams/transformers/team-to-entity-row.test.js
index 7b1eb6a5..258def81 100644
--- a/src/server/teams/transformers/team-to-entity-row.test.js
+++ b/src/server/teams/transformers/team-to-entity-row.test.js
@@ -1,64 +1,162 @@
-import { config } from '~/src/config/config.js'
import { teamToEntityRow } from '~/src/server/teams/transformers/team-to-entity-row.js'
import { cdpTeamFixture } from '~/src/__fixtures__/admin/cdp-team.js'
import { cdpTeamWithoutGithubFixture } from '~/src/__fixtures__/admin/cdp-team-without-github.js'
-const githubOrg = config.get('githubOrg')
-
describe('#teamToEntityRow', () => {
- test('Should provide expected team transformation', () => {
- expect(teamToEntityRow(cdpTeamFixture.team)).toEqual([
- {
- kind: 'link',
- url: '/teams/aabe63e7-87ef-4beb-a596-c810631fc474',
- value: 'Platform'
- },
- {
- kind: 'link',
- newWindow: true,
- url: `https://github.com/orgs/${githubOrg}/teams/cdp-platform`,
- value: '@cdp-platform'
- },
- {
- kind: 'text',
- value: 2
- },
- {
- kind: 'date',
- value: '2023-10-03T11:11:31.085Z'
- },
- {
- kind: 'date',
- value: '2023-09-28T12:52:14.673Z'
- }
- ])
+ describe('When authenticated', () => {
+ test('Should provide expected team transformation', () => {
+ expect(teamToEntityRow(true)(cdpTeamFixture.team)).toEqual({
+ cells: [
+ {
+ entity: {
+ kind: 'html',
+ value: ''
+ },
+ headers: 'member',
+ isCentered: true,
+ classes: 'app-entity-table__cell--owned'
+ },
+ {
+ entity: {
+ kind: 'link',
+ url: '/teams/aabe63e7-87ef-4beb-a596-c810631fc474',
+ value: 'Platform'
+ },
+ headers: 'name'
+ },
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: 'https://github.com/orgs/DEFRA/teams/cdp-platform',
+ value: '@cdp-platform'
+ },
+ headers: 'github-team'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 2
+ },
+ headers: 'members'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2023-10-03T11:11:31.085Z'
+ },
+ headers: 'updated'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2023-09-28T12:52:14.673Z'
+ },
+ headers: 'created'
+ }
+ ]
+ })
+ })
+
+ test('Should provide expected team transformation when team is not linked to a GitHub team', () => {
+ expect(teamToEntityRow(true)(cdpTeamWithoutGithubFixture.team)).toEqual({
+ cells: [
+ {
+ entity: {
+ kind: 'html',
+ value: ''
+ },
+ headers: 'member',
+ isCentered: true,
+ classes: 'app-entity-table__cell--owned'
+ },
+ {
+ entity: {
+ kind: 'link',
+ url: '/teams/47c04343-4c0e-4326-9848-bef7c1e2eedd',
+ value: 'Admin'
+ },
+ headers: 'name'
+ },
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: null,
+ value: null
+ },
+ headers: 'github-team'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 4
+ },
+ headers: 'members'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2023-08-30T08:03:23.657Z'
+ },
+ headers: 'updated'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2023-08-23T16:18:28.742Z'
+ },
+ headers: 'created'
+ }
+ ]
+ })
+ })
})
- test('Should provide expected team transformation when team is not linked to a GitHub team', () => {
- expect(teamToEntityRow(cdpTeamWithoutGithubFixture.team)).toEqual([
- {
- kind: 'link',
- url: '/teams/47c04343-4c0e-4326-9848-bef7c1e2eedd',
- value: 'Admin'
- },
- {
- kind: 'link',
- newWindow: true,
- url: null,
- value: null
- },
- {
- kind: 'text',
- value: 4
- },
- {
- kind: 'date',
- value: '2023-08-30T08:03:23.657Z'
- },
- {
- kind: 'date',
- value: '2023-08-23T16:18:28.742Z'
- }
- ])
+ describe('When not authenticated', () => {
+ test('Should provide expected team transformation without member cell', () => {
+ expect(teamToEntityRow(false)(cdpTeamFixture.team)).toEqual({
+ cells: [
+ {
+ entity: {
+ kind: 'link',
+ url: '/teams/aabe63e7-87ef-4beb-a596-c810631fc474',
+ value: 'Platform'
+ },
+ headers: 'name'
+ },
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: 'https://github.com/orgs/DEFRA/teams/cdp-platform',
+ value: '@cdp-platform'
+ },
+ headers: 'github-team'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 2
+ },
+ headers: 'members'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2023-10-03T11:11:31.085Z'
+ },
+ headers: 'updated'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2023-09-28T12:52:14.673Z'
+ },
+ headers: 'created'
+ }
+ ]
+ })
+ })
})
})
diff --git a/src/server/teams/views/list.njk b/src/server/teams/views/list.njk
index fb336259..0e40a890 100644
--- a/src/server/teams/views/list.njk
+++ b/src/server/teams/views/list.njk
@@ -2,19 +2,10 @@
{% block content %}
{{ appPageHeading({
- text: "Teams"
+ text: "Teams",
+ intro: "Team details, members and assets"
}) }}
- {{ appEntityList({
- headings: [
- { text: "Team", size: "medium"},
- { text: "GitHub team", size: "medium"},
- { text: "Members", size: "small"},
- { text: "Last updated", size: "medium"},
- { text: "Created", size: "medium"}
- ],
- entityRows: entityRows,
- noResult: "Currently there are no teams"
- }) }}
+ {{ appEntityTable(tableData) }}
{% endblock %}
diff --git a/src/server/test-suites/controllers/test-suite-list.js b/src/server/test-suites/controllers/test-suite-list.js
index e09c4e64..9eed0a1c 100644
--- a/src/server/test-suites/controllers/test-suite-list.js
+++ b/src/server/test-suites/controllers/test-suite-list.js
@@ -1,24 +1,52 @@
-import { sortBy } from '~/src/server/common/helpers/sort/sort-by.js'
+import { validate as uuidValidate } from 'uuid'
+import { sortByOwner } from '~/src/server/common/helpers/sort/sort-by-owner.js'
import { fetchTestSuites } from '~/src/server/test-suites/helpers/fetch/index.js'
import { fetchRepositories } from '~/src/server/common/helpers/fetch/fetch-repositories.js'
import { testSuiteDecorator } from '~/src/server/test-suites/helpers/decorators/test-suite.js'
-import { transformTestSuiteToEntityRow } from '~/src/server/test-suites/transformers/test-suite-to-entity-row.js'
+import { provideAuthedUser } from '~/src/server/common/helpers/auth/pre/provide-authed-user.js'
+import { testSuiteToEntityRow } from '~/src/server/test-suites/transformers/test-suite-to-entity-row.js'
const testSuiteListController = {
+ options: {
+ pre: [provideAuthedUser]
+ },
handler: async (request, h) => {
- const { repositories } = await fetchRepositories()
- const testSuites = await fetchTestSuites()
+ const authedUser = request.pre.authedUser
+ const isAuthenticated = authedUser?.isAuthenticated
+ const userScopeUUIDs = authedUser?.scope.filter(uuidValidate) ?? []
- const entityRows = testSuites
- .map(testSuiteDecorator(repositories))
- ?.sort(sortBy('serviceName', 'asc'))
- ?.map(transformTestSuiteToEntityRow)
+ const [testSuites, { repositories }] = await Promise.all([
+ fetchTestSuites(),
+ fetchRepositories()
+ ])
+
+ const decorator = testSuiteDecorator(repositories, userScopeUUIDs)
+ const rowBuilder = testSuiteToEntityRow(isAuthenticated)
+ const ownerSorter = sortByOwner('serviceName')
+
+ const rows = testSuites
+ ?.map(decorator)
+ .toSorted(ownerSorter)
+ .map(rowBuilder)
return h.view('test-suites/views/list', {
pageTitle: 'Test Suites',
- heading: 'Test Suites',
- entityRows
+ tableData: {
+ headers: [
+ ...(isAuthenticated
+ ? [{ id: 'owner', classes: 'app-entity-table__cell--owned' }]
+ : []),
+ { id: 'test-suite', text: 'Test Suite', width: '15' },
+ { id: 'team', text: 'Team', width: '15' },
+ { id: 'kind', text: 'Kind', width: '10' },
+ { id: 'github-repository', text: 'GitHub Repository', width: '20' },
+ { id: 'last-ran', text: 'Last Ran', width: '20' },
+ { id: 'created', text: 'Created', width: '20' }
+ ],
+ rows,
+ noResult: 'No test suites found'
+ }
})
}
}
diff --git a/src/server/test-suites/controllers/test-suite.js b/src/server/test-suites/controllers/test-suite.js
index 255fd5de..afa0cdd7 100644
--- a/src/server/test-suites/controllers/test-suite.js
+++ b/src/server/test-suites/controllers/test-suite.js
@@ -1,13 +1,13 @@
import Joi from 'joi'
import Boom from '@hapi/boom'
-import { fetchTestRuns } from '~/src/server/test-suites/helpers/fetch/index.js'
import { shouldPoll } from '~/src/server/test-suites/helpers/should-poll.js'
+import { fetchTestRuns } from '~/src/server/test-suites/helpers/fetch/index.js'
+import { provideCanRun } from '~/src/server/test-suites/helpers/pre/provide-can-run.js'
import { provideTestSuite } from '~/src/server/test-suites/helpers/pre/provide-test-suite.js'
-import { transformTestSuiteRunResults } from '~/src/server/test-suites/transformers/test-suite-run-results.js'
+import { testSuiteRunResults } from '~/src/server/test-suites/transformers/test-suite-run-results.js'
+import { transformTestSuiteToSummary } from '~/src/server/test-suites/transformers/test-suite-to-summary.js'
import { provideEnvironmentOptions } from '~/src/server/test-suites/helpers/pre/provide-environment-options.js'
-import { testSuiteToEntityDataList } from '~/src/server/test-suites/transformers/test-suite-to-entity-data-list.js'
-import { provideCanRun } from '~/src/server/test-suites/helpers/pre/provide-can-run.js'
const testSuiteController = {
options: {
@@ -26,21 +26,31 @@ const testSuiteController = {
const serviceName = testSuite.serviceName
const testRuns = await fetchTestRuns(serviceName)
-
- const testSuiteRunResults = testRuns.map((test) =>
- transformTestSuiteRunResults(test, canRun)
- )
+ const rows = testRuns.map((test) => testSuiteRunResults(test, canRun))
return h.view('test-suites/views/test-suite', {
pageTitle: `Test Suite - ${serviceName}`,
- heading: serviceName,
testSuite,
canRun,
- entityDataList: testSuiteToEntityDataList(testSuite),
+ summaryList: transformTestSuiteToSummary(testSuite),
environmentOptions,
- testSuiteRunResults,
owningTeamIds: testSuite.teams.map((testsuite) => testsuite.teamId),
shouldPoll: shouldPoll(testRuns),
+ tableData: {
+ headers: [
+ { id: 'version', text: 'Version', width: '5' },
+ { id: 'environment', text: 'Environment', width: '15' },
+ { id: 'status', text: 'Status', width: '5' },
+ { id: 'logs', text: 'Logs', width: '15' },
+ { id: 'results', text: 'Results', width: '10' },
+ { id: 'user', text: 'User', width: '20' },
+ { id: 'duration', text: 'Duration', width: '5' },
+ { id: 'last-ran', text: 'Last Ran', width: '15' },
+ { id: 'action', text: 'Action', width: '10' }
+ ],
+ rows,
+ noResult: 'No test suite run results found'
+ },
breadcrumbs: [
{
text: 'Test suites',
diff --git a/src/server/test-suites/helpers/decorators/test-suite.js b/src/server/test-suites/helpers/decorators/test-suite.js
index 9c4e3ea4..5eebf7b8 100644
--- a/src/server/test-suites/helpers/decorators/test-suite.js
+++ b/src/server/test-suites/helpers/decorators/test-suite.js
@@ -1,14 +1,19 @@
import { repositoriesDecorator } from '~/src/server/common/helpers/decorators/repositories.js'
import { provideTestType } from '~/src/server/test-suites/helpers/provide-test-type.js'
-function testSuiteDecorator(repositories) {
- return function addDetail({ testSuite, lastRun }) {
- const testSuiteWithRepo = repositoriesDecorator(repositories)(testSuite)
+function testSuiteDecorator(repositories, userScopeUUIDs) {
+ const decorator = repositoriesDecorator(repositories)
+
+ return ({ testSuite, lastRun }) => {
+ const testSuiteWithRepo = decorator(testSuite)
return {
...testSuiteWithRepo,
lastRun,
- testType: provideTestType(testSuiteWithRepo.topics)
+ testType: provideTestType(testSuiteWithRepo.topics),
+ isOwner: testSuiteWithRepo?.teams.some((team) =>
+ userScopeUUIDs.includes(team.teamId)
+ )
}
}
}
diff --git a/src/server/test-suites/transformers/test-suite-run-results.js b/src/server/test-suites/transformers/test-suite-run-results.js
index 84a87b07..fa3d929d 100644
--- a/src/server/test-suites/transformers/test-suite-run-results.js
+++ b/src/server/test-suites/transformers/test-suite-run-results.js
@@ -8,6 +8,7 @@ import {
import { provideTestRunStatusClassname } from '~/src/server/test-suites/helpers/provide-test-run-status-classname.js'
import { buildLogsLink } from '~/src/server/test-suites/helpers/build-logs-link.js'
import { getTestStatusIcon } from '~/src/server/test-suites/helpers/get-test-status-icon.js'
+import { formatText } from '~/src/config/nunjucks/filters/index.js'
function getDuration({ created, taskLastUpdated }, hasResult) {
if (created && taskLastUpdated && hasResult) {
@@ -17,7 +18,7 @@ function getDuration({ created, taskLastUpdated }, hasResult) {
return null
}
-function transformTestSuiteRunResults(testRun, canRun) {
+function testSuiteRunResults(testRun, canRun) {
const runTaskStatus = testRun.taskStatus?.toLowerCase()
const runTestStatus = testRun.testStatus?.toLowerCase()
@@ -34,48 +35,80 @@ function transformTestSuiteRunResults(testRun, canRun) {
testRun.taskLastUpdated
].every(Boolean)
- return [
- {
- kind: 'link',
- value: testRun.tag,
- url: `https://github.com/DEFRA/${testRun.testSuite}/releases/tag/${testRun.tag}`,
- newWindow: true
- },
- {
- kind: 'text',
- value: startCase(testRun.environment)
- },
- {
- kind: 'tag',
- value: testRun.taskStatus,
- classes: provideTestRunStatusClassname(testRun.taskStatus),
- showLoader: inProgress
- },
- {
- kind: 'link',
- value: logsLinkDataAvailable ? `logs.${testRun.environment}` : null,
- url: logsLinkDataAvailable && buildLogsLink(testRun, hasResult),
- newWindow: true
- },
- {
- kind: 'link',
- value: hasResult ? 'Report' : null,
- url: `/test-suites/test-results/${testRun.environment}/${testRun.tag}/${testRun.testSuite}/${testRun.runId}/index.html`,
- icon: getTestStatusIcon(runTestStatus)
- },
- {
- kind: 'text',
- value: testRun.user.displayName
- },
- { kind: 'text', value: getDuration(testRun, hasResult) },
- { kind: 'date', value: testRun.taskLastUpdated },
- {
- kind: 'button',
- classes: 'app-button--small',
- value: canRun && runTaskStatus === taskStatus.inProgress ? 'Stop' : null,
- url: `/test-suites/${testRun.testSuite}/${testRun.runId}/stop`
- }
- ]
+ return {
+ cells: [
+ {
+ headers: 'version',
+ entity: {
+ kind: 'link',
+ value: testRun.tag,
+ url: `https://github.com/DEFRA/${testRun.testSuite}/releases/tag/${testRun.tag}`,
+ newWindow: true
+ }
+ },
+ {
+ headers: 'environment',
+ entity: {
+ kind: 'text',
+ value: startCase(testRun.environment)
+ }
+ },
+ {
+ headers: 'status',
+ entity: {
+ kind: 'tag',
+ value: formatText(testRun.taskStatus),
+ classes: provideTestRunStatusClassname(testRun.taskStatus),
+ showLoader: inProgress
+ }
+ },
+ {
+ headers: 'logs',
+ entity: {
+ kind: 'link',
+ value: logsLinkDataAvailable ? `logs.${testRun.environment}` : null,
+ url: logsLinkDataAvailable && buildLogsLink(testRun, hasResult),
+ newWindow: true
+ }
+ },
+ {
+ headers: 'results',
+ isCentered: true,
+ classes: 'app-entity-table__cell--owned',
+ entity: {
+ kind: 'link',
+ value: hasResult ? 'Report' : null,
+ url: `/test-suites/test-results/${testRun.environment}/${testRun.tag}/${testRun.testSuite}/${testRun.runId}/index.html`,
+ icon: getTestStatusIcon(runTestStatus)
+ }
+ },
+ {
+ headers: 'user',
+ entity: {
+ kind: 'text',
+ value: testRun.user.displayName
+ }
+ },
+ {
+ headers: 'duration',
+ entity: { kind: 'text', value: getDuration(testRun, hasResult) }
+ },
+ {
+ headers: 'last-ran',
+ entity: { kind: 'date', value: testRun.taskLastUpdated }
+ },
+ {
+ headers: 'action',
+ entity: {
+ kind: 'button',
+ classes: 'app-button--small',
+ value:
+ canRun && runTaskStatus === taskStatus.inProgress ? 'Stop' : null,
+ url: `/test-suites/${testRun.testSuite}/${testRun.runId}/stop`
+ }
+ }
+ ]
+ }
}
-export { transformTestSuiteRunResults }
+export { testSuiteRunResults }
diff --git a/src/server/test-suites/transformers/test-suite-run-results.test.js b/src/server/test-suites/transformers/test-suite-run-results.test.js
index c3774205..4b25d596 100644
--- a/src/server/test-suites/transformers/test-suite-run-results.test.js
+++ b/src/server/test-suites/transformers/test-suite-run-results.test.js
@@ -1,108 +1,170 @@
-import { transformTestSuiteRunResults } from '~/src/server/test-suites/transformers/test-suite-run-results.js'
+import { testSuiteRunResults } from '~/src/server/test-suites/transformers/test-suite-run-results.js'
import { testSuiteRunsFixture } from '~/src/__fixtures__/test-suite-runs.js'
describe('#transformTestSuiteRunResults', () => {
describe('When a user can NOT run the tests', () => {
test('Should provide expected test suite run transformation without action buttons', () => {
expect(
- testSuiteRunsFixture.map((t) => transformTestSuiteRunResults(t, false))
+ testSuiteRunsFixture.map((t) => testSuiteRunResults(t, false))
).toEqual([
- [
- {
- kind: 'link',
- newWindow: true,
- url: 'https://github.com/DEFRA/cdp-portal-smoke-tests/releases/tag/0.2.0',
- value: '0.2.0'
- },
- {
- kind: 'text',
- value: 'Infra Dev'
- },
- {
- classes: 'govuk-tag--light-blue',
- kind: 'tag',
- showLoader: true,
- value: 'in-progress'
- },
- {
- kind: 'link',
- newWindow: true,
- url: "https://logs.infra-dev.cdp-int.defra.cloud/_dashboards/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:'2024-02-27T10:29:32.000',to:'2024-02-27T10:31:36.000'))&_a=(columns:!(_source),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:'ecs_task_arn:arn:aws:ecs:eu-west-2:123456789:task%2Finfra-dev-ecs-public%2Ff5cffc31e21149208f38b8ec2b168c50'),sort:!())&_a=(columns:!(log),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:''),sort:!())",
- value: 'logs.infra-dev'
- },
- {
- icon: expect.stringContaining('Test passed'),
- kind: 'link',
- url: '/test-suites/test-results/infra-dev/0.2.0/cdp-portal-smoke-tests/383547d8-f71c-4e7e-8b03-4ddf09fd84fe/index.html',
- value: 'Report'
- },
- {
- kind: 'text',
- value: 'B. A. Baracus'
- },
- {
- kind: 'text',
- value: '2 minutes'
- },
- {
- kind: 'date',
- value: '2024-02-27T10:31:36Z'
- },
- {
- classes: 'app-button--small',
- kind: 'button',
- value: null,
- url: '/test-suites/cdp-portal-smoke-tests/383547d8-f71c-4e7e-8b03-4ddf09fd84fe/stop'
- }
- ],
- [
- {
- kind: 'link',
- newWindow: true,
- url: 'https://github.com/DEFRA/cdp-portal-smoke-tests/releases/tag/0.1.0',
- value: '0.1.0'
- },
- {
- kind: 'text',
- value: 'Infra Dev'
- },
- {
- classes: 'govuk-tag--green',
- kind: 'tag',
- showLoader: false,
- value: 'finished'
- },
- {
- kind: 'link',
- newWindow: true,
- url: "https://logs.infra-dev.cdp-int.defra.cloud/_dashboards/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:'2024-02-26T16:38:28.000',to:'2024-02-26T16:40:34.000'))&_a=(columns:!(_source),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:'ecs_task_arn:arn:aws:ecs:eu-west-2:123456789:task%2Finfra-dev-ecs-public%2F7e4c74aa41e44a0399bef08711563715'),sort:!())&_a=(columns:!(log),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:''),sort:!())",
- value: 'logs.infra-dev'
- },
- {
- icon: expect.stringContaining('Test passed'),
- kind: 'link',
- url: '/test-suites/test-results/infra-dev/0.1.0/cdp-portal-smoke-tests/dc34cdaf-1f51-44cf-8c63-e9b6800d9609/index.html',
- value: 'Report'
- },
- {
- kind: 'text',
- value: 'B. A. Baracus'
- },
- {
- kind: 'text',
- value: '2 minutes'
- },
- {
- kind: 'date',
- value: '2024-02-26T16:40:34Z'
- },
- {
- kind: 'button',
- classes: 'app-button--small',
- url: '/test-suites/cdp-portal-smoke-tests/dc34cdaf-1f51-44cf-8c63-e9b6800d9609/stop',
- value: null
- }
- ]
+ {
+ cells: [
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: 'https://github.com/DEFRA/cdp-portal-smoke-tests/releases/tag/0.2.0',
+ value: '0.2.0'
+ },
+ headers: 'version'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'Infra Dev'
+ },
+ headers: 'environment'
+ },
+ {
+ entity: {
+ classes: 'govuk-tag--light-blue',
+ kind: 'tag',
+ showLoader: true,
+ value: 'In-progress'
+ },
+ headers: 'status'
+ },
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: "https://logs.infra-dev.cdp-int.defra.cloud/_dashboards/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:'2024-02-27T10:29:32.000',to:'2024-02-27T10:31:36.000'))&_a=(columns:!(_source),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:'ecs_task_arn:arn:aws:ecs:eu-west-2:123456789:task%2Finfra-dev-ecs-public%2Ff5cffc31e21149208f38b8ec2b168c50'),sort:!())&_a=(columns:!(log),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:''),sort:!())",
+ value: 'logs.infra-dev'
+ },
+ headers: 'logs'
+ },
+ {
+ classes: 'app-entity-table__cell--owned',
+ entity: {
+ icon: expect.stringContaining('app-tick-icon'),
+ kind: 'link',
+ url: '/test-suites/test-results/infra-dev/0.2.0/cdp-portal-smoke-tests/383547d8-f71c-4e7e-8b03-4ddf09fd84fe/index.html',
+ value: 'Report'
+ },
+ headers: 'results',
+ isCentered: true
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'B. A. Baracus'
+ },
+ headers: 'user'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: '2 minutes'
+ },
+ headers: 'duration'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2024-02-27T10:31:36Z'
+ },
+ headers: 'last-ran'
+ },
+ {
+ entity: {
+ classes: 'app-button--small',
+ kind: 'button',
+ url: '/test-suites/cdp-portal-smoke-tests/383547d8-f71c-4e7e-8b03-4ddf09fd84fe/stop',
+ value: null
+ },
+ headers: 'action'
+ }
+ ]
+ },
+ {
+ cells: [
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: 'https://github.com/DEFRA/cdp-portal-smoke-tests/releases/tag/0.1.0',
+ value: '0.1.0'
+ },
+ headers: 'version'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'Infra Dev'
+ },
+ headers: 'environment'
+ },
+ {
+ entity: {
+ classes: 'govuk-tag--green',
+ kind: 'tag',
+ showLoader: false,
+ value: 'Finished'
+ },
+ headers: 'status'
+ },
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: "https://logs.infra-dev.cdp-int.defra.cloud/_dashboards/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:'2024-02-26T16:38:28.000',to:'2024-02-26T16:40:34.000'))&_a=(columns:!(_source),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:'ecs_task_arn:arn:aws:ecs:eu-west-2:123456789:task%2Finfra-dev-ecs-public%2F7e4c74aa41e44a0399bef08711563715'),sort:!())&_a=(columns:!(log),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:''),sort:!())",
+ value: 'logs.infra-dev'
+ },
+ headers: 'logs'
+ },
+ {
+ classes: 'app-entity-table__cell--owned',
+ entity: {
+ icon: expect.stringContaining('app-tick-icon'),
+ kind: 'link',
+ url: '/test-suites/test-results/infra-dev/0.1.0/cdp-portal-smoke-tests/dc34cdaf-1f51-44cf-8c63-e9b6800d9609/index.html',
+ value: 'Report'
+ },
+ headers: 'results',
+ isCentered: true
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'B. A. Baracus'
+ },
+ headers: 'user'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: '2 minutes'
+ },
+ headers: 'duration'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2024-02-26T16:40:34Z'
+ },
+ headers: 'last-ran'
+ },
+ {
+ entity: {
+ classes: 'app-button--small',
+ kind: 'button',
+ url: '/test-suites/cdp-portal-smoke-tests/dc34cdaf-1f51-44cf-8c63-e9b6800d9609/stop',
+ value: null
+ },
+ headers: 'action'
+ }
+ ]
+ }
])
})
})
@@ -110,104 +172,166 @@ describe('#transformTestSuiteRunResults', () => {
describe('When a user can run the tests', () => {
test('Should provide expected test suite run transformation with action buttons', () => {
expect(
- testSuiteRunsFixture.map((t) => transformTestSuiteRunResults(t, true))
+ testSuiteRunsFixture.map((t) => testSuiteRunResults(t, true))
).toEqual([
- [
- {
- kind: 'link',
- newWindow: true,
- url: 'https://github.com/DEFRA/cdp-portal-smoke-tests/releases/tag/0.2.0',
- value: '0.2.0'
- },
- {
- kind: 'text',
- value: 'Infra Dev'
- },
- {
- classes: 'govuk-tag--light-blue',
- kind: 'tag',
- showLoader: true,
- value: 'in-progress'
- },
- {
- kind: 'link',
- newWindow: true,
- url: "https://logs.infra-dev.cdp-int.defra.cloud/_dashboards/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:'2024-02-27T10:29:32.000',to:'2024-02-27T10:31:36.000'))&_a=(columns:!(_source),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:'ecs_task_arn:arn:aws:ecs:eu-west-2:123456789:task%2Finfra-dev-ecs-public%2Ff5cffc31e21149208f38b8ec2b168c50'),sort:!())&_a=(columns:!(log),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:''),sort:!())",
- value: 'logs.infra-dev'
- },
- {
- icon: expect.stringContaining('Test passed'),
- kind: 'link',
- url: '/test-suites/test-results/infra-dev/0.2.0/cdp-portal-smoke-tests/383547d8-f71c-4e7e-8b03-4ddf09fd84fe/index.html',
- value: 'Report'
- },
- {
- kind: 'text',
- value: 'B. A. Baracus'
- },
- {
- kind: 'text',
- value: '2 minutes'
- },
- {
- kind: 'date',
- value: '2024-02-27T10:31:36Z'
- },
- {
- classes: 'app-button--small',
- kind: 'button',
- value: 'Stop',
- url: '/test-suites/cdp-portal-smoke-tests/383547d8-f71c-4e7e-8b03-4ddf09fd84fe/stop'
- }
- ],
- [
- {
- kind: 'link',
- newWindow: true,
- url: 'https://github.com/DEFRA/cdp-portal-smoke-tests/releases/tag/0.1.0',
- value: '0.1.0'
- },
- {
- kind: 'text',
- value: 'Infra Dev'
- },
- {
- classes: 'govuk-tag--green',
- kind: 'tag',
- showLoader: false,
- value: 'finished'
- },
- {
- kind: 'link',
- newWindow: true,
- url: "https://logs.infra-dev.cdp-int.defra.cloud/_dashboards/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:'2024-02-26T16:38:28.000',to:'2024-02-26T16:40:34.000'))&_a=(columns:!(_source),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:'ecs_task_arn:arn:aws:ecs:eu-west-2:123456789:task%2Finfra-dev-ecs-public%2F7e4c74aa41e44a0399bef08711563715'),sort:!())&_a=(columns:!(log),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:''),sort:!())",
- value: 'logs.infra-dev'
- },
- {
- icon: expect.stringContaining('Test passed'),
- kind: 'link',
- url: '/test-suites/test-results/infra-dev/0.1.0/cdp-portal-smoke-tests/dc34cdaf-1f51-44cf-8c63-e9b6800d9609/index.html',
- value: 'Report'
- },
- {
- kind: 'text',
- value: 'B. A. Baracus'
- },
- {
- kind: 'text',
- value: '2 minutes'
- },
- {
- kind: 'date',
- value: '2024-02-26T16:40:34Z'
- },
- {
- kind: 'button',
- classes: 'app-button--small',
- url: '/test-suites/cdp-portal-smoke-tests/dc34cdaf-1f51-44cf-8c63-e9b6800d9609/stop',
- value: null
- }
- ]
+ {
+ cells: [
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: 'https://github.com/DEFRA/cdp-portal-smoke-tests/releases/tag/0.2.0',
+ value: '0.2.0'
+ },
+ headers: 'version'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'Infra Dev'
+ },
+ headers: 'environment'
+ },
+ {
+ entity: {
+ classes: 'govuk-tag--light-blue',
+ kind: 'tag',
+ showLoader: true,
+ value: 'In-progress'
+ },
+ headers: 'status'
+ },
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: "https://logs.infra-dev.cdp-int.defra.cloud/_dashboards/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:'2024-02-27T10:29:32.000',to:'2024-02-27T10:31:36.000'))&_a=(columns:!(_source),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:'ecs_task_arn:arn:aws:ecs:eu-west-2:123456789:task%2Finfra-dev-ecs-public%2Ff5cffc31e21149208f38b8ec2b168c50'),sort:!())&_a=(columns:!(log),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:''),sort:!())",
+ value: 'logs.infra-dev'
+ },
+ headers: 'logs'
+ },
+ {
+ classes: 'app-entity-table__cell--owned',
+ entity: {
+ icon: expect.stringContaining('app-tick-icon'),
+ kind: 'link',
+ url: '/test-suites/test-results/infra-dev/0.2.0/cdp-portal-smoke-tests/383547d8-f71c-4e7e-8b03-4ddf09fd84fe/index.html',
+ value: 'Report'
+ },
+ headers: 'results',
+ isCentered: true
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'B. A. Baracus'
+ },
+ headers: 'user'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: '2 minutes'
+ },
+ headers: 'duration'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2024-02-27T10:31:36Z'
+ },
+ headers: 'last-ran'
+ },
+ {
+ entity: {
+ classes: 'app-button--small',
+ kind: 'button',
+ url: '/test-suites/cdp-portal-smoke-tests/383547d8-f71c-4e7e-8b03-4ddf09fd84fe/stop',
+ value: 'Stop'
+ },
+ headers: 'action'
+ }
+ ]
+ },
+ {
+ cells: [
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: 'https://github.com/DEFRA/cdp-portal-smoke-tests/releases/tag/0.1.0',
+ value: '0.1.0'
+ },
+ headers: 'version'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'Infra Dev'
+ },
+ headers: 'environment'
+ },
+ {
+ entity: {
+ classes: 'govuk-tag--green',
+ kind: 'tag',
+ showLoader: false,
+ value: 'Finished'
+ },
+ headers: 'status'
+ },
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: "https://logs.infra-dev.cdp-int.defra.cloud/_dashboards/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:'2024-02-26T16:38:28.000',to:'2024-02-26T16:40:34.000'))&_a=(columns:!(_source),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:'ecs_task_arn:arn:aws:ecs:eu-west-2:123456789:task%2Finfra-dev-ecs-public%2F7e4c74aa41e44a0399bef08711563715'),sort:!())&_a=(columns:!(log),filters:!(),index:c0abdf20-d49c-11ee-9eac-1d3409bea15a,interval:auto,query:(language:kuery,query:''),sort:!())",
+ value: 'logs.infra-dev'
+ },
+ headers: 'logs'
+ },
+ {
+ classes: 'app-entity-table__cell--owned',
+ entity: {
+ icon: expect.stringContaining('app-tick-icon'),
+ kind: 'link',
+ url: '/test-suites/test-results/infra-dev/0.1.0/cdp-portal-smoke-tests/dc34cdaf-1f51-44cf-8c63-e9b6800d9609/index.html',
+ value: 'Report'
+ },
+ headers: 'results',
+ isCentered: true
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'B. A. Baracus'
+ },
+ headers: 'user'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: '2 minutes'
+ },
+ headers: 'duration'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2024-02-26T16:40:34Z'
+ },
+ headers: 'last-ran'
+ },
+ {
+ entity: {
+ classes: 'app-button--small',
+ kind: 'button',
+ url: '/test-suites/cdp-portal-smoke-tests/dc34cdaf-1f51-44cf-8c63-e9b6800d9609/stop',
+ value: null
+ },
+ headers: 'action'
+ }
+ ]
+ }
])
})
})
diff --git a/src/server/test-suites/transformers/test-suite-to-entity-row.js b/src/server/test-suites/transformers/test-suite-to-entity-row.js
index 197e0e9a..c1e4525f 100644
--- a/src/server/test-suites/transformers/test-suite-to-entity-row.js
+++ b/src/server/test-suites/transformers/test-suite-to-entity-row.js
@@ -1,40 +1,96 @@
import { config } from '~/src/config/config.js'
+import {
+ renderComponent,
+ renderIcon
+} from '~/src/server/common/helpers/nunjucks/render-component.js'
-function transformTestSuiteToEntityRow(testSuite) {
- const githubOrg = config.get('githubOrg')
- const teams = testSuite?.teams
- ?.filter((team) => team.teamId)
- ?.map((team) => ({
- kind: 'link',
- value: team.name,
- url: `/teams/${team.teamId}`
- }))
+function testSuiteToEntityRow(isAuthenticated) {
+ return (testSuite) => {
+ const githubOrg = config.get('githubOrg')
- return [
- {
- kind: 'link',
- value: testSuite.serviceName,
- url: `/test-suites/${testSuite.serviceName}`
- },
- {
- kind: 'group',
- value: teams?.length ? teams : null
- },
- {
- kind: 'text',
- value: testSuite.testType
- },
- {
- kind: 'link',
- value: `${githubOrg}/${testSuite.id}`,
- url: `https://github.com/${githubOrg}/${testSuite.id}`,
- newWindow: true
- },
- {
- kind: 'date',
- value: testSuite.lastRun?.taskLastUpdated
+ const icon = testSuite.isOwner
+ ? renderComponent(
+ 'tool-tip',
+ {
+ text: 'Owned Test Suite',
+ classes: 'app-tool-tip--small'
+ },
+ [
+ renderIcon('star-icon', {
+ classes: 'app-icon--tiny'
+ })
+ ]
+ )
+ : ''
+
+ const teams = testSuite?.teams
+ ?.filter((team) => team.teamId)
+ ?.map((team) => ({
+ kind: 'link',
+ value: team.name,
+ url: `/teams/${team.teamId}`
+ }))
+
+ return {
+ cells: [
+ ...(isAuthenticated
+ ? [
+ {
+ headers: 'owner',
+ isCentered: true,
+ classes: 'app-entity-table__cell--owned',
+ entity: { kind: 'html', value: icon }
+ }
+ ]
+ : []),
+ {
+ headers: 'test-suite',
+ entity: {
+ kind: 'link',
+ value: testSuite.serviceName,
+ url: `/test-suites/${testSuite.serviceName}`
+ }
+ },
+ {
+ headers: 'team',
+ entity: {
+ kind: 'group',
+ value: teams?.length ? teams : null
+ }
+ },
+ {
+ headers: 'kind',
+ entity: {
+ kind: 'text',
+ value: testSuite.testType
+ }
+ },
+ {
+ headers: 'github-repository',
+ entity: {
+ kind: 'link',
+ value: `${githubOrg}/${testSuite.id}`,
+ url: `https://github.com/${githubOrg}/${testSuite.id}`,
+ newWindow: true
+ }
+ },
+ {
+ headers: 'last-ran',
+ entity: {
+ kind: 'date',
+ value: testSuite.lastRun?.taskLastUpdated
+ }
+ },
+ {
+ headers: 'created',
+ entity: {
+ kind: 'date',
+ value: testSuite.createdAt
+ }
+ }
+ ]
}
- ]
+ }
}
-export { transformTestSuiteToEntityRow }
+export { testSuiteToEntityRow }
diff --git a/src/server/test-suites/transformers/test-suite-to-entity-row.test.js b/src/server/test-suites/transformers/test-suite-to-entity-row.test.js
index 5c18121d..9215f81c 100644
--- a/src/server/test-suites/transformers/test-suite-to-entity-row.test.js
+++ b/src/server/test-suites/transformers/test-suite-to-entity-row.test.js
@@ -1,41 +1,131 @@
-import { config } from '~/src/config/config.js'
import { testSuiteWithLastRunFixture } from '~/src/__fixtures__/test-suite.js'
-import { transformTestSuiteToEntityRow } from '~/src/server/test-suites/transformers/test-suite-to-entity-row.js'
-
-const githubOrg = config.get('githubOrg')
+import { testSuiteToEntityRow } from '~/src/server/test-suites/transformers/test-suite-to-entity-row.js'
describe('#transformServiceToEntityRow', () => {
- test('Should provide expected service entity row transformation', () => {
- expect(transformTestSuiteToEntityRow(testSuiteWithLastRunFixture)).toEqual([
- {
- kind: 'link',
- url: '/test-suites/cdp-portal-smoke-tests',
- value: 'cdp-portal-smoke-tests'
- },
- {
- kind: 'group',
- value: [
- {
- kind: 'link',
- url: '/teams/aabe63e7-87ef-4beb-a596-c810631fc474',
- value: 'Platform'
+ describe('When authenticated', () => {
+ test('Should provide expected service entity row transformation', () => {
+ expect(testSuiteToEntityRow(true)(testSuiteWithLastRunFixture)).toEqual({
+ cells: [
+ {
+ classes: 'app-entity-table__cell--owned',
+ entity: {
+ kind: 'html',
+ value: ''
+ },
+ headers: 'owner',
+ isCentered: true
+ },
+ {
+ entity: {
+ kind: 'link',
+ url: '/test-suites/cdp-portal-smoke-tests',
+ value: 'cdp-portal-smoke-tests'
+ },
+ headers: 'test-suite'
+ },
+ {
+ entity: {
+ kind: 'group',
+ value: [
+ {
+ kind: 'link',
+ url: '/teams/aabe63e7-87ef-4beb-a596-c810631fc474',
+ value: 'Platform'
+ }
+ ]
+ },
+ headers: 'team'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'Smoke'
+ },
+ headers: 'kind'
+ },
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: 'https://github.com/DEFRA/cdp-portal-smoke-tests',
+ value: 'DEFRA/cdp-portal-smoke-tests'
+ },
+ headers: 'github-repository'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2023-04-12T17:18:48Z'
+ },
+ headers: 'last-ran'
+ },
+ {
+ entity: {
+ kind: 'date'
+ },
+ headers: 'created'
+ }
+ ]
+ })
+ })
+ })
+
+ describe('When not authenticated', () => {
+ test('Should provide expected service entity row transformation', () => {
+ expect(testSuiteToEntityRow(false)(testSuiteWithLastRunFixture)).toEqual({
+ cells: [
+ {
+ entity: {
+ kind: 'link',
+ url: '/test-suites/cdp-portal-smoke-tests',
+ value: 'cdp-portal-smoke-tests'
+ },
+ headers: 'test-suite'
+ },
+ {
+ entity: {
+ kind: 'group',
+ value: [
+ {
+ kind: 'link',
+ url: '/teams/aabe63e7-87ef-4beb-a596-c810631fc474',
+ value: 'Platform'
+ }
+ ]
+ },
+ headers: 'team'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'Smoke'
+ },
+ headers: 'kind'
+ },
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: 'https://github.com/DEFRA/cdp-portal-smoke-tests',
+ value: 'DEFRA/cdp-portal-smoke-tests'
+ },
+ headers: 'github-repository'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2023-04-12T17:18:48Z'
+ },
+ headers: 'last-ran'
+ },
+ {
+ entity: {
+ kind: 'date'
+ },
+ headers: 'created'
}
]
- },
- {
- kind: 'text',
- value: 'Smoke'
- },
- {
- kind: 'link',
- newWindow: true,
- url: `https://github.com/${githubOrg}/cdp-portal-smoke-tests`,
- value: `${githubOrg}/cdp-portal-smoke-tests`
- },
- {
- kind: 'date',
- value: '2023-04-12T17:18:48Z'
- }
- ])
+ })
+ })
})
})
diff --git a/src/server/test-suites/transformers/test-suite-to-summary.js b/src/server/test-suites/transformers/test-suite-to-summary.js
new file mode 100644
index 00000000..63e32ab5
--- /dev/null
+++ b/src/server/test-suites/transformers/test-suite-to-summary.js
@@ -0,0 +1,61 @@
+import { buildLink } from '~/src/server/common/helpers/view/build-link.js'
+import { buildList } from '~/src/server/common/helpers/view/build-list.js'
+import { noValue } from '~/src/server/common/constants/no-value.js'
+import { renderComponent } from '~/src/server/common/helpers/nunjucks/render-component.js'
+
+function transformTestSuiteToSummary(testSuite) {
+ const teams = testSuite?.teams
+ ?.filter((team) => team.teamId)
+ ?.map((team) => buildLink(`/teams/${team.teamId}`, team.name, false))
+
+ const topics = testSuite?.topics?.map((topic) =>
+ renderComponent('tag', {
+ text: topic,
+ url: `https://github.com/search?q=topic%3Acdp+org%3ADEFRA+topic%3A${topic}&type=repositories`,
+ newWindow: true,
+ link: { classes: 'app-link--without-underline' },
+ attributes: { 'data-testid': 'govuk-tag' }
+ }).trim()
+ )
+
+ return {
+ classes: 'app-summary-list govuk-!-margin-bottom-8',
+ attributes: {
+ 'data-testid': 'govuk-summary-list'
+ },
+ rows: [
+ {
+ key: { text: `Team${teams?.length > 1 ? 's' : ''}` },
+ value: {
+ html: teams?.length ? buildList(teams) : noValue
+ }
+ },
+ {
+ key: { text: 'Primary Language' },
+ value: { text: testSuite.primaryLanguage ?? noValue }
+ },
+ {
+ key: {
+ text: 'GitHub Repository'
+ },
+ value: {
+ html: buildLink(testSuite.githubUrl)
+ }
+ },
+ {
+ key: { text: 'Topics' },
+ value: {
+ html: topics?.length ? topics.join(' ') : noValue
+ }
+ },
+ {
+ key: { text: 'Created' },
+ value: {
+ html: renderComponent('time', { datetime: testSuite.createdAt })
+ }
+ }
+ ]
+ }
+}
+
+export { transformTestSuiteToSummary }
diff --git a/src/server/test-suites/transformers/test-suite-to-summary.test.js b/src/server/test-suites/transformers/test-suite-to-summary.test.js
new file mode 100644
index 00000000..c47f697f
--- /dev/null
+++ b/src/server/test-suites/transformers/test-suite-to-summary.test.js
@@ -0,0 +1,65 @@
+import { testSuiteFixture } from '~/src/__fixtures__/test-suite.js'
+import { repositoryDecorator } from '~/src/server/common/helpers/decorators/repository.js'
+import { repositoryFixture } from '~/src/__fixtures__/repository.js'
+import { transformTestSuiteToSummary } from '~/src/server/test-suites/transformers/test-suite-to-summary.js'
+
+describe('#testSuiteToEntityDataList', () => {
+ describe('With a test suite', () => {
+ test('Should provide expected test suite summary transformation', () => {
+ expect(
+ transformTestSuiteToSummary(
+ repositoryDecorator(testSuiteFixture, repositoryFixture.repository)
+ )
+ ).toEqual({
+ attributes: {
+ 'data-testid': 'govuk-summary-list'
+ },
+ classes: 'app-summary-list govuk-!-margin-bottom-8',
+ rows: [
+ {
+ key: {
+ text: 'Team'
+ },
+ value: {
+ html: expect.stringContaining('Platform')
+ }
+ },
+ {
+ key: {
+ text: 'Primary Language'
+ },
+ value: {
+ text: 'JavaScript'
+ }
+ },
+ {
+ key: {
+ text: 'GitHub Repository'
+ },
+ value: {
+ html: expect.stringContaining(
+ 'https://github.com/DEFRA/cdp-portal-smoke-tests'
+ )
+ }
+ },
+ {
+ key: {
+ text: 'Topics'
+ },
+ value: {
+ html: expect.stringContaining('frontend')
+ }
+ },
+ {
+ key: {
+ text: 'Created'
+ },
+ value: {
+ html: expect.stringContaining('Wed 12th Apr 2023 at 17:16')
+ }
+ }
+ ]
+ })
+ })
+ })
+})
diff --git a/src/server/test-suites/views/list.njk b/src/server/test-suites/views/list.njk
index 2f2bb0f0..941e8d9b 100644
--- a/src/server/test-suites/views/list.njk
+++ b/src/server/test-suites/views/list.njk
@@ -1,21 +1,11 @@
{% extends "layouts/page.njk" %}
{% block content %}
- {{ appHeading({
- title: heading,
- caption: "Environment, User Journey and Performance tests."
+ {{ appPageHeading({
+ text: "Test Suites",
+ intro: "User Journey and Performance tests"
}) }}
- {{ appEntityList({
- headings: [
- { text: "Test Suite", size: "large" },
- { text: "Team", size: "medium" },
- { text: "Type", size: "small" },
- { text: "GitHub Repository", size: "massive" },
- { text: "Last Ran", size: "medium" }
- ],
- entityRows: entityRows,
- noResult: "Currently there are no test suites"
- }) }}
+ {{ appEntityTable(tableData) }}
{% endblock %}
diff --git a/src/server/test-suites/views/test-suite.njk b/src/server/test-suites/views/test-suite.njk
index e5f3503f..8f964b15 100644
--- a/src/server/test-suites/views/test-suite.njk
+++ b/src/server/test-suites/views/test-suite.njk
@@ -2,32 +2,30 @@
{% block content %}
- {{ appHeading({
- title: heading,
- caption: "Information about the " + heading + " test-suite."
+ {{ appPageHeading({
+ caption: "Test Suite",
+ text: testSuite.serviceName
}) }}
-
+
-
+
-
About
{{ testSuite.description }}
-
+ {{ govukSummaryList(summaryList) }}
+
-
{% if canRun %}
-
{% call appPanel() %}
{% endcall %}
-
{% endif %}
-
@@ -102,22 +98,7 @@
Results from {{ testSuite.serviceName }} test suite runs.
- {{ appEntityList({
- headings: [
- { text: "Version", size: "tiny" },
- { text: "Environment", size: "small" },
- { text: "Status", size: "small" },
- { text: "Logs", size: "small" },
- { text: "Results", size: "small" },
- { text: "User", size: "large" },
- { text: "Duration", size: "small" },
- { text: "Last Ran", size: "medium" },
- { text: "Action", size: "small"}
- ],
- entityRows: testSuiteRunResults,
- noResult: "Currently there are no test suite run results"
- }) }}
-
+ {{ appEntityTable(tableData) }}
{% endblock %}
@@ -127,14 +108,5 @@
{% endif %}
-
-
-
- {{ appEntityDataList({
- heading: "Details",
- items: entityDataList
- }) }}
-
-
{% endblock %}
diff --git a/src/server/utilities/controllers/libraries-list-controller.js b/src/server/utilities/controllers/libraries-list-controller.js
index bc142c0a..9be47da7 100644
--- a/src/server/utilities/controllers/libraries-list-controller.js
+++ b/src/server/utilities/controllers/libraries-list-controller.js
@@ -1,20 +1,48 @@
-import { sortBy } from '~/src/server/common/helpers/sort/sort-by.js'
+import { validate as uuidValidate } from 'uuid'
+
import { fetchLibraries } from '~/src/server/utilities/helpers/fetch/fetch-libraries.js'
-import { utilityToEntityRow } from '~/src/server/utilities/transformers/utility-to-entity-row.js'
+import { provideAuthedUser } from '~/src/server/common/helpers/auth/pre/provide-authed-user.js'
+import { buildUtilitiesTableData } from '~/src/server/utilities/helpers/build-utilities-table-data.js'
const librariesListController = {
- handler: async (_request, h) => {
- const { repositories } = await fetchLibraries()
+ options: {
+ pre: [provideAuthedUser]
+ },
+ handler: async (request, h) => {
+ const authedUser = request.pre.authedUser
+ const isAuthenticated = authedUser?.isAuthenticated
+ const userScopeUUIDs = authedUser?.scope.filter(uuidValidate) ?? []
+
+ const { repositories: libraries } = await fetchLibraries()
- const entityRows = repositories
- ?.sort(sortBy('id', 'asc'))
- ?.map(utilityToEntityRow('libraries'))
+ const rows = buildUtilitiesTableData({
+ utilities: libraries,
+ utilityType: 'libraries',
+ isAuthenticated,
+ userScopeUUIDs
+ })
+ const title = 'Libraries'
return h.view('utilities/views/list', {
- pageTitle: 'Libraries',
- heading: 'Libraries',
- entityRows,
- noResult: 'Currently there are no libraries'
+ pageTitle: title,
+ pageHeading: {
+ text: title,
+ intro: 'Microservice and test-suite libraries'
+ },
+ tableData: {
+ headers: [
+ ...(isAuthenticated
+ ? [{ id: 'owner', classes: 'app-entity-table__cell--owned' }]
+ : []),
+ { id: 'utility', text: 'Utility', width: '20' },
+ { id: 'team', text: 'Team', width: '15' },
+ { id: 'language', text: 'Language', width: '10' },
+ { id: 'github-repository', text: 'GitHub Repository', width: '20' },
+ { id: 'created', text: 'Created', width: '30' }
+ ],
+ rows,
+ noResult: 'No libraries found'
+ }
})
}
}
diff --git a/src/server/utilities/controllers/templates-list-controller.js b/src/server/utilities/controllers/templates-list-controller.js
index 37594c53..41bb0a9c 100644
--- a/src/server/utilities/controllers/templates-list-controller.js
+++ b/src/server/utilities/controllers/templates-list-controller.js
@@ -1,20 +1,48 @@
-import { sortBy } from '~/src/server/common/helpers/sort/sort-by.js'
+import { validate as uuidValidate } from 'uuid'
+
import { fetchTemplates } from '~/src/server/utilities/helpers/fetch/fetch-templates.js'
-import { utilityToEntityRow } from '~/src/server/utilities/transformers/utility-to-entity-row.js'
+import { provideAuthedUser } from '~/src/server/common/helpers/auth/pre/provide-authed-user.js'
+import { buildUtilitiesTableData } from '~/src/server/utilities/helpers/build-utilities-table-data.js'
const templatesListController = {
- handler: async (_request, h) => {
- const { repositories } = await fetchTemplates()
+ options: {
+ pre: [provideAuthedUser]
+ },
+ handler: async (request, h) => {
+ const authedUser = request.pre.authedUser
+ const isAuthenticated = authedUser?.isAuthenticated
+ const userScopeUUIDs = authedUser?.scope.filter(uuidValidate) ?? []
+
+ const { repositories: templates } = await fetchTemplates()
- const entityRows = repositories
- ?.sort(sortBy('id', 'asc'))
- ?.map(utilityToEntityRow('templates'))
+ const rows = buildUtilitiesTableData({
+ utilities: templates,
+ utilityType: 'templates',
+ isAuthenticated,
+ userScopeUUIDs
+ })
+ const title = 'Templates'
return h.view('utilities/views/list', {
- pageTitle: 'Templates',
- heading: 'Templates',
- entityRows,
- noResult: 'Currently there are no templates'
+ pageTitle: title,
+ pageHeading: {
+ text: title,
+ intro: 'Microservice and test-suite templates'
+ },
+ tableData: {
+ headers: [
+ ...(isAuthenticated
+ ? [{ id: 'owner', classes: 'app-entity-table__cell--owned' }]
+ : []),
+ { id: 'utility', text: 'Utility', width: '20' },
+ { id: 'team', text: 'Team', width: '15' },
+ { id: 'language', text: 'Language', width: '10' },
+ { id: 'github-repository', text: 'GitHub Repository', width: '20' },
+ { id: 'created', text: 'Created', width: '30' }
+ ],
+ rows,
+ noResult: 'No templates found'
+ }
})
}
}
diff --git a/src/server/utilities/helpers/build-utilities-table-data.js b/src/server/utilities/helpers/build-utilities-table-data.js
new file mode 100644
index 00000000..5f565fe2
--- /dev/null
+++ b/src/server/utilities/helpers/build-utilities-table-data.js
@@ -0,0 +1,26 @@
+import { utilityToEntityRow } from '~/src/server/utilities/transformers/utility-to-entity-row.js'
+import { sortByOwner } from '~/src/server/common/helpers/sort/sort-by-owner.js'
+
+function buildUtilitiesTableData({
+ utilities,
+ utilityType,
+ isAuthenticated,
+ userScopeUUIDs
+}) {
+ const rowDecorator = utilityToEntityRow(utilityType, isAuthenticated)
+ const ownerSorter = sortByOwner('id')
+
+ const rows = utilities
+ .map((utility) => ({
+ ...utility,
+ isOwner: utility.teams?.some((team) =>
+ userScopeUUIDs.includes(team.teamId)
+ )
+ }))
+ .toSorted(ownerSorter)
+ .map(rowDecorator)
+
+ return rows
+}
+
+export { buildUtilitiesTableData }
diff --git a/src/server/utilities/transformers/utility-to-entity-row.js b/src/server/utilities/transformers/utility-to-entity-row.js
index 1d098771..c800f488 100644
--- a/src/server/utilities/transformers/utility-to-entity-row.js
+++ b/src/server/utilities/transformers/utility-to-entity-row.js
@@ -1,35 +1,76 @@
import { removeUrlParts } from '~/src/server/common/helpers/remove-url-parts.js'
+import {
+ renderComponent,
+ renderIcon
+} from '~/src/server/common/helpers/nunjucks/render-component.js'
-function utilityToEntityRow(utilityType) {
- return (utility) => [
- {
- kind: 'link',
- value: utility.id,
- url: `/utilities/${utilityType}/${utility.id}`
- },
- {
- kind: 'group',
- value: utility?.teams?.map((team) => ({
- kind: 'link',
- value: team.name,
- url: `/teams/${team.teamId}`
- }))
- },
- {
- kind: 'text',
- value: utility.primaryLanguage
- },
- {
- kind: 'link',
- value: removeUrlParts(utility.url),
- url: utility.url,
- newWindow: true
- },
- {
- kind: 'date',
- value: utility.createdAt
+function utilityToEntityRow(utilityType, isAuthenticated) {
+ return (utility) => {
+ const icon = utility.isOwner
+ ? renderComponent(
+ 'tool-tip',
+ { text: 'Owned Utility', classes: 'app-tool-tip--small' },
+ [renderIcon('star-icon', { classes: 'app-icon--tiny' })]
+ )
+ : ''
+
+ return {
+ cells: [
+ ...(isAuthenticated
+ ? [
+ {
+ headers: 'owner',
+ isCentered: true,
+ classes: 'app-entity-table__cell--owned',
+ entity: { kind: 'html', value: icon }
+ }
+ ]
+ : []),
+ {
+ headers: 'service',
+ entity: {
+ kind: 'link',
+ value: utility.id,
+ url: `/utilities/${utilityType}/${utility.id}`
+ }
+ },
+ {
+ headers: 'service',
+ entity: {
+ kind: 'group',
+ value: utility?.teams?.map((team) => ({
+ kind: 'link',
+ value: team.name,
+ url: `/teams/${team.teamId}`
+ }))
+ }
+ },
+ {
+ headers: 'service',
+ entity: {
+ kind: 'text',
+ value: utility.primaryLanguage
+ }
+ },
+ {
+ headers: 'service',
+ entity: {
+ kind: 'link',
+ value: removeUrlParts(utility.url),
+ url: utility.url,
+ newWindow: true
+ }
+ },
+ {
+ headers: 'service',
+ entity: {
+ kind: 'date',
+ value: utility.createdAt
+ }
+ }
+ ]
}
- ]
+ }
}
export { utilityToEntityRow }
diff --git a/src/server/utilities/transformers/utility-to-entity-row.test.js b/src/server/utilities/transformers/utility-to-entity-row.test.js
index a464b1c6..599fe215 100644
--- a/src/server/utilities/transformers/utility-to-entity-row.test.js
+++ b/src/server/utilities/transformers/utility-to-entity-row.test.js
@@ -1,43 +1,129 @@
-import { config } from '~/src/config/config.js'
import { utilityToEntityRow } from '~/src/server/utilities/transformers/utility-to-entity-row.js'
import { templatesFixture } from '~/src/__fixtures__/templates.js'
-const githubOrg = config.get('githubOrg')
-
describe('#utilityToEntityRow', () => {
- test('Should provide expected "templates" transformation', () => {
- expect(
- utilityToEntityRow('templates')(templatesFixture.templates.at(0))
- ).toEqual([
- {
- kind: 'link',
- url: '/utilities/templates/cdp-node-frontend-template',
- value: 'cdp-node-frontend-template'
- },
- {
- kind: 'group',
- value: [
- {
- kind: 'link',
- url: '/teams/aabe63e7-87ef-4beb-a596-c810631fc474',
- value: 'Platform'
+ describe('When authenticated', () => {
+ test('Should provide expected "templates" transformation', () => {
+ expect(
+ utilityToEntityRow(
+ 'templates',
+ true
+ )(templatesFixture.repositories.at(0))
+ ).toEqual({
+ cells: [
+ {
+ classes: 'app-entity-table__cell--owned',
+ entity: {
+ kind: 'html',
+ value: ''
+ },
+ headers: 'owner',
+ isCentered: true
+ },
+ {
+ entity: {
+ kind: 'link',
+ url: '/utilities/templates/cdp-dotnet-backend-template',
+ value: 'cdp-dotnet-backend-template'
+ },
+ headers: 'service'
+ },
+ {
+ entity: {
+ kind: 'group',
+ value: [
+ {
+ kind: 'link',
+ url: '/teams/aabe63e7-87ef-4beb-a596-c810631fc474',
+ value: 'Platform'
+ }
+ ]
+ },
+ headers: 'service'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'C#'
+ },
+ headers: 'service'
+ },
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: 'https://github.com/DEFRA/cdp-dotnet-backend-template',
+ value: 'DEFRA/cdp-dotnet-backend-template'
+ },
+ headers: 'service'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2023-08-24T07:08:56+00:00'
+ },
+ headers: 'service'
+ }
+ ]
+ })
+ })
+ })
+
+ describe('When not authenticated', () => {
+ test('Should provide expected "templates" transformation', () => {
+ expect(
+ utilityToEntityRow(
+ 'templates',
+ false
+ )(templatesFixture.repositories.at(0))
+ ).toEqual({
+ cells: [
+ {
+ entity: {
+ kind: 'link',
+ url: '/utilities/templates/cdp-dotnet-backend-template',
+ value: 'cdp-dotnet-backend-template'
+ },
+ headers: 'service'
+ },
+ {
+ entity: {
+ kind: 'group',
+ value: [
+ {
+ kind: 'link',
+ url: '/teams/aabe63e7-87ef-4beb-a596-c810631fc474',
+ value: 'Platform'
+ }
+ ]
+ },
+ headers: 'service'
+ },
+ {
+ entity: {
+ kind: 'text',
+ value: 'C#'
+ },
+ headers: 'service'
+ },
+ {
+ entity: {
+ kind: 'link',
+ newWindow: true,
+ url: 'https://github.com/DEFRA/cdp-dotnet-backend-template',
+ value: 'DEFRA/cdp-dotnet-backend-template'
+ },
+ headers: 'service'
+ },
+ {
+ entity: {
+ kind: 'date',
+ value: '2023-08-24T07:08:56+00:00'
+ },
+ headers: 'service'
}
]
- },
- {
- kind: 'text',
- value: 'JavaScript'
- },
- {
- kind: 'link',
- newWindow: true,
- url: `https://github.com/${githubOrg}/cdp-node-frontend-template`,
- value: `${githubOrg}/cdp-node-frontend-template`
- },
- {
- kind: 'date',
- value: '2023-04-26T15:27:09+00:00'
- }
- ])
+ })
+ })
})
})
diff --git a/src/server/utilities/views/list.njk b/src/server/utilities/views/list.njk
index d4d52edf..bae6e688 100644
--- a/src/server/utilities/views/list.njk
+++ b/src/server/utilities/views/list.njk
@@ -3,20 +3,12 @@
{% block content %}
{% call appSplitPane() %}
{{ appPageHeading({
- text: heading
+ text: pageHeading.text,
+ intro: pageHeading.intro
}) }}
- {{ appEntityList({
- headings: [
- { text: "Item", size: "large" },
- { text: "Team", size: "medium" },
- { text: "Language", size: "small" },
- { text: "GitHub Repository", size: "massive" },
- { text: "Created", size: "medium" }
- ],
- entityRows: entityRows,
- noResult: noResult
- }) }}
+ {{ appEntityTable(tableData) }}
+
{% endcall %}
{% endblock %}
|