From 446b679bca32599d2c09ad8ceda096f7afe56ba9 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Thu, 27 Mar 2025 10:23:55 +0100
Subject: [PATCH 01/14] chore: update Cypress parallel test execution to use 2
 instances

---
 Jenkinsfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Jenkinsfile b/Jenkinsfile
index 05ef34791..7f4144a54 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -126,7 +126,7 @@ pipeline {
                             sh "docker-compose ${env.COMPOSE_PARAMS} up -d"
 
                             image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") {
-                                sh 'sh test/cypress/cypressParallel.sh 1'
+                                sh 'sh test/cypress/cypressParallel.sh 2'
                             }
                         }
                     }

From d94dafd6671c885ca663b1ac86c17448922c7225 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Thu, 27 Mar 2025 11:43:00 +0100
Subject: [PATCH 02/14] chore: update Cypress parallel test execution to use 3
 instances

---
 Jenkinsfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Jenkinsfile b/Jenkinsfile
index 7f4144a54..73c700f19 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -126,7 +126,7 @@ pipeline {
                             sh "docker-compose ${env.COMPOSE_PARAMS} up -d"
 
                             image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") {
-                                sh 'sh test/cypress/cypressParallel.sh 2'
+                                sh 'sh test/cypress/cypressParallel.sh 3'
                             }
                         }
                     }

From 696dbd4149c6e05046bfa8450bd955f31e49b73d Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Thu, 27 Mar 2025 12:27:47 +0100
Subject: [PATCH 03/14] chore: update Cypress parallel test execution to use 4
 instances

---
 Jenkinsfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Jenkinsfile b/Jenkinsfile
index 73c700f19..0c209bdef 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -126,7 +126,7 @@ pipeline {
                             sh "docker-compose ${env.COMPOSE_PARAMS} up -d"
 
                             image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") {
-                                sh 'sh test/cypress/cypressParallel.sh 3'
+                                sh 'sh test/cypress/cypressParallel.sh 4'
                             }
                         }
                     }

From 71c6741cf290bf0ca58b4be97c2e0709f1ab087a Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Thu, 27 Mar 2025 12:28:11 +0100
Subject: [PATCH 04/14] chore: update Cypress parallel test execution to use 6
 instances

---
 Jenkinsfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Jenkinsfile b/Jenkinsfile
index 0c209bdef..2a4e80e4f 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -126,7 +126,7 @@ pipeline {
                             sh "docker-compose ${env.COMPOSE_PARAMS} up -d"
 
                             image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") {
-                                sh 'sh test/cypress/cypressParallel.sh 4'
+                                sh 'sh test/cypress/cypressParallel.sh 6'
                             }
                         }
                     }

From ea314073d2b78f3d5c2df2031c9af8176e5f5d08 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Thu, 27 Mar 2025 13:26:42 +0100
Subject: [PATCH 05/14] chore: update Cypress parallel test execution to use 2
 instances

---
 Jenkinsfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Jenkinsfile b/Jenkinsfile
index 2a4e80e4f..7f4144a54 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -126,7 +126,7 @@ pipeline {
                             sh "docker-compose ${env.COMPOSE_PARAMS} up -d"
 
                             image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") {
-                                sh 'sh test/cypress/cypressParallel.sh 6'
+                                sh 'sh test/cypress/cypressParallel.sh 2'
                             }
                         }
                     }

From f3925026738af32b0bc00a20e62d4e203d6274df Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 31 Mar 2025 15:02:37 +0200
Subject: [PATCH 06/14] fix: workerSummary

---
 src/pages/Worker/Card/WorkerSummary.vue | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue
index 40787613c..26c84fe09 100644
--- a/src/pages/Worker/Card/WorkerSummary.vue
+++ b/src/pages/Worker/Card/WorkerSummary.vue
@@ -73,21 +73,18 @@ onBeforeMount(async () => {
                                 />
                             </template>
                         </VnLv>
-                        <VnLv :value="worker.mobileExtension">
-                            <template #label>
-                                {{ t('worker.summary.phoneExtension') }}
+                        <VnLv :label="t('worker.summary.phoneExtension')">
+                            <template #value>
                                 <VnLinkPhone :phone-number="worker.mobileExtension" />
                             </template>
                         </VnLv>
-                        <VnLv :value="worker.phone">
-                            <template #label>
-                                {{ t('worker.summary.entPhone') }}
+                        <VnLv :label="t('worker.summary.entPhone')">
+                            <template #value>
                                 <VnLinkPhone :phone-number="worker.phone" />
                             </template>
                         </VnLv>
-                        <VnLv :value="advancedSummary?.client?.phone">
-                            <template #label>
-                                {{ t('worker.summary.personalPhone') }}
+                        <VnLv :label="t('worker.summary.personalPhone')">
+                            <template #value>
                                 <VnLinkPhone
                                     :phone-number="advancedSummary?.client?.phone"
                                 />
@@ -147,9 +144,8 @@ onBeforeMount(async () => {
                         </span>
                     </template>
                 </VnLv>
-                <VnLv :value="worker?.sip?.extension">
-                    <template #label>
-                        {{ t('worker.summary.sipExtension') }}
+                <VnLv :label="t('worker.summary.sipExtension')">
+                    <template #value>
                         <VnLinkPhone :phone-number="worker?.sip?.extension" />
                     </template>
                 </VnLv>

From 0208debdbefee208764c9ec27ade547d2f88ea5b Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 31 Mar 2025 15:15:07 +0200
Subject: [PATCH 07/14] feat: worker vnLinkPhone

---
 src/pages/Worker/Card/WorkerDescriptor.vue | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/pages/Worker/Card/WorkerDescriptor.vue b/src/pages/Worker/Card/WorkerDescriptor.vue
index 060520e84..0f09c0a97 100644
--- a/src/pages/Worker/Card/WorkerDescriptor.vue
+++ b/src/pages/Worker/Card/WorkerDescriptor.vue
@@ -128,15 +128,13 @@ const handlePhotoUpdated = (evt = false) => {
                 </template>
             </VnLv>
 
-            <VnLv :value="entity.phone">
-                <template #label>
-                    {{ t('globals.phone') }}
+            <VnLv :label="t('globals.phone')">
+                <template #value>
                     <VnLinkPhone :phone-number="entity.phone" />
                 </template>
             </VnLv>
-            <VnLv :value="entity?.sip?.extension">
-                <template #label>
-                    {{ t('worker.summary.sipExtension') }}
+            <VnLv :label="t('worker.summary.sipExtension')">
+                <template #value>
                     <VnLinkPhone :phone-number="entity?.sip?.extension" />
                 </template>
             </VnLv>

From dd739b11650802e6090f63d3578ef647cd8fdc21 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 31 Mar 2025 15:15:17 +0200
Subject: [PATCH 08/14] fix: customer vnLinkPhone

---
 src/pages/Customer/Card/CustomerSummary.vue | 33 +++++++++++----------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/src/pages/Customer/Card/CustomerSummary.vue b/src/pages/Customer/Card/CustomerSummary.vue
index 7d5d691a3..04246c39c 100644
--- a/src/pages/Customer/Card/CustomerSummary.vue
+++ b/src/pages/Customer/Card/CustomerSummary.vue
@@ -84,27 +84,28 @@ const sumRisk = ({ clientRisks }) => {
                 <VnLv :label="t('customer.summary.customerId')" :value="entity.id" />
                 <VnLv :label="t('globals.name')" :value="entity.name" />
                 <VnLv :label="t('customer.summary.contact')" :value="entity.contact" />
-                <VnLv :value="entity.phone">
-                    <template #label>
-                        {{ t('customer.extendedList.tableVisibleColumns.phone') }}
+                <VnLv :label="t('customer.extendedList.tableVisibleColumns.phone')">
+                    <template #value>
                         <VnLinkPhone :phone-number="entity.phone" />
                     </template>
                 </VnLv>
-                <VnLv :value="entity.mobile">
-                    <template #label>
-                        {{ t('customer.summary.mobile') }}
-                        <VnLinkPhone :phone-number="entity.mobile" />
-                        <VnLinkPhone
-                            say-simple
-                            :phone-number="entity.mobile"
-                            :channel="entity.country?.saySimpleCountry?.channel"
-                            class="q-ml-xs"
-                        />
+                <VnLv :label="t('customer.summary.mobile')">
+                    <template #value>
+                        <div class="col">
+                            <VnLinkPhone :phone-number="entity.mobile" />
+                        </div>
+                        <div class="col">
+                            <VnLinkPhone
+                                say-simple
+                                :phone-number="entity.mobile"
+                                :channel="entity.country?.saySimpleCountry?.channel"
+                                class="q-ml-xs"
+                            />
+                        </div>
                     </template>
                 </VnLv>
-                <VnLv :value="entity.email" copy
-                    ><template #label>
-                        {{ t('globals.params.email') }}
+                <VnLv :label="t('globals.params.email')"
+                    ><template #value>
                         <VnLinkMail email="entity.email"></VnLinkMail> </template
                 ></VnLv>
                 <VnLv :label="t('globals.department')">

From 19121fbeb988a83951bce220f02447d655e5f1e8 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 31 Mar 2025 15:15:29 +0200
Subject: [PATCH 09/14] fix: roadmap

---
 src/pages/Route/Roadmap/RoadmapSummary.vue | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/src/pages/Route/Roadmap/RoadmapSummary.vue b/src/pages/Route/Roadmap/RoadmapSummary.vue
index 0c1c2b903..dcd02d98e 100644
--- a/src/pages/Route/Roadmap/RoadmapSummary.vue
+++ b/src/pages/Route/Roadmap/RoadmapSummary.vue
@@ -112,12 +112,9 @@ const filter = {
                         :label="t('Trailer Plate')"
                         :value="dashIfEmpty(entity?.trailerPlate)"
                     />
-                    <VnLv :label="t('Phone')" :value="dashIfEmpty(entity?.phone)">
+                    <VnLv :label="t('Phone')">
                         <template #value>
-                            <span>
-                                {{ dashIfEmpty(entity?.phone) }}
-                                <VnLinkPhone :phone-number="entity?.phone" />
-                            </span>
+                            <VnLinkPhone :phone-number="entity?.phone" />
                         </template>
                     </VnLv>
                     <VnLv

From d71029c7e9ebb9222096e6d8c2539ab8881c4826 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Mon, 31 Mar 2025 15:15:37 +0200
Subject: [PATCH 10/14] feat: dashIfEmpty

---
 src/components/ui/VnLinkPhone.vue | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/components/ui/VnLinkPhone.vue b/src/components/ui/VnLinkPhone.vue
index 4174e4ae6..94b4b9d1c 100644
--- a/src/components/ui/VnLinkPhone.vue
+++ b/src/components/ui/VnLinkPhone.vue
@@ -1,7 +1,7 @@
 <script setup>
 import { ref, reactive, useAttrs, onBeforeMount, capitalize } from 'vue';
 import axios from 'axios';
-import { parsePhone } from 'src/filters';
+import { dashIfEmpty, parsePhone } from 'src/filters';
 import useOpenURL from 'src/composables/useOpenURL';
 
 const props = defineProps({
@@ -31,9 +31,8 @@ onBeforeMount(async () => {
         if (!channel) channel = defaultChannel;
 
         phone.value = await parsePhone(props.phoneNumber, props.country?.toLowerCase());
-        config[
-            type
-        ].url = `${url}?customerIdentity=%2B${phone.value}&channelId=${channel}`;
+        config[type].url =
+            `${url}?customerIdentity=%2B${phone.value}&channelId=${channel}`;
     }
 });
 
@@ -57,5 +56,6 @@ function handleClick() {
             {{ capitalize(type).replace('-', '') }}
         </QTooltip>
     </QBtn>
-    {{ phoneNumber }}
+
+    <span>{{ dashIfEmpty(phone) }}</span>
 </template>

From 588876952a5e5531b89f82d5087f2ebb91840a06 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 1 Apr 2025 14:51:24 +0200
Subject: [PATCH 11/14] fix: customerSummary

---
 src/pages/Customer/Card/CustomerSummary.vue | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/pages/Customer/Card/CustomerSummary.vue b/src/pages/Customer/Card/CustomerSummary.vue
index 04246c39c..3e88cd5da 100644
--- a/src/pages/Customer/Card/CustomerSummary.vue
+++ b/src/pages/Customer/Card/CustomerSummary.vue
@@ -96,17 +96,20 @@ const sumRisk = ({ clientRisks }) => {
                         </div>
                         <div class="col">
                             <VnLinkPhone
+                                sip
                                 say-simple
                                 :phone-number="entity.mobile"
                                 :channel="entity.country?.saySimpleCountry?.channel"
-                                class="q-ml-xs"
                             />
                         </div>
                     </template>
                 </VnLv>
-                <VnLv :label="t('globals.params.email')"
-                    ><template #value>
-                        <VnLinkMail email="entity.email"></VnLinkMail> </template
+                <VnLv
+                    :label="t('globals.params.email')"
+                    :value="entity.email"
+                    class="ellipsis"
+                    copy
+                    ><template #value> <VnLinkMail :email="entity.email" /> </template
                 ></VnLv>
                 <VnLv :label="t('globals.department')">
                     <template #value>

From 02a78c662bee2b3c7bf5545b805e4a926aee63d4 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 1 Apr 2025 14:51:49 +0200
Subject: [PATCH 12/14] perf: handle VnLinkMail and VnEmail

---
 src/components/ui/VnLinkMail.vue  |  4 ++
 src/components/ui/VnLinkPhone.vue | 69 +++++++++++++++++++------------
 2 files changed, 46 insertions(+), 27 deletions(-)

diff --git a/src/components/ui/VnLinkMail.vue b/src/components/ui/VnLinkMail.vue
index a54f463f5..6c5129a9b 100644
--- a/src/components/ui/VnLinkMail.vue
+++ b/src/components/ui/VnLinkMail.vue
@@ -1,8 +1,11 @@
 <script setup>
+import { dashIfEmpty } from 'src/filters';
+
 defineProps({ email: { type: [String], default: null } });
 </script>
 <template>
     <QBtn
+        class="q-pr-xs"
         v-if="email"
         flat
         round
@@ -13,4 +16,5 @@ defineProps({ email: { type: [String], default: null } });
         :href="`mailto:${email}`"
         @click.stop
     />
+    <span>{{ dashIfEmpty(email) }}</span>
 </template>
diff --git a/src/components/ui/VnLinkPhone.vue b/src/components/ui/VnLinkPhone.vue
index 94b4b9d1c..e34a70011 100644
--- a/src/components/ui/VnLinkPhone.vue
+++ b/src/components/ui/VnLinkPhone.vue
@@ -12,50 +12,65 @@ const props = defineProps({
 
 const phone = ref(props.phoneNumber);
 const config = reactive({
-    sip: { icon: 'phone', href: `sip:${props.phoneNumber}` },
     'say-simple': {
         icon: 'vn:saysimple',
         url: null,
         channel: props.channel,
     },
+    sip: { icon: 'phone', href: `sip:${props.phoneNumber}` },
 });
-const type = Object.keys(config).find((key) => key in useAttrs()) || 'sip';
+
+const attrs = useAttrs();
+const types = Object.keys(config)
+    .filter((key) => key in attrs)
+    .sort();
+const activeTypes = types.length ? types : ['sip'];
 
 onBeforeMount(async () => {
     if (!phone.value) return;
-    let { channel } = config[type];
 
-    if (type === 'say-simple') {
-        const { url, defaultChannel } = (await axios.get('SaySimpleConfigs/findOne'))
-            .data;
-        if (!channel) channel = defaultChannel;
+    for (const type of activeTypes) {
+        if (type === 'say-simple') {
+            let { channel } = config[type];
+            const { url, defaultChannel } = (await axios.get('SaySimpleConfigs/findOne'))
+                .data;
+            if (!channel) channel = defaultChannel;
 
-        phone.value = await parsePhone(props.phoneNumber, props.country?.toLowerCase());
-        config[type].url =
-            `${url}?customerIdentity=%2B${phone.value}&channelId=${channel}`;
+            phone.value = await parsePhone(
+                props.phoneNumber,
+                props.country?.toLowerCase(),
+            );
+            config[type].url =
+                `${url}?customerIdentity=%2B${phone.value}&channelId=${channel}`;
+        }
     }
 });
 
-function handleClick() {
+function handleClick(type) {
     if (config[type].url) useOpenURL(config[type].url);
     else if (config[type].href) window.location.href = config[type].href;
 }
 </script>
-<template>
-    <QBtn
-        v-if="phone"
-        flat
-        round
-        :icon="config[type].icon"
-        size="sm"
-        color="primary"
-        padding="none"
-        @click.stop="handleClick"
-    >
-        <QTooltip>
-            {{ capitalize(type).replace('-', '') }}
-        </QTooltip>
-    </QBtn>
 
-    <span>{{ dashIfEmpty(phone) }}</span>
+<template>
+    <div class="flex items-center gap-2">
+        <template v-for="type in activeTypes">
+            <QBtn
+                :key="type"
+                v-if="phone"
+                flat
+                round
+                :icon="config[type].icon"
+                size="sm"
+                color="primary"
+                padding="none"
+                @click.stop="() => handleClick(type)"
+            >
+                <QTooltip>
+                    {{ capitalize(type).replace('-', '') }}
+                </QTooltip>
+            </QBtn></template
+        >
+        <span>{{ dashIfEmpty(phone) }}</span>
+    </div>
 </template>

From 40cfe2a5cc8d3d92919d2340ba49db7d144a23fe Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 1 Apr 2025 14:52:05 +0200
Subject: [PATCH 13/14] style: add ellipsis class to CardSummary

---
 src/components/ui/CardSummary.vue | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/components/ui/CardSummary.vue b/src/components/ui/CardSummary.vue
index 2ec6bea78..7ea91edca 100644
--- a/src/components/ui/CardSummary.vue
+++ b/src/components/ui/CardSummary.vue
@@ -159,6 +159,7 @@ async function fetch() {
                 display: flex;
                 flex-direction: row;
                 margin-top: 2px;
+                align-items: start;
                 .label {
                     color: var(--vn-label-color);
                     width: 9em;
@@ -169,6 +170,10 @@ async function fetch() {
                     flex-grow: 0;
                     flex-shrink: 0;
                 }
+                &.ellipsis > .value {
+                    text-overflow: ellipsis;
+                    white-space: pre;
+                }
                 .value {
                     color: var(--vn-text-color);
                     overflow: hidden;

From f02fa732ee7dad015868f2543893f353333ef0a9 Mon Sep 17 00:00:00 2001
From: Javier Segarra <jsegarra@verdnatura.es>
Date: Tue, 1 Apr 2025 15:10:49 +0200
Subject: [PATCH 14/14] feat: remove unused vnLinkPhone

---
 src/pages/Customer/Card/CustomerSummary.vue | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/src/pages/Customer/Card/CustomerSummary.vue b/src/pages/Customer/Card/CustomerSummary.vue
index 3e88cd5da..342643ec3 100644
--- a/src/pages/Customer/Card/CustomerSummary.vue
+++ b/src/pages/Customer/Card/CustomerSummary.vue
@@ -91,17 +91,12 @@ const sumRisk = ({ clientRisks }) => {
                 </VnLv>
                 <VnLv :label="t('customer.summary.mobile')">
                     <template #value>
-                        <div class="col">
-                            <VnLinkPhone :phone-number="entity.mobile" />
-                        </div>
-                        <div class="col">
-                            <VnLinkPhone
-                                sip
-                                say-simple
-                                :phone-number="entity.mobile"
-                                :channel="entity.country?.saySimpleCountry?.channel"
-                            />
-                        </div>
+                        <VnLinkPhone
+                            sip
+                            say-simple
+                            :phone-number="entity.mobile"
+                            :channel="entity.country?.saySimpleCountry?.channel"
+                        />
                     </template>
                 </VnLv>
                 <VnLv