Skip to content

Commit

Permalink
feat: 🚸 rework project selection
Browse files Browse the repository at this point in the history
  • Loading branch information
ArnaudTA committed Oct 6, 2024
1 parent a78d097 commit 5fac6f1
Show file tree
Hide file tree
Showing 38 changed files with 762 additions and 482 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/cache.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ on:

jobs:
cleanup-cache:
name: Delete gituhb cache
name: Delete github cache
runs-on: ubuntu-latest
steps:
- name: Check out code
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ jobs:
BROWSERS: "${{ github.base_ref == 'main' && 'chrome,firefox' || 'firefox' }}"

build:

uses: ./.github/workflows/build.yml
needs:
- expose-vars
Expand Down
25 changes: 20 additions & 5 deletions apps/client/cypress/components/specs/repo-form.ct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ describe('RepoForm.vue', () => {

const randomDbSetup = createRandomDbSetup({})
const projectStore = useProjectStore()
projectStore.selectedProject = randomDbSetup.project
projectStore.myProjectsById = {
[randomDbSetup.project.id]: randomDbSetup.project.id,
}
projectStore.setSelectedProject(randomDbSetup.project.id)

cy.mount(RepoForm, { props })

Expand Down Expand Up @@ -95,7 +98,10 @@ describe('RepoForm.vue', () => {

const randomDbSetup = createRandomDbSetup({})
const projectStore = useProjectStore()
projectStore.selectedProject = randomDbSetup.project
projectStore.myProjectsById = {
[randomDbSetup.project.id]: randomDbSetup.project.id,
}
projectStore.setSelectedProject(randomDbSetup.project.id)

cy.mount(RepoForm, { props })

Expand Down Expand Up @@ -185,7 +191,10 @@ describe('RepoForm.vue', () => {

const randomDbSetup = createRandomDbSetup({})
const projectStore = useProjectStore()
projectStore.selectedProject = randomDbSetup.project
projectStore.myProjectsById = {
[randomDbSetup.project.id]: randomDbSetup.project.id,
}
projectStore.setSelectedProject(randomDbSetup.project.id)

cy.mount(RepoForm, { props })

Expand Down Expand Up @@ -230,7 +239,10 @@ describe('RepoForm.vue', () => {

const randomDbSetup = createRandomDbSetup({})
const projectStore = useProjectStore()
projectStore.selectedProject = randomDbSetup.project
projectStore.myProjectsById = {
[randomDbSetup.project.id]: randomDbSetup.project.id,
}
projectStore.setSelectedProject(randomDbSetup.project.id)

cy.mount(RepoForm, { props })

Expand Down Expand Up @@ -269,7 +281,10 @@ describe('RepoForm.vue', () => {

const randomDbSetup = createRandomDbSetup({})
const projectStore = useProjectStore()
projectStore.selectedProject = randomDbSetup.project
projectStore.myProjectsById = {
[randomDbSetup.project.id]: randomDbSetup.project.id,
}
projectStore.setSelectedProject(randomDbSetup.project.id)

cy.mount(RepoForm, { props })

Expand Down
36 changes: 19 additions & 17 deletions apps/client/cypress/components/specs/services-config.ct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ import ServicesConfig from '@/components/ServicesConfig.vue'

const argoto = { to: 'https://argocd.domain.com/applications?showFavorites=false&proj=&sync=&health=&namespace=&cluster=&labels=&search=org-project', name: '' }
const gitlabto = { to: 'https://gitlab.domain.com/forge-mi/projects/org/project', name: '' }
const services = [{ imgSrc: '/img/argocd.svg', title: 'ArgoCD', name: 'argocd', urls: [argoto, argoto, argoto], manifest: {} }, { imgSrc: '/img/gitlab.svg', title: 'Gitlab', name: 'gitlab', urls: [gitlabto, gitlabto], manifest: {} }, { imgSrc: '/img/harbor.svg', title: 'Harbor', name: 'registry', urls: [{ to: 'https://harbor.domain.com/harbor/projects/254', name: '' }], manifest: { global: [{ permissions: { admin: { read: true, write: true }, user: { read: true, write: false } }, key: 'publish-ro-robot-by-default', kind: 'switch', title: 'Publier le robot RO par défaut', value: 'default', initialValue: 'disabled' }], project: [{ permissions: { admin: { read: true, write: true }, user: { read: true, write: false } }, key: 'view-robot', kind: 'switch', title: 'Publier le robot', initialValue: 'disabled', value: 'default', description: 'Autoriser un robot de lecture sur le projet' }] } }, { imgSrc: '/img/sonarqube.svg', title: 'SonarQube', name: 'sonarqube', urls: [], manifest: {} }]
const services = [
{ imgSrc: '/img/argocd.svg', title: 'ArgoCD', name: 'argocd', urls: [argoto, argoto, argoto], manifest: {} },
{ imgSrc: '/img/gitlab.svg', title: 'Gitlab', name: 'gitlab', urls: [gitlabto, gitlabto], manifest: {} },
{ imgSrc: '/img/harbor.svg', title: 'Harbor', name: 'registry', urls: [{ to: 'https://harbor.domain.com/harbor/projects/254', name: '' }], manifest: { global: [{ permissions: { admin: { read: true, write: true }, user: { read: true, write: false } }, key: 'publish-ro-robot-by-default', kind: 'switch', title: 'Publier le robot RO par défaut', value: 'default', initialValue: 'disabled' }], project: [{ permissions: { admin: { read: true, write: true }, user: { read: true, write: false } }, key: 'view-robot', kind: 'switch', title: 'Publier le robot', initialValue: 'disabled', value: 'default', description: 'Autoriser un robot de lecture sur le projet' }] } },
{ imgSrc: '/img/sonarqube.svg', title: 'SonarQube', name: 'sonarqube', urls: [], manifest: {} },
]

const urlsLength = services.reduce((length, service) => length + service.urls.length, 0)

describe('Service Configuration Component', () => {
it('Affiche correctement les services et leurs configurations', () => {
Expand All @@ -18,18 +25,14 @@ describe('Service Configuration Component', () => {
displayGlobal: true,
},
})
// Vérifie que les services sont correctement affichés
cy.getByDataTestid('service-argocd').should('exist')

// Vérifie que les boutons de lien sont présents et fonctionnent
cy.getByDataTestid('service-argocd').find('a').should('have.length', 5)
cy.getByDataTestid('service-argocd').find('button').first().click() // Simule un clic sur le premier lien
// Vérifie que les services sont correctement affichés
cy.getByDataTestid('services-urls').find('a').should('have.length', urlsLength)

// Verifies qu'il n'y ait que 2 bouton "lien" si 2 to
cy.getByDataTestid('service-gitlab').find('a').should('have.length', 2)
cy.getByDataTestid('service-config-registry').should('exist')

// Verifies qu'il n'y ait pas de boutons "lien"
cy.getByDataTestid('service-sonarqube').find('a').should('not.exist')
// Vérifie que les boutons de lien sont présents et fonctionnent
cy.getByDataTestid('service-config-registry').click() // Simule un clic sur le premier lien

// Vérifie que les boutons de rechargement sont présents
cy.getByDataTestid('reloadBtn').should('exist')
Expand All @@ -44,12 +47,11 @@ describe('Service Configuration Component', () => {
},
})
// Simule un clic sur le bouton d'extension
cy.getByDataTestid('service-registry').within(() => {
cy.getByDataTestid('additional-config').should('not.be.visible')
cy.getByDataTestid('dropdown-button').click()
cy.getByDataTestid('additional-config').should('be.visible')
cy.getByDataTestid('dropdown-button').click()
cy.getByDataTestid('additional-config').should('not.be.visible')
})
cy.getByDataTestid('service-config-registry')
.click()
cy.getByDataTestid('service-project-config-registry')
.should('exist')
cy.getByDataTestid('service-project-config-registry')
.should('exist')
})
})
13 changes: 8 additions & 5 deletions apps/client/cypress/components/specs/team-ct.ct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import '@gouvfr/dsfr/dist/dsfr.min.css'
import '@gouvfr/dsfr/dist/utility/icons/icons.min.css'
import '@gouvfr/dsfr/dist/utility/utility.main.min.css'
import '@/main.css'
import { createRandomDbSetup, getRandomUser } from '@cpn-console/test-utils'
import type { ProjectV2 } from '@cpn-console/shared'
import { faker } from '@faker-js/faker'
import TeamCt from '@/components/TeamCt.vue'
import { useProjectStore } from '@/stores/project.js'
import { useUsersStore } from '@/stores/users.js'
import { useUserStore } from '@/stores/user.js'

const ownerId = faker.string.uuid()
const props: {
Expand Down Expand Up @@ -87,10 +87,11 @@ describe('TeamCt.vue', () => {
})
it('Should mount a TeamCt for user', () => {
useProjectStore()
const { project } = createRandomDbSetup({ nbUsers: 4 })
const newUser = getRandomUser()
const userStore = useUserStore()
// devrait tester que l'on peut toujours quitter un projet
userStore.userProfile = { id: props.project.members[0].id }

cy.intercept('GET', `api/v1/projects/${project.id}/users/match?letters=*`, { body: [newUser] })
// cy.intercept('GET', `api/v1/projects/${project.id}/users/match?letters=*`, { body: [newUser] })

cy.mount(TeamCt, { props: { ...props, canTransfer: false, canManage: false } })

Expand All @@ -101,7 +102,9 @@ describe('TeamCt.vue', () => {
cy.get('tbody > tr')
.should('have.length', props.project.members.length + 1) // +1 cause owner is not a member
cy.get('thead > tr > th')
.should('have.length', 3)
.should('have.length', 4)
// devrait tester que l'on peut toujours quitter un projet
// cy.get('.fr-fi-close-line').should('have.length', 1)
})
cy.getByDataTestid('showTransferProjectBtn')
.should('not.exist')
Expand Down
27 changes: 18 additions & 9 deletions apps/client/cypress/e2e/specs/01-logs.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ describe('Create Project', () => {
})
cy.getByDataTestid('replayHooksBtn')
.click()
cy.wait('@listLogs')
cy.getByDataTestid('displayLogsPanel')
.should('be.visible')
.within(() => {
Expand All @@ -35,16 +36,17 @@ describe('Create Project', () => {
cy.getByDataTestid('menuMyProjects').click()
.url().should('contain', '/projects')
cy.getByDataTestid('displayLogsPanel')
.should('not.be.visible')
.should('not.exist')
})

it('Should handle display project logs as manager or memebr of project', () => {
it.only('Should handle display project logs as manager or memebr of project', () => {
cy.kcLogin('tcolin')
cy.intercept('GET', '/api/v1/logs?*').as('listLogs')

// as owner
cy.goToProjects()
cy.getByDataTestid(`projectTile-${betaapp.name}`).click()
cy.wait('@listLogs')
cy.getByDataTestid('displayLogsPanel')
.should('not.be.visible')
cy.getByDataTestid('displayLogsBtn')
Expand All @@ -63,17 +65,24 @@ describe('Create Project', () => {
})

// as member
cy.getByDataTestid('menuMyProjects').click()
.url().should('contain', '/projects')

cy.goToProjects()
cy.getByDataTestid(`projectTile-candilib`).click()
cy.wait('@listLogs')
cy.getByDataTestid('displayLogsPanel')
.should('not.exist')
.should('not.be.visible')
cy.getByDataTestid('displayLogsBtn')
.should('not.exist')
.should('be.visible')
.click()
cy.getByDataTestid('displayLogsPanel')
.should('be.visible')
.within(() => {
cy.get('span').should('contain', '0 - 0 sur 0')
})
cy.getByDataTestid('menuRepos').click()
cy.getByDataTestid('displayLogsBtn')
.should('not.exist')
cy.getByDataTestid('displayLogsPanel')
.should('be.visible')
.within(() => {
cy.get('span').should('contain', '0 - 0 sur 0')
})
})
})
3 changes: 2 additions & 1 deletion apps/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
"pinia": "^2.1.7",
"vue": "^3.4.38",
"vue-router": "^4.4.5",
"vue3-json-viewer": "^2.2.2"
"vue3-json-viewer": "^2.2.2",
"xbytes": "^1.9.1"
},
"optionalDependencies": {
"@cypress/vue": "^6.0.1",
Expand Down
15 changes: 14 additions & 1 deletion apps/client/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ import { swaggerUiPath } from '@cpn-console/shared'
import { getKeycloak } from './utils/keycloak/keycloak.js'
import { useSnackbarStore } from './stores/snackbar.js'
import { useSystemSettingsStore } from './stores/system-settings.js'
import { useProjectStore } from './stores/project.js'
import { useUserStore } from './stores/user.js'
import { useServiceStore } from '@/stores/services-monitor.js'
const keycloak = getKeycloak()
const snackbarStore = useSnackbarStore()
const systemStore = useSystemSettingsStore()
const projectStore = useProjectStore()
const userStore = useUserStore()
const isLoggedIn = ref<boolean | undefined>(keycloak.authenticated)
Expand Down Expand Up @@ -35,6 +39,9 @@ const serviceStore = useServiceStore()
onBeforeMount(() => {
serviceStore.startHealthPolling()
serviceStore.checkServicesHealth()
if (userStore.isLoggedIn) {
projectStore.getMyProjects()
}
})
</script>

Expand All @@ -57,12 +64,14 @@ onBeforeMount(() => {
<router-view />
</div>
<DsoSnackbar />
<SelectProject
class="max-lg:hidden"
/>
</div>

<DsfrFooter
class="dso-footer"
a11y-compliance="partiellement conforme"
:logo-text="['Ministère', 'de l’Intérieur', 'et des Outre-Mer']"
:mandatory-links="[]"
>
<template #description>
Expand Down Expand Up @@ -92,4 +101,8 @@ onBeforeMount(() => {
.fr-container {
max-width: 100%;
}
.fr-header__logo {
display: none;
}
</style>
65 changes: 65 additions & 0 deletions apps/client/src/components/ConsumptionPanel.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<script lang="ts" setup>
import type { ProjectV2 } from '@cpn-console/shared'
import xbytes from 'xbytes'
import { computed, onBeforeMount } from 'vue'
import { useProjectStore } from '../stores/project.js'
import { type Consumption, listQuotasToConsumption } from '../utils/func.js'
import { useQuotaStore } from '../stores/quota.js'
const props = defineProps<{
ids: ProjectV2['id'][]
}>()
const projectStore = useProjectStore()
const quotaStore = useQuotaStore()
const consumption = computed<Consumption>(() => {
if (props.ids) {
const projects = props.ids.map(id => projectStore.myProjectsById[id] ?? projectStore.projectsById[id])
const quotas = projects.map(project => project.environments.map(env => quotaStore.quotasById[env.quotaId]))
.flat()
return listQuotasToConsumption(quotas)
}
return {
cpu: 0,
memory: 0,
}
})
onBeforeMount(() => {
quotaStore.getAllQuotas()
})
</script>

<template>
<div
id="consumption-panel"
data-testid="consumptionPanel"
class="grid grid-cols-1 content-between max-w-40 pl-2 p-1 place-items-end gap-2"
>
<DsfrBadge
v-if="props.ids.length > 1"
:label="`${props.ids.length} Projets`"
no-icon
type=""
/>
<DsfrBadge
v-if="consumption.cpu != null"
:label="`${consumption.cpu} CPU`"
no-icon
type=""
/>
<DsfrBadge
v-if="consumption.memory != null"
:label="`${xbytes(consumption.memory, { iec: true })} RAM`"
no-icon
type=""
/>
</div>
</template>

<style>
.fr-callout#consumption-panel {
margin: 0 !important;
margin-bottom: 0 !important;
}
</style>
8 changes: 7 additions & 1 deletion apps/client/src/components/LogsViewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ async function showLogs(index: number) {
:step="step"
@set-page="showLogs($event)"
/>
<div
v-if="!logs.length"
class="text-center mt-2 w-full"
>
Aucun événement à afficher
</div>
<div
v-for="log in logs"
:key="log.id"
Expand All @@ -126,7 +132,7 @@ async function showLogs(index: number) {
class="flex gap-2"
>
<DsfrBadge
v-if="log?.data?.totalExecutionTime"
v-if="typeof log?.data?.totalExecutionTime !== 'undefined'"
:label="`${log.data.totalExecutionTime} ms`"
no-icon
/>
Expand Down
Loading

0 comments on commit 5fac6f1

Please sign in to comment.