Merge pull request 'feat: refs #6897 add time formatting and improve column alignment handling in VnTable' (!1435) from 6897-fixMinorIssueWithSelectAndStyle into test
gitea/salix-front/pipeline/pr-dev This commit looks good Details
gitea/salix-front/pipeline/head This commit looks good Details

Reviewed-on: #1435
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
This commit is contained in:
Pablo Natek 2025-02-20 07:44:18 +00:00
commit bdd5843d14
5 changed files with 58 additions and 18 deletions

View File

@ -1,6 +1,6 @@
<script setup>
import { markRaw, computed } from 'vue';
import { QIcon, QCheckbox, QToggle } from 'quasar';
import { QIcon, QToggle } from 'quasar';
import { dashIfEmpty } from 'src/filters';
import VnSelect from 'components/common/VnSelect.vue';

View File

@ -14,10 +14,10 @@ import {
import { useArrayData } from 'src/composables/useArrayData';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
import { useQuasar } from 'quasar';
import { useQuasar, date } from 'quasar';
import { useStateStore } from 'stores/useStateStore';
import { useFilterParams } from 'src/composables/useFilterParams';
import { dashIfEmpty } from 'src/filters';
import { dashIfEmpty, toDate } from 'src/filters';
import CrudModel from 'src/components/CrudModel.vue';
import FormModelPopup from 'components/FormModelPopup.vue';
@ -345,7 +345,7 @@ const clickHandler = async (event) => {
if (isDateElement || isTimeElement || isQselectDropDown) return;
if (clickedElement === null) {
destroyInput(editingRow.value, editingField.value);
await destroyInput(editingRow.value, editingField.value);
return;
}
const rowIndex = clickedElement.getAttribute('data-row-index');
@ -355,7 +355,7 @@ const clickHandler = async (event) => {
if (editingRow.value !== null && editingField.value !== null) {
if (editingRow.value == rowIndex && editingField.value == colField) return;
destroyInput(editingRow.value, editingField.value);
await destroyInput(editingRow.value, editingField.value);
}
if (isEditableColumn(column)) {
@ -365,7 +365,7 @@ const clickHandler = async (event) => {
async function handleTabKey(event, rowIndex, colField) {
if (editingRow.value == rowIndex && editingField.value == colField)
destroyInput(editingRow.value, editingField.value);
await destroyInput(editingRow.value, editingField.value);
const direction = event.shiftKey ? -1 : 1;
const { nextRowIndex, nextColumnName } = await handleTabNavigation(
@ -425,7 +425,8 @@ async function renderInput(rowId, field, clickedElement) {
await column?.cellEvent?.['update:modelValue']?.(value, oldValue, row);
},
keyup: async (event) => {
if (event.key === 'Enter') handleBlur(rowId, field, clickedElement);
if (event.key === 'Enter')
await destroyInput(rowIndex, field, clickedElement);
},
keydown: async (event) => {
switch (event.key) {
@ -434,7 +435,7 @@ async function renderInput(rowId, field, clickedElement) {
event.stopPropagation();
break;
case 'Escape':
destroyInput(rowId, field, clickedElement);
await destroyInput(rowId, field, clickedElement);
break;
default:
break;
@ -456,12 +457,13 @@ async function renderInput(rowId, field, clickedElement) {
node.el?.querySelector('span > div > div').focus();
}
function destroyInput(rowIndex, field, clickedElement) {
async function destroyInput(rowIndex, field, clickedElement) {
if (!clickedElement)
clickedElement = document.querySelector(
`[data-row-index="${rowIndex}"][data-col-field="${field}"]`,
);
if (clickedElement) {
await nextTick();
render(null, clickedElement);
Array.from(clickedElement.childNodes).forEach((child) => {
child.style.visibility = 'visible';
@ -473,10 +475,6 @@ function destroyInput(rowIndex, field, clickedElement) {
editingField.value = null;
}
function handleBlur(rowIndex, field, clickedElement) {
destroyInput(rowIndex, field, clickedElement);
}
async function handleTabNavigation(rowIndex, colName, direction) {
const columns = $props.columns;
const totalColumns = columns.length;
@ -527,11 +525,36 @@ function formatColumnValue(col, row, dashIfEmpty) {
} else {
return col.format(row, dashIfEmpty);
}
}
if (col?.component === 'date') return dashIfEmpty(toDate(row[col?.name]));
if (col?.component === 'time')
return row[col?.name] >= 5
? dashIfEmpty(date.formatDate(new Date(row[col?.name]), 'HH:mm'))
: row[col?.name];
if (selectRegex.test(col?.component) && $props.isEditable) {
const { find, url } = col.attrs;
const urlRelation = url?.charAt(0)?.toLocaleLowerCase() + url?.slice(1, -1);
if (col?.attrs.options) {
const find = col?.attrs.options.find((option) => option.id === row[col.name]);
if (!col.attrs?.optionLabel || !find) return dashIfEmpty(row[col?.name]);
return dashIfEmpty(find[col.attrs?.optionLabel ?? 'name']);
}
if (typeof row[urlRelation] == 'object') {
if (typeof find == 'object')
return dashIfEmpty(row[urlRelation][find?.label ?? 'name']);
return dashIfEmpty(row[urlRelation][col?.attrs.optionLabel ?? 'name']);
}
if (typeof row[urlRelation] == 'string') return dashIfEmpty(row[urlRelation]);
} else {
return dashIfEmpty(row[col?.name]);
}
}
const checkbox = ref(null);
function cardClick(_, row) {
if ($props.redirect) router.push({ path: `/${$props.redirect}/${row.id}` });
}
@ -730,7 +753,11 @@ function cardClick(_, row) {
<span
v-else
:class="hasEditableFormat(col)"
:style="col?.style ? col.style(row) : null"
:style="
typeof col?.style == 'function'
? col.style(row)
: col?.style
"
style="bottom: 0"
>
{{ formatColumnValue(col, row, dashIfEmpty) }}
@ -783,7 +810,7 @@ function cardClick(_, row) {
<QCardSection
vertical
class="no-margin no-padding"
:class="colsMap.tableActions ? '' : 'fit'"
:class="colsMap.tableActions ? 'w-80' : 'fit'"
>
<!-- Chips -->
<QCardSection

View File

@ -7,6 +7,7 @@ export function getColAlign(col) {
case 'number':
align = 'right';
break;
case 'time':
case 'date':
case 'checkbox':
align = 'center';

View File

@ -119,7 +119,7 @@ const columns = computed(() => [
:url="`Workers/${entityId}/trainingCourse`"
:url-create="`Workers/${entityId}/trainingCourse`"
save-url="TrainingCourses/crud"
:filter="courseFilter"
:user-filter="courseFilter"
:create="{
urlCreate: 'trainingCourses',
title: t('Create training course'),

View File

@ -8,6 +8,17 @@ const { t } = useI18n();
const route = useRoute();
const entityId = computed(() => route.params.id);
const centerFilter = {
include: [
{
relation: 'center',
scope: {
fields: ['id', 'name'],
},
},
],
};
const columns = [
{
align: 'left',
@ -33,7 +44,7 @@ const columns = [
create: true,
component: 'select',
attrs: {
url: 'medicalCenters',
url: 'centers',
fields: ['id', 'name'],
},
},
@ -84,6 +95,7 @@ const columns = [
ref="tableRef"
data-key="WorkerMedical"
:url="`Workers/${entityId}/medicalReview`"
:user-filter="centerFilter"
save-url="MedicalReviews/crud"
:create="{
urlCreate: 'medicalReviews',