diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..3c3629e64 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +node_modules diff --git a/CHANGELOG.md b/CHANGELOG.md index 58b68b7fa..10b7c73f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,41 @@ +# Version 25.08 - 2025-03-04 + +### Added 🆕 + +- feat: add order for table (origin/8681_ticketAdvance_updates) by:Javier Segarra +- feat: detect when is descriptor proxy by:Javier Segarra +- feat: refs #7356 update CrudModel by:Javier Segarra +- feat: refs #8242 remove teleport by:Javier Segarra +- feat: refs #8242 use stateStore by:Javier Segarra +- fix: fixed negative bases style by:Jon +- fix: fixed style when clicking on icons by:Jon +- refactor: refs #6897 remove debug logs and unused style (origin/6897-fixSomeCaus) by:pablone +- style: refs #7356 eslint format by:Javier Segarra + +### Changed 📦 + +- perf: refs #7356 minor changes (origin/7356_ticketService) by:Javier Segarra +- refactor: refs #6897 remove debug logs and unused style (origin/6897-fixSomeCaus) by:pablone +- refactor: refs #6897 update component props and attributes for consistency and improved functionality (origin/6897-fixMinorIssues) by:pablone +- refactor: refs #6897 update component props and improve UI handling in Entry pages by:pablone +- refactor: refs #6897 update VnTable components for improved value handling and UI adjustments (origin/6897-minorFixes) by:pablone +- refactor: refs #8697 simplify date handling in ItemDiary component by:pablone + +### Fixed 🛠️ + +- fix: add datakey by:Javier Segarra +- fix: fixed account descriptor menu and created e2e by:Jon +- fix: fixed negative bases style by:Jon +- fix: fixed style when clicking on icons by:Jon +- fix: refs #6553 workerBusiness (origin/6553-fixWorkerBusinessV2) by:carlossa +- fix: refs #6553 workerBusiness v3 by:carlossa +- fix: refs #6897 prevent default event behavior in autocompleteExpense function by:pablone +- fix: refs #7356 chaining params by:Javier Segarra +- fix: refs #7356 ticketService by:Javier Segarra +- fix: refs #8242 workerDepartmentTree bug (origin/8242_leftMenu_responsive) by:Javier Segarra +- fix: workerBasicData by:carlossa +- Revert "revert 1015acefb7e400be2d8b5958dba69b4d98276b34" (origin/fix_revert_revert, fix_revert_revert) by:alexm + # Version 25.06 - 2025-02-18 ### Added 🆕 diff --git a/Jenkinsfile b/Jenkinsfile index c20da8ab2..18b27528b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,6 +1,7 @@ #!/usr/bin/env groovy def PROTECTED_BRANCH +def IS_LATEST def BRANCH_ENV = [ test: 'test', @@ -10,19 +11,22 @@ def BRANCH_ENV = [ node { stage('Setup') { - env.FRONT_REPLICAS = 1 env.NODE_ENV = BRANCH_ENV[env.BRANCH_NAME] ?: 'dev' - PROTECTED_BRANCH = [ 'dev', 'test', 'master', + 'main', 'beta' - ].contains(env.BRANCH_NAME) + ] - // https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables + IS_PROTECTED_BRANCH = PROTECTED_BRANCH.contains(env.BRANCH_NAME) + IS_LATEST = ['master', 'main'].contains(env.BRANCH_NAME) + + // https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables echo "NODE_NAME: ${env.NODE_NAME}" echo "WORKSPACE: ${env.WORKSPACE}" + echo "CHANGE_TARGET: ${env.CHANGE_TARGET}" configFileProvider([ configFile(fileId: 'salix-front.properties', @@ -33,7 +37,7 @@ node { props.each {key, value -> echo "${key}: ${value}" } } - if (PROTECTED_BRANCH) { + if (IS_PROTECTED_BRANCH) { configFileProvider([ configFile(fileId: "salix-front.branch.${env.BRANCH_NAME}", variable: 'BRANCH_PROPS_FILE') @@ -58,6 +62,19 @@ pipeline { PROJECT_NAME = 'lilium' } stages { + stage('Version') { + when { + expression { IS_PROTECTED_BRANCH } + } + steps { + script { + def packageJson = readJSON file: 'package.json' + def version = "${packageJson.version}-build${env.BUILD_ID}" + writeFile(file: 'VERSION.txt', text: version) + echo "VERSION: ${version}" + } + } + } stage('Install') { environment { NODE_ENV = "" @@ -68,48 +85,88 @@ pipeline { } stage('Test') { when { - expression { !PROTECTED_BRANCH } + expression { !IS_PROTECTED_BRANCH } } environment { - NODE_ENV = "" + NODE_ENV = '' + CI = 'true' + TZ = 'Europe/Madrid' } - steps { - sh 'pnpm run test:unit:ci' - } - post { - always { - junit( - testResults: 'junitresults.xml', - allowEmptyResults: true - ) + parallel { + stage('Unit') { + steps { + sh 'pnpm run test:front:ci' + } + post { + always { + junit( + testResults: 'junit/vitest.xml', + allowEmptyResults: true + ) + } + } + } + stage('E2E') { + environment { + CREDS = credentials('docker-registry') + COMPOSE_PROJECT = "${PROJECT_NAME}-${env.BUILD_ID}" + COMPOSE_PARAMS = "-p ${env.COMPOSE_PROJECT} -f test/cypress/docker-compose.yml --project-directory ." + } + steps { + script { + sh 'rm junit/e2e-*.xml || true' + env.COMPOSE_TAG = PROTECTED_BRANCH.contains(env.CHANGE_TARGET) ? env.CHANGE_TARGET : 'dev' + + sh 'docker login --username $CREDS_USR --password $CREDS_PSW $REGISTRY' + sh "docker-compose ${env.COMPOSE_PARAMS} up -d" + + def image = docker.build('lilium-dev', '-f docs/Dockerfile.dev docs') + image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") { + sh 'cypress run --browser chromium || true' + } + } + } + post { + always { + sh "docker-compose ${env.COMPOSE_PARAMS} down -v" + junit( + testResults: 'junit/e2e-*.xml', + allowEmptyResults: true + ) + } + } } } } stage('Build') { when { - expression { PROTECTED_BRANCH } + expression { IS_PROTECTED_BRANCH } } environment { - CREDENTIALS = credentials('docker-registry') + VERSION = readFile 'VERSION.txt' } steps { - sh 'quasar build' script { - def packageJson = readJSON file: 'package.json' - env.VERSION = "${packageJson.version}-build${env.BUILD_ID}" + sh 'quasar build' + + def baseImage = "salix-frontend:${env.VERSION}" + def image = docker.build(baseImage, ".") + docker.withRegistry("https://${env.REGISTRY}", 'docker-registry') { + image.push() + image.push(env.BRANCH_NAME) + if (IS_LATEST) image.push('latest') + } } - dockerBuild() } } stage('Deploy') { when { - expression { PROTECTED_BRANCH } + expression { IS_PROTECTED_BRANCH } + } + environment { + VERSION = readFile 'VERSION.txt' } steps { - script { - def packageJson = readJSON file: 'package.json' - env.VERSION = "${packageJson.version}-build${env.BUILD_ID}" - } withKubeConfig([ serverUrl: "$KUBERNETES_API", credentialsId: 'kubernetes', diff --git a/README.md b/README.md index e87a84d60..262e12e58 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ quasar dev ### Run unit tests ```bash -pnpm run test:unit +pnpm run test:front ``` ### Run e2e tests diff --git a/cypress.config.js b/cypress.config.js index a9e27fcfd..5cf075e2a 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -1,12 +1,37 @@ import { defineConfig } from 'cypress'; -// https://docs.cypress.io/app/tooling/reporters -// https://docs.cypress.io/app/references/configuration -// https://www.npmjs.com/package/cypress-mochawesome-reporter + +let urlHost, reporter, reporterOptions; + +if (process.env.CI) { + urlHost = 'front'; + reporter = 'junit'; + reporterOptions = { + mochaFile: 'junit/e2e-[hash].xml', + toConsole: false, + }; +} else { + urlHost = 'localhost'; + reporter = 'cypress-mochawesome-reporter'; + reporterOptions = { + charts: true, + reportPageTitle: 'Cypress Inline Reporter', + reportFilename: '[status]_[datetime]-report', + embeddedScreenshots: true, + reportDir: 'test/cypress/reports', + inlineAssets: true, + }; +} export default defineConfig({ e2e: { - baseUrl: 'http://localhost:9000/', - experimentalStudio: true, + baseUrl: `http://${urlHost}:9000`, + experimentalStudio: false, + defaultCommandTimeout: 10000, + trashAssetsBeforeRuns: false, + requestTimeout: 10000, + responseTimeout: 30000, + pageLoadTimeout: 60000, + defaultBrowser: 'chromium', fixturesFolder: 'test/cypress/fixtures', screenshotsFolder: 'test/cypress/screenshots', supportFile: 'test/cypress/support/index.js', @@ -14,29 +39,19 @@ export default defineConfig({ downloadsFolder: 'test/cypress/downloads', video: false, specPattern: 'test/cypress/integration/**/*.spec.js', - experimentalRunAllSpecs: false, - watchForFileChanges: false, - reporter: 'cypress-mochawesome-reporter', - reporterOptions: { - charts: true, - reportPageTitle: 'Cypress Inline Reporter', - reportFilename: '[status]_[datetime]-report', - embeddedScreenshots: true, - reportDir: 'test/cypress/reports', - inlineAssets: true, - }, + experimentalRunAllSpecs: true, + watchForFileChanges: true, + reporter, + reporterOptions, component: { componentFolder: 'src', testFiles: '**/*.spec.js', supportFile: 'test/cypress/support/unit.js', }, - setupNodeEvents: async (on, config) => { - const plugin = await import('cypress-mochawesome-reporter/plugin'); - plugin.default(on); - - return config; - }, viewportWidth: 1280, viewportHeight: 720, }, + experimentalMemoryManagement: true, + defaultCommandTimeout: 10000, + numTestsKeptInMemory: 2, }); diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index df793fc75..000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,7 +0,0 @@ -version: '3.7' -services: - main: - image: registry.verdnatura.es/salix-frontend:${VERSION:?} - build: - context: . - dockerfile: ./Dockerfile diff --git a/docs/Dockerfile.dev b/docs/Dockerfile.dev new file mode 100644 index 000000000..29b194ffa --- /dev/null +++ b/docs/Dockerfile.dev @@ -0,0 +1,45 @@ +FROM debian:12.9-slim + +ARG DEBIAN_FRONTEND=noninteractive + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + gnupg2 \ + && curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ + && apt-get install -y --no-install-recommends nodejs \ + && npm install -g corepack@0.31.0 \ + && corepack enable pnpm \ + && rm -rf /var/lib/apt/lists/* + +RUN apt-get update \ + && apt-get -y --no-install-recommends install \ + apt-utils \ + chromium \ + libasound2 \ + libgbm-dev \ + libgtk-3-0 \ + libgtk2.0-0 \ + libnotify-dev \ + libnss3 \ + libxss1 \ + libxtst6 \ + xauth \ + xvfb \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +RUN groupadd -r -g 1000 app \ + && useradd -r -u 1000 -g app -m -d /home/app app +USER app + +ENV SHELL=bash +ENV PNPM_HOME="/home/app/.local/share/pnpm" +ENV PATH="$PNPM_HOME:$PATH" + +RUN pnpm setup \ + && pnpm install --global cypress@13.6.6 \ + && cypress install + +WORKDIR /app diff --git a/package.json b/package.json index d23ed0ced..1361d1fd8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-front", - "version": "25.08.0", + "version": "25.10.0", "description": "Salix frontend", "productName": "Salix", "author": "Verdnatura", @@ -14,8 +14,8 @@ "test:e2e": "cypress open", "test:e2e:ci": "npm run resetDatabase && cd ../salix-front && cypress run", "test": "echo \"See package.json => scripts for available tests.\" && exit 0", - "test:unit": "vitest", - "test:unit:ci": "vitest run", + "test:front": "vitest", + "test:front:ci": "vitest run", "commitlint": "commitlint --edit", "prepare": "npx husky install", "addReferenceTag": "node .husky/addReferenceTag.js", @@ -71,4 +71,4 @@ "vite": "^6.0.11", "vitest": "^0.31.1" } -} \ No newline at end of file +} diff --git a/proxy-serve.js b/proxy-serve.js index 415968c85..1e9bcf96b 100644 --- a/proxy-serve.js +++ b/proxy-serve.js @@ -1,6 +1,6 @@ export default [ { path: '/api', - rule: { target: 'http://0.0.0.0:3000' }, + rule: { target: 'http://127.0.0.1:3000' }, }, ]; diff --git a/quasar.config.js b/quasar.config.js index 9467c92af..8b6125a90 100644 --- a/quasar.config.js +++ b/quasar.config.js @@ -11,6 +11,7 @@ import { configure } from 'quasar/wrappers'; import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'; import path from 'path'; +const target = `http://${process.env.CI ? 'back' : 'localhost'}:3000`; export default configure(function (/* ctx */) { return { @@ -108,13 +109,17 @@ export default configure(function (/* ctx */) { }, proxy: { '/api': { - target: 'http://0.0.0.0:3000', + target: target, logLevel: 'debug', changeOrigin: true, secure: false, }, }, open: false, + allowedHosts: [ + 'front', // Agrega este nombre de host + 'localhost', // Opcional, para pruebas locales + ], }, // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#framework diff --git a/src/components/CrudModel.vue b/src/components/CrudModel.vue index 93a2ac96a..8c4f70f3b 100644 --- a/src/components/CrudModel.vue +++ b/src/components/CrudModel.vue @@ -184,8 +184,11 @@ async function saveChanges(data) { if ($props.beforeSaveFn) { changes = await $props.beforeSaveFn(changes, getChanges); } - try { + if (changes?.creates?.length === 0 && changes?.updates?.length === 0) { + return; + } + await axios.post($props.saveUrl || $props.url + '/crud', changes); } finally { isLoading.value = false; diff --git a/src/components/FilterTravelForm.vue b/src/components/FilterTravelForm.vue index 765d97763..c522d0269 100644 --- a/src/components/FilterTravelForm.vue +++ b/src/components/FilterTravelForm.vue @@ -124,7 +124,7 @@ const selectTravel = ({ id }) => { window.location.reload(); - + + + {{ t('ticketSale.reserved') }} + + + {{ $t('salesTicketsTable.risk') }}: - {{ toCurrency(row.risk - row.credit) }} + {{ toCurrency(row.risk - (row.credit ?? 0)) }} {{ $t('salesTicketsTable.purchaseRequest') }} - + {{ $t('salesTicketsTable.noVerifiedData') }} diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue index 0d186bd57..d0c657f8a 100644 --- a/src/components/VnTable/VnTable.vue +++ b/src/components/VnTable/VnTable.vue @@ -51,14 +51,14 @@ const $props = defineProps({ type: Boolean, default: true, }, - rightSearchIcon: { - type: Boolean, - default: true, - }, rowClick: { type: [Function, Boolean], default: null, }, + rowCtrlClick: { + type: [Function, Boolean], + default: null, + }, redirect: { type: String, default: null, @@ -685,6 +685,7 @@ const rowCtrlClickFunction = computed(() => { @update:selected="emit('update:selected', $event)" @selection="(details) => handleSelection(details, rows)" :hide-selected-banner="true" + :data-cy="$props.dataCy ?? 'vnTable'" >