refactor: refs #6897 refactor vnTable for non input editable table
gitea/salix-front/pipeline/pr-dev There was a failure building this commit
Details
gitea/salix-front/pipeline/pr-dev There was a failure building this commit
Details
This commit is contained in:
parent
6dd0b32389
commit
54ace8c682
|
@ -6,11 +6,11 @@ import useNotify from 'src/composables/useNotify.js';
|
||||||
const { notify } = useNotify();
|
const { notify } = useNotify();
|
||||||
|
|
||||||
export default boot(({ app }) => {
|
export default boot(({ app }) => {
|
||||||
app.mixin(qFormMixin);
|
|
||||||
app.mixin(mainShortcutMixin);
|
|
||||||
app.directive('shortcut', keyShortcut);
|
|
||||||
app.config.errorHandler = function (err) {
|
app.config.errorHandler = function (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
notify('globals.error', 'negative', 'error');
|
notify('globals.error', 'negative', 'error');
|
||||||
};
|
};
|
||||||
|
app.directive('shortcut', keyShortcut);
|
||||||
|
app.mixin(qFormMixin);
|
||||||
|
app.mixin(mainShortcutMixin);
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,36 +8,27 @@ const props = defineProps({
|
||||||
validator: (value) => value.length <= 3,
|
validator: (value) => value.length <= 3,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const sectionHeight = computed(() => `${100 / props.colors.length}%`);
|
const sectionHeight = computed(() => `${100 / props.colors.length}%`);
|
||||||
|
|
||||||
const divStyle = computed(() => ({
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
}));
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="color-div" :style="divStyle">
|
<div class="color-div">
|
||||||
<div
|
<div
|
||||||
v-for="(color, index) in colors"
|
v-for="(color, index) in colors"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="color-section"
|
:style="{
|
||||||
:style="{ backgroundColor: color, height: sectionHeight }"
|
backgroundColor: color,
|
||||||
></div>
|
height: sectionHeight,
|
||||||
|
width: '100%',
|
||||||
|
flexShrink: 0,
|
||||||
|
}"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.color-div {
|
.color-div {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 100%;
|
height: 100vh;
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.color-section {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -14,6 +14,7 @@ import VnComponent from 'components/common/VnComponent.vue';
|
||||||
import VnUserLink from 'components/ui/VnUserLink.vue';
|
import VnUserLink from 'components/ui/VnUserLink.vue';
|
||||||
|
|
||||||
const model = defineModel(undefined, { required: true });
|
const model = defineModel(undefined, { required: true });
|
||||||
|
const emit = defineEmits(['blur']);
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
column: {
|
column: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
@ -39,6 +40,10 @@ const $props = defineProps({
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
autofocus: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
showLabel: {
|
showLabel: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: null,
|
default: null,
|
||||||
|
@ -99,6 +104,7 @@ const defaultComponents = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
checkbox: {
|
checkbox: {
|
||||||
|
ref: 'checkbox',
|
||||||
component: markRaw(QCheckbox),
|
component: markRaw(QCheckbox),
|
||||||
attrs: ({ model }) => {
|
attrs: ({ model }) => {
|
||||||
const defaultAttrs = {
|
const defaultAttrs = {
|
||||||
|
@ -115,6 +121,10 @@ const defaultComponents = {
|
||||||
},
|
},
|
||||||
forceAttrs: {
|
forceAttrs: {
|
||||||
label: $props.showLabel && $props.column.label,
|
label: $props.showLabel && $props.column.label,
|
||||||
|
autofocus: true,
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
blur: () => emit('blur'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
|
@ -160,7 +170,27 @@ const col = computed(() => {
|
||||||
return newColumn;
|
return newColumn;
|
||||||
});
|
});
|
||||||
|
|
||||||
const components = computed(() => $props.components ?? defaultComponents);
|
const components = computed(() => {
|
||||||
|
const sourceComponents = $props.components ?? defaultComponents;
|
||||||
|
|
||||||
|
return Object.keys(sourceComponents).reduce((acc, key) => {
|
||||||
|
const component = sourceComponents[key];
|
||||||
|
|
||||||
|
if (!component || typeof component !== 'object') {
|
||||||
|
acc[key] = component;
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
acc[key] = {
|
||||||
|
...component,
|
||||||
|
attrs: {
|
||||||
|
...(component.attrs || {}),
|
||||||
|
autofocus: $props.autofocus,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="row no-wrap">
|
<div class="row no-wrap">
|
||||||
|
@ -170,6 +200,7 @@ const components = computed(() => $props.components ?? defaultComponents);
|
||||||
:components="components"
|
:components="components"
|
||||||
:value="{ row, model }"
|
:value="{ row, model }"
|
||||||
v-model="model"
|
v-model="model"
|
||||||
|
@blur="emit('blur')"
|
||||||
/>
|
/>
|
||||||
<VnComponent
|
<VnComponent
|
||||||
v-if="col.component"
|
v-if="col.component"
|
||||||
|
@ -177,6 +208,7 @@ const components = computed(() => $props.components ?? defaultComponents);
|
||||||
:components="components"
|
:components="components"
|
||||||
:value="{ row, model }"
|
:value="{ row, model }"
|
||||||
v-model="model"
|
v-model="model"
|
||||||
|
@blur="emit('blur')"
|
||||||
/>
|
/>
|
||||||
<span :title="value" v-else>{{ value }}</span>
|
<span :title="value" v-else>{{ value }}</span>
|
||||||
<VnComponent
|
<VnComponent
|
||||||
|
@ -185,6 +217,7 @@ const components = computed(() => $props.components ?? defaultComponents);
|
||||||
:components="components"
|
:components="components"
|
||||||
:value="{ row, model }"
|
:value="{ row, model }"
|
||||||
v-model="model"
|
v-model="model"
|
||||||
|
@blur="emit('blur')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onBeforeMount, onMounted, computed, watch } from 'vue';
|
import { ref, onBeforeMount, onMounted, computed, watch, nextTick } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
|
@ -327,6 +327,7 @@ const editingRow = ref(null);
|
||||||
const editingField = ref(null);
|
const editingField = ref(null);
|
||||||
|
|
||||||
const handleClick = (event) => {
|
const handleClick = (event) => {
|
||||||
|
console.log('event: ', event);
|
||||||
const clickedElement = event.target.closest('td');
|
const clickedElement = event.target.closest('td');
|
||||||
|
|
||||||
if (!clickedElement) return;
|
if (!clickedElement) return;
|
||||||
|
@ -338,17 +339,132 @@ const handleClick = (event) => {
|
||||||
startEditing(Number(rowIndex), colField);
|
startEditing(Number(rowIndex), colField);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const vnEditableCell = ref(null);
|
||||||
const startEditing = (rowId, field) => {
|
const startEditing = async (rowId, field) => {
|
||||||
|
console.log('entrando a startEditing');
|
||||||
|
const col = $props.columns.find((col) => col.name === field);
|
||||||
|
if (col?.isEditable === false) return;
|
||||||
editingRow.value = rowId;
|
editingRow.value = rowId;
|
||||||
editingField.value = field;
|
editingField.value = field;
|
||||||
|
if (col.component === 'checkbox') {
|
||||||
|
await nextTick();
|
||||||
|
const inputElement = vnEditableCell.value?.$el?.querySelector('span > div');
|
||||||
|
inputElement.focus();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const stopEditing = () => {
|
const stopEditing = (rowIndex, field) => {
|
||||||
|
if (editingRow.value !== rowIndex || editingField.value !== field) return;
|
||||||
editingRow.value = null;
|
editingRow.value = null;
|
||||||
editingField.value = null;
|
editingField.value = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const findNextEditableColumnIndex = (columns, startIndex) => {
|
||||||
|
let index = startIndex;
|
||||||
|
console.log('columns: ', columns);
|
||||||
|
console.log('index: ', index);
|
||||||
|
console.log(
|
||||||
|
'columns[index]?.isVisible === false || columns[index]?.isEditable === false: ',
|
||||||
|
columns[index]?.isVisible === false || columns[index]?.isEditable === false
|
||||||
|
);
|
||||||
|
while (columns[index]?.isVisible === false && columns[index]?.isEditable === false) {
|
||||||
|
index++;
|
||||||
|
if (index >= columns.length) {
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
if (index === startIndex) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('index: ', index);
|
||||||
|
return index;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTab = async (rowIndex, colName) => {
|
||||||
|
console.log('colName: ', colName);
|
||||||
|
console.log('rowIndex: ', rowIndex);
|
||||||
|
const columns = $props.columns;
|
||||||
|
console.log('columns: ', columns);
|
||||||
|
|
||||||
|
if (!Array.isArray(columns) || columns.length === 0) return;
|
||||||
|
|
||||||
|
let currentColumnIndex = columns.findIndex((col) => col.name === colName);
|
||||||
|
if (currentColumnIndex === -1) return;
|
||||||
|
|
||||||
|
currentColumnIndex++;
|
||||||
|
if (currentColumnIndex >= columns.length) {
|
||||||
|
currentColumnIndex = 0;
|
||||||
|
rowIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentColumnIndex = findNextEditableColumnIndex(columns, currentColumnIndex);
|
||||||
|
if (currentColumnIndex === -1) return;
|
||||||
|
|
||||||
|
await startEditing(rowIndex, columns[currentColumnIndex].name);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleShiftTab = async (rowIndex, colName) => {
|
||||||
|
console.log('handleShiftTab: ');
|
||||||
|
const columns = $props.columns;
|
||||||
|
const currentColumnIndex = columns.findIndex((col) => col.name === colName);
|
||||||
|
|
||||||
|
if (currentColumnIndex === -1) return;
|
||||||
|
|
||||||
|
let prevColumnIndex = currentColumnIndex - 1;
|
||||||
|
let prevRowIndex = rowIndex;
|
||||||
|
|
||||||
|
while (prevColumnIndex >= 0 && columns[prevColumnIndex]?.isEditable === false) {
|
||||||
|
prevColumnIndex--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevColumnIndex < 0) {
|
||||||
|
prevColumnIndex = columns.length - 1;
|
||||||
|
prevRowIndex -= 1;
|
||||||
|
|
||||||
|
while (prevRowIndex >= 0 && columns[prevColumnIndex]?.isEditable === false) {
|
||||||
|
prevColumnIndex--;
|
||||||
|
if (prevColumnIndex < 0) {
|
||||||
|
prevColumnIndex = columns.length - 1;
|
||||||
|
prevRowIndex--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevRowIndex < 0) {
|
||||||
|
stopEditing(rowIndex, colName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await startEditing(prevRowIndex, columns[prevColumnIndex]?.name);
|
||||||
|
console.log('finishHandleShiftTab');
|
||||||
|
};
|
||||||
|
const handleTabKey = async (event, rowIndex, colName) => {
|
||||||
|
console.log('colName: ', colName);
|
||||||
|
console.log('rowIndex: ', rowIndex);
|
||||||
|
console.log('event: ', event);
|
||||||
|
if (event.shiftKey) await handleShiftTab(rowIndex, colName);
|
||||||
|
else await handleTab(rowIndex, colName);
|
||||||
|
};
|
||||||
|
function getCheckboxIcon(value) {
|
||||||
|
switch (value) {
|
||||||
|
case true:
|
||||||
|
return 'check';
|
||||||
|
case false:
|
||||||
|
return 'close';
|
||||||
|
default:
|
||||||
|
return 'unknown_med';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldDisplayReadonly(col, rowIndex) {
|
||||||
|
return (
|
||||||
|
col?.isEditable === false ||
|
||||||
|
editingRow.value !== rowIndex ||
|
||||||
|
editingField.value !== col?.name
|
||||||
|
);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QDrawer
|
<QDrawer
|
||||||
v-if="$props.rightSearch"
|
v-if="$props.rightSearch"
|
||||||
|
@ -433,7 +549,7 @@ const stopEditing = () => {
|
||||||
<template #body="{ rows }">
|
<template #body="{ rows }">
|
||||||
<QTable
|
<QTable
|
||||||
v-bind="table"
|
v-bind="table"
|
||||||
class="vnTable"
|
:class="['vnTable', table ? 'selection-cell' : '']"
|
||||||
wrap-cells
|
wrap-cells
|
||||||
:columns="splittedColumns.columns"
|
:columns="splittedColumns.columns"
|
||||||
:rows="rows"
|
:rows="rows"
|
||||||
|
@ -452,10 +568,6 @@ const stopEditing = () => {
|
||||||
"
|
"
|
||||||
@row-click="(_, row) => rowClickFunction && rowClickFunction(row)"
|
@row-click="(_, row) => rowClickFunction && rowClickFunction(row)"
|
||||||
@update:selected="emit('update:selected', $event)"
|
@update:selected="emit('update:selected', $event)"
|
||||||
@row-contextmenu="
|
|
||||||
(event, row, index) =>
|
|
||||||
console.log('event ', event, ' row ', row, ' index ', index)
|
|
||||||
"
|
|
||||||
@click="handleClick"
|
@click="handleClick"
|
||||||
>
|
>
|
||||||
<template #top-left v-if="!$props.withoutHeader">
|
<template #top-left v-if="!$props.withoutHeader">
|
||||||
|
@ -535,22 +647,27 @@ const stopEditing = () => {
|
||||||
</template>
|
</template>
|
||||||
<template #body-cell="{ col, row, rowIndex }">
|
<template #body-cell="{ col, row, rowIndex }">
|
||||||
<QTd
|
<QTd
|
||||||
|
v-if="col.visible ?? true"
|
||||||
:style="{
|
:style="{
|
||||||
maxWidth: col?.width ?? false,
|
'max-width': col?.width ?? false,
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
}"
|
}"
|
||||||
class="no-margin body-cell"
|
:class="[
|
||||||
:class="[getColAlign(col), col.columnClass]"
|
getColAlign(col),
|
||||||
v-if="col.visible ?? true"
|
col.columnClass,
|
||||||
|
'body-cell no-margin no-padding',
|
||||||
|
]"
|
||||||
:data-row-index="rowIndex"
|
:data-row-index="rowIndex"
|
||||||
:data-col-field="col?.name"
|
:data-col-field="col?.name"
|
||||||
:auto-foucs="col?.tabIndex"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="
|
v-if="shouldDisplayReadonly(col, rowIndex)"
|
||||||
col?.isEditable === false ||
|
class="no-padding no-margin"
|
||||||
editingRow !== rowIndex ||
|
style="
|
||||||
editingField !== col?.name
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: middle;
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<slot
|
<slot
|
||||||
|
@ -561,19 +678,18 @@ const stopEditing = () => {
|
||||||
>
|
>
|
||||||
<QIcon
|
<QIcon
|
||||||
v-if="col?.component === 'checkbox'"
|
v-if="col?.component === 'checkbox'"
|
||||||
:name="
|
:name="getCheckboxIcon(row[col?.name])"
|
||||||
row[col?.name]
|
style="color: var(--vn-text-color)"
|
||||||
? 'check_box'
|
size="var(--font-size)"
|
||||||
: 'check_box_outline_blank' ||
|
:class="
|
||||||
'indeterminate_check_box'
|
isEditable && (col?.isEditable ?? 'editable-text')
|
||||||
"
|
"
|
||||||
size="sm"
|
|
||||||
style="color: var(--vn-label-color)"
|
|
||||||
:class="col?.isEditable ?? 'editable-text'"
|
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
v-else
|
v-else
|
||||||
:class="col?.isEditable ?? 'editable-text'"
|
:class="
|
||||||
|
isEditable && (col?.isEditable ?? 'editable-text')
|
||||||
|
"
|
||||||
:style="col?.style ? col.style(row) : null"
|
:style="col?.style ? col.style(row) : null"
|
||||||
>
|
>
|
||||||
{{
|
{{
|
||||||
|
@ -584,15 +700,25 @@ const stopEditing = () => {
|
||||||
</span>
|
</span>
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else-if="isEditable">
|
||||||
<VnTableColumn
|
<VnTableColumn
|
||||||
|
ref="vnEditableCell"
|
||||||
:column="col"
|
:column="col"
|
||||||
:row="row"
|
:row="row"
|
||||||
:is-editable="col.isEditable ?? isEditable"
|
:is-editable="col.isEditable ?? isEditable"
|
||||||
v-model="row[col.name]"
|
v-model="row[col.name]"
|
||||||
component-prop="columnField"
|
component-prop="columnField"
|
||||||
class="cell-input"
|
class="cell-input q-px-xs"
|
||||||
auto-focus
|
@blur="stopEditing(rowIndex, col?.name)"
|
||||||
|
@keyup.enter="stopEditing(rowIndex, col?.name)"
|
||||||
|
@keydown.tab.prevent="
|
||||||
|
handleTabKey($event, rowIndex, col?.name)
|
||||||
|
"
|
||||||
|
@keydown.shift.tab.prevent="
|
||||||
|
handleShiftTab(rowIndex, col?.name)
|
||||||
|
"
|
||||||
|
@keydown.escape="stopEditing(rowIndex, col?.name)"
|
||||||
|
:autofocus="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</QTd>
|
</QTd>
|
||||||
|
@ -835,22 +961,23 @@ es:
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
.selection-cell {
|
||||||
|
table td:first-child {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
.side-padding {
|
.side-padding {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
.editable-text:hover {
|
.editable-text:hover {
|
||||||
border: 1px dashed var(--q-primary);
|
border-bottom: 1px dashed var(--q-primary);
|
||||||
cursor: pointer;
|
|
||||||
@extend .side-padding;
|
@extend .side-padding;
|
||||||
}
|
}
|
||||||
.editable-text {
|
.editable-text {
|
||||||
border-radius: 16px;
|
border-bottom: 1px dashed var(--vn-label-color);
|
||||||
box-shadow: 0 0 1px 1px rgb(56, 56, 56);
|
|
||||||
border: 1px dashed rgba(0, 0, 0, 0.15);
|
|
||||||
@extend .side-padding;
|
@extend .side-padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cell-input {
|
.cell-input {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
|
@ -17,6 +17,8 @@ const $props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['blur']);
|
||||||
|
|
||||||
const componentArray = computed(() => {
|
const componentArray = computed(() => {
|
||||||
if (typeof $props.prop === 'object') return [$props.prop];
|
if (typeof $props.prop === 'object') return [$props.prop];
|
||||||
return $props.prop;
|
return $props.prop;
|
||||||
|
@ -54,6 +56,7 @@ function toValueAttrs(attrs) {
|
||||||
v-bind="mix(toComponent).attrs"
|
v-bind="mix(toComponent).attrs"
|
||||||
v-on="mix(toComponent).event ?? {}"
|
v-on="mix(toComponent).event ?? {}"
|
||||||
v-model="model"
|
v-model="model"
|
||||||
|
@blur="emit('blur')"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -9,6 +9,7 @@ const emit = defineEmits([
|
||||||
'update:options',
|
'update:options',
|
||||||
'keyup.enter',
|
'keyup.enter',
|
||||||
'remove',
|
'remove',
|
||||||
|
'blur',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
|
@ -88,6 +89,7 @@ defineExpose({
|
||||||
:type="$attrs.type"
|
:type="$attrs.type"
|
||||||
:class="{ required: $attrs.required }"
|
:class="{ required: $attrs.required }"
|
||||||
@keyup.enter="emit('keyup.enter')"
|
@keyup.enter="emit('keyup.enter')"
|
||||||
|
@blur="emit('blur')"
|
||||||
:clearable="false"
|
:clearable="false"
|
||||||
:rules="mixinRules"
|
:rules="mixinRules"
|
||||||
:lazy-rules="true"
|
:lazy-rules="true"
|
||||||
|
|
|
@ -27,6 +27,7 @@ const isPopupOpen = ref();
|
||||||
const hover = ref();
|
const hover = ref();
|
||||||
const mask = ref();
|
const mask = ref();
|
||||||
const $attrs = useAttrs();
|
const $attrs = useAttrs();
|
||||||
|
const emit = defineEmits(['blur']);
|
||||||
|
|
||||||
const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
|
const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
|
||||||
|
|
||||||
|
@ -102,6 +103,7 @@ const styleAttrs = computed(() => {
|
||||||
:rules="mixinRules"
|
:rules="mixinRules"
|
||||||
:clearable="false"
|
:clearable="false"
|
||||||
@click="isPopupOpen = true"
|
@click="isPopupOpen = true"
|
||||||
|
@blur="emit('blur')"
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
>
|
>
|
||||||
<template #append>
|
<template #append>
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
import VnInput from 'src/components/common/VnInput.vue';
|
||||||
const model = defineModel({ type: [Number, String] });
|
const model = defineModel({ type: [Number, String] });
|
||||||
|
const emit = defineEmits(['blur']);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VnInput v-bind="$attrs" v-model.number="model" type="number" />
|
<VnInput v-bind="$attrs" v-model.number="model" type="number" @blur="emit('blur')" />
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -24,6 +24,7 @@ const mixinRules = [requiredFieldRule, ...($attrs.rules ?? [])];
|
||||||
const dateFormat = 'HH:mm';
|
const dateFormat = 'HH:mm';
|
||||||
const isPopupOpen = ref();
|
const isPopupOpen = ref();
|
||||||
const hover = ref();
|
const hover = ref();
|
||||||
|
const emit = defineEmits(['blur']);
|
||||||
|
|
||||||
const styleAttrs = computed(() => {
|
const styleAttrs = computed(() => {
|
||||||
return props.isOutlined
|
return props.isOutlined
|
||||||
|
@ -80,6 +81,7 @@ function dateToTime(newDate) {
|
||||||
style="min-width: 100px"
|
style="min-width: 100px"
|
||||||
:rules="mixinRules"
|
:rules="mixinRules"
|
||||||
@click="isPopupOpen = false"
|
@click="isPopupOpen = false"
|
||||||
|
@blur="emit('blur')"
|
||||||
type="time"
|
type="time"
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
>
|
>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { ref, toRefs, computed, watch, onMounted, useAttrs } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import FetchData from 'src/components/FetchData.vue';
|
import FetchData from 'src/components/FetchData.vue';
|
||||||
import { useValidator } from 'src/composables/useValidator';
|
import { useValidator } from 'src/composables/useValidator';
|
||||||
const emit = defineEmits(['update:modelValue', 'update:options', 'remove']);
|
const emit = defineEmits(['update:modelValue', 'update:options', 'remove', 'blur']);
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
|
@ -247,6 +247,7 @@ const getVal = (val) => ($props.useLike ? { like: `%${val}%` } : val);
|
||||||
:option-value="optionValue"
|
:option-value="optionValue"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
@filter="filterHandler"
|
@filter="filterHandler"
|
||||||
|
@blur="() => emit('blur')"
|
||||||
:emit-value="nullishToTrue($attrs['emit-value'])"
|
:emit-value="nullishToTrue($attrs['emit-value'])"
|
||||||
:map-options="nullishToTrue($attrs['map-options'])"
|
:map-options="nullishToTrue($attrs['map-options'])"
|
||||||
:use-input="nullishToTrue($attrs['use-input'])"
|
:use-input="nullishToTrue($attrs['use-input'])"
|
||||||
|
|
|
@ -14,7 +14,7 @@ const $props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const options = ref([]);
|
const options = ref([]);
|
||||||
|
const emit = defineEmits(['blur']);
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(async () => {
|
||||||
const { url, optionValue, optionLabel } = useAttrs();
|
const { url, optionValue, optionLabel } = useAttrs();
|
||||||
const findBy = $props.find ?? url?.charAt(0)?.toLocaleLowerCase() + url?.slice(1, -1);
|
const findBy = $props.find ?? url?.charAt(0)?.toLocaleLowerCase() + url?.slice(1, -1);
|
||||||
|
@ -35,5 +35,5 @@ onBeforeMount(async () => {
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VnSelect v-bind="$attrs" :options="$attrs.options ?? options" />
|
<VnSelect v-bind="$attrs" :options="$attrs.options ?? options" @blur="emit('blur')" />
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -144,11 +144,6 @@ select:-webkit-autofill {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vn-table-separation-row {
|
|
||||||
height: 16px !important;
|
|
||||||
background-color: var(--vn-section-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Estilo para el asterisco en campos requeridos */
|
/* Estilo para el asterisco en campos requeridos */
|
||||||
.q-field.required .q-field__label:after {
|
.q-field.required .q-field__label:after {
|
||||||
content: ' *';
|
content: ' *';
|
||||||
|
@ -263,7 +258,6 @@ input::-webkit-inner-spin-button {
|
||||||
font-size: 11pt;
|
font-size: 11pt;
|
||||||
}
|
}
|
||||||
td {
|
td {
|
||||||
font-size: 11pt;
|
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Checkbox Focus with Button</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
}
|
||||||
|
.checkbox-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
input[type='checkbox'] {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
/* Estilos para el foco */
|
||||||
|
input[type='checkbox']:focus {
|
||||||
|
outline: 2px solid blue;
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="checkbox-container">
|
||||||
|
<input type="checkbox" id="myCheckbox" />
|
||||||
|
<label for="myCheckbox">Acepto los términos y condiciones</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Botón para enfocar el checkbox -->
|
||||||
|
<button id="focusButton">Dar foco al checkbox</button>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const checkbox = document.getElementById('myCheckbox');
|
||||||
|
const focusButton = document.getElementById('focusButton');
|
||||||
|
|
||||||
|
// Manejador de eventos para cuando el checkbox recibe el foco
|
||||||
|
checkbox.addEventListener('focus', () => {
|
||||||
|
console.log('El checkbox tiene el foco');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Manejador de eventos para cuando el checkbox pierde el foco
|
||||||
|
checkbox.addEventListener('blur', () => {
|
||||||
|
console.log('El checkbox perdió el foco');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Manejador de eventos para cuando se cambia el estado del checkbox
|
||||||
|
checkbox.addEventListener('change', (event) => {
|
||||||
|
if (event.target.checked) {
|
||||||
|
console.log('El checkbox está marcado');
|
||||||
|
} else {
|
||||||
|
console.log('El checkbox no está marcado');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Dar foco al checkbox cuando se presiona el botón
|
||||||
|
focusButton.addEventListener('click', () => {
|
||||||
|
checkbox.focus();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -157,6 +157,7 @@ const onFilterTravelSelected = (formData, id) => {
|
||||||
</VnRow>
|
</VnRow>
|
||||||
<VnRow>
|
<VnRow>
|
||||||
<QCheckbox
|
<QCheckbox
|
||||||
|
v-focus
|
||||||
v-model="data.isOrdered"
|
v-model="data.isOrdered"
|
||||||
:label="t('entry.basicData.ordered')"
|
:label="t('entry.basicData.ordered')"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -9,20 +9,24 @@ import VnTable from 'src/components/VnTable/VnTable.vue';
|
||||||
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
|
||||||
import FetchedTags from 'components/ui/FetchedTags.vue';
|
import FetchedTags from 'components/ui/FetchedTags.vue';
|
||||||
import VnColor from 'src/components/VnColor.vue';
|
import VnColor from 'src/components/VnColor.vue';
|
||||||
import { dashIfEmpty } from 'src/filters';
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const selectedRows = ref([]);
|
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
const selectedRows = ref([]);
|
||||||
const columns = [
|
const columns = [
|
||||||
|
{
|
||||||
|
name: 'buyFk',
|
||||||
|
isId: true,
|
||||||
|
visible: false,
|
||||||
|
isEditable: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
align: 'center',
|
align: 'center',
|
||||||
label: 'Nv',
|
label: 'Nv',
|
||||||
name: 'isIgnored',
|
name: 'isIgnored',
|
||||||
component: 'checkbox',
|
component: 'checkbox',
|
||||||
width: '35px',
|
width: '35px',
|
||||||
tabIndex: 1,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'center',
|
align: 'center',
|
||||||
|
@ -31,12 +35,12 @@ const columns = [
|
||||||
component: 'input',
|
component: 'input',
|
||||||
create: true,
|
create: true,
|
||||||
width: '45px',
|
width: '45px',
|
||||||
tabIndex: 2,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '',
|
label: '',
|
||||||
name: 'hex',
|
name: 'hex',
|
||||||
columnSearch: false,
|
columnSearch: false,
|
||||||
|
isEditable: false,
|
||||||
width: '5px',
|
width: '5px',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -61,8 +65,7 @@ const columns = [
|
||||||
label: t('Sti.'),
|
label: t('Sti.'),
|
||||||
name: 'stickers',
|
name: 'stickers',
|
||||||
component: 'number',
|
component: 'number',
|
||||||
width: '50px',
|
width: '35px',
|
||||||
tabIndex: 1,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'center',
|
align: 'center',
|
||||||
|
@ -170,6 +173,7 @@ const columns = [
|
||||||
label: 'Tags',
|
label: 'Tags',
|
||||||
name: 'tags',
|
name: 'tags',
|
||||||
width: '120px',
|
width: '120px',
|
||||||
|
columnSearch: false,
|
||||||
isEditable: false,
|
isEditable: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -180,26 +184,26 @@ const columns = [
|
||||||
width: '35px',
|
width: '35px',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
onMounted(() => (stateStore.rightDrawer = false));
|
onMounted(() => {
|
||||||
|
stateStore.rightDrawer = false;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VnSubToolbar />
|
<VnSubToolbar />
|
||||||
<VnTable
|
<VnTable
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
data-key="EntryBuys"
|
data-key="EntryBuys"
|
||||||
:url="`Entries/${route.params.id}/getBuys`"
|
:url="`Entries/${route.params.id}/getBuys`"
|
||||||
|
:disable-option="{ card: true }"
|
||||||
:right-search="false"
|
:right-search="false"
|
||||||
:row-click="false"
|
:row-click="false"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:disable-option="{ card: true }"
|
|
||||||
class="buyList"
|
class="buyList"
|
||||||
is-editable
|
is-editable
|
||||||
auto-load
|
auto-load
|
||||||
>
|
>
|
||||||
<template #column-hex="{ row }">
|
<template #column-hex>
|
||||||
{{ console.log('row?.hex: ', row?.hex) }}
|
<VnColor :colors="['#ff0000', '#ffff00', '#ff0000']" style="height: 100%" />
|
||||||
<VnColor :colors="['#ff0000']" />
|
|
||||||
</template>
|
</template>
|
||||||
<template #column-name="{ row }">
|
<template #column-name="{ row }">
|
||||||
<span class="link">
|
<span class="link">
|
||||||
|
@ -211,11 +215,19 @@ onMounted(() => (stateStore.rightDrawer = false));
|
||||||
<FetchedTags :item="row" :columns="3" />
|
<FetchedTags :item="row" :columns="3" />
|
||||||
</template>
|
</template>
|
||||||
<template #column-stickers="{ row }">
|
<template #column-stickers="{ row }">
|
||||||
<span>{{ row.stickers }}</span>
|
<span style="color: var(--vn-label-color)">{{ row.printedStickers }}</span>
|
||||||
<span style="color: var(--vn-label-color)">/{{ row.printedStickers }}</span>
|
<span>/{{ row.stickers }}</span>
|
||||||
</template>
|
</template>
|
||||||
</VnTable>
|
</VnTable>
|
||||||
</template>
|
</template>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.q-checkbox__inner--dark {
|
||||||
|
&__inner {
|
||||||
|
border-radius: 0% !important;
|
||||||
|
background-color: rosybrown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<i18n>
|
<i18n>
|
||||||
es:
|
es:
|
||||||
Article: Artículo
|
Article: Artículo
|
||||||
|
|
|
@ -271,67 +271,6 @@ const fetchEntryBuys = async () => {
|
||||||
:disable="true"
|
:disable="true"
|
||||||
/>
|
/>
|
||||||
</QCard>
|
</QCard>
|
||||||
<!-- <QCard class="vn-two" style="min-width: 100%">
|
|
||||||
<a class="header header-link">
|
|
||||||
{{ t('entry.summary.buys') }}
|
|
||||||
<QIcon name="open_in_new" />
|
|
||||||
</a>
|
|
||||||
<QTable
|
|
||||||
:rows="entryBuys"
|
|
||||||
:columns="entriesTableColumns"
|
|
||||||
row-key="index"
|
|
||||||
class="full-width q-mt-md"
|
|
||||||
:no-data-label="t('globals.noResults')"
|
|
||||||
>
|
|
||||||
<template #body="{ cols, row, rowIndex }">
|
|
||||||
<QTr no-hover>
|
|
||||||
<QTd v-for="col in cols" :key="col?.name">
|
|
||||||
<component
|
|
||||||
:is="tableColumnComponents[col?.name].component()"
|
|
||||||
v-bind="tableColumnComponents[col?.name].props()"
|
|
||||||
@click="tableColumnComponents[col?.name].event()"
|
|
||||||
class="col-content"
|
|
||||||
>
|
|
||||||
<template
|
|
||||||
v-if="
|
|
||||||
col?.name !== 'observation' &&
|
|
||||||
col?.name !== 'isConfirmed'
|
|
||||||
"
|
|
||||||
>{{ col.value }}</template
|
|
||||||
>
|
|
||||||
<QTooltip v-if="col.toolTip">{{
|
|
||||||
col.toolTip
|
|
||||||
}}</QTooltip>
|
|
||||||
</component>
|
|
||||||
</QTd>
|
|
||||||
</QTr>
|
|
||||||
<QTr no-hover>
|
|
||||||
<QTd>
|
|
||||||
<span>{{ row.item.itemType.code }}</span>
|
|
||||||
</QTd>
|
|
||||||
<QTd>
|
|
||||||
<span>{{ row.item.id }}</span>
|
|
||||||
</QTd>
|
|
||||||
<QTd>
|
|
||||||
<span>{{ row.item.size }}</span>
|
|
||||||
</QTd>
|
|
||||||
<QTd>
|
|
||||||
<span>{{ toCurrency(row.item.minPrice) }}</span>
|
|
||||||
</QTd>
|
|
||||||
<QTd colspan="6">
|
|
||||||
<span>{{ row.item.concept }}</span>
|
|
||||||
<span v-if="row.item.subName" class="subName">
|
|
||||||
{{ row.item.subName }}
|
|
||||||
</span>
|
|
||||||
<FetchedTags :item="row.item" />
|
|
||||||
</QTd>
|
|
||||||
</QTr>
|
|
||||||
<QTr v-if="rowIndex !== entryBuys.length - 1">
|
|
||||||
<QTd colspan="10" class="vn-table-separation-row" />
|
|
||||||
</QTr>
|
|
||||||
</template>
|
|
||||||
</QTable>
|
|
||||||
</QCard> -->
|
|
||||||
</template>
|
</template>
|
||||||
</CardSummary>
|
</CardSummary>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -21,9 +21,8 @@ const $props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QPopupProxy>
|
<QPopupProxy style="max-width: 10px">
|
||||||
<ItemDescriptor
|
<ItemDescriptor
|
||||||
v-if="$props.id"
|
v-if="$props.id"
|
||||||
:id="$props.id"
|
:id="$props.id"
|
||||||
|
|
Loading…
Reference in New Issue