Enhance form column settings and table display

- Add "Show all" and "Hide all" buttons in column settings modal
- Improve column width handling and default width management
- Update OpenSelect and OpenText components to support more flexible prop types
- Add z-index to table header for better visual hierarchy
- Refactor column width property from `cell_width` to `width`
This commit is contained in:
Julien Nahum
2025-02-17 11:27:58 +01:00
parent 0d6bd1bfde
commit 55b0f57741
8 changed files with 203 additions and 38 deletions

View File

@@ -2,10 +2,14 @@
<modal
compact-header
:show="show"
v-bind="$attrs"
@close="$emit('close')"
>
<template #icon>
<Icon name="heroicons:adjustments-horizontal" class="w-8 h-8" />
<Icon
name="heroicons:adjustments-horizontal"
class="w-8 h-8"
/>
</template>
<template #title>
Manage Columns
@@ -21,7 +25,24 @@
class="font-semibold mb-2"
:class="{ 'mt-4': sectionIndex > 0 }"
>
{{ section.title }}
<div class="flex items-center justify-between">
<span>{{ section.title }}</span>
<div class="flex items-center gap-2 text-xs text-gray-500">
<button
class="hover:text-gray-700"
@click="toggleAllColumns(section.fields, true)"
>
Show all
</button>
<span class="text-gray-300">|</span>
<button
class="hover:text-gray-700"
@click="toggleAllColumns(section.fields, false)"
>
Hide all
</button>
</div>
</div>
</h4>
<div class="border border-gray-300">
<div class="grid grid-cols-[1fr,auto,auto] gap-4 px-4 py-2 bg-gray-50 border-b border-gray-300">
@@ -46,8 +67,8 @@
</p>
<div class="flex justify-center w-20">
<ToggleSwitchInput
v-model="displayColumns[field.id]"
wrapper-class="mb-0"
v-model="computedDisplayColumns[field.id]"
wrapper-class="my-0"
label=""
:name="`display-${field.id}`"
@update:model-value="onChangeDisplayColumns"
@@ -55,8 +76,8 @@
</div>
<div class="flex justify-center w-20">
<ToggleSwitchInput
v-model="wrapColumns[field.id]"
wrapper-class="mb-0"
v-model="computedWrapColumns[field.id]"
wrapper-class="my-0"
label=""
:name="`wrap-${field.id}`"
/>
@@ -85,6 +106,14 @@ const props = defineProps({
columns: {
type: Array,
default: () => []
},
displayColumns: {
type: Object,
default: () => ({})
},
wrapColumns: {
type: Object,
default: () => ({})
}
})
@@ -122,16 +151,24 @@ const sections = computed(() => [
])
// Column preferences storage
const storageKey = computed(() => `column-preferences-formid-${props.form.id}`)
const columnPreferences = useStorage(
computed(() => props.form ? `column-preferences-formid-${props.form.id}` : null),
storageKey.value,
{
display: {},
wrap: {},
widths: {}
},
localStorage,
{
onError: (error) => {
console.error('Storage error:', error)
}
}
)
const displayColumns = computed({
const computedDisplayColumns = computed({
get: () => columnPreferences.value.display,
set: (val) => {
columnPreferences.value.display = val
@@ -139,7 +176,7 @@ const displayColumns = computed({
}
})
const wrapColumns = computed({
const computedWrapColumns = computed({
get: () => columnPreferences.value.wrap,
set: (val) => {
columnPreferences.value.wrap = val
@@ -164,12 +201,18 @@ function preserveColumnWidths(newColumns, existingColumns = []) {
// Then fallback to form properties
const existing = existingColumns?.find(e => e.id === col.id)
const width = storedWidth || currentCol?.cell_width || currentCol?.width || existing?.cell_width || existing?.width || col.width || 150
// Convert any non-numeric width to default
const defaultWidth = 250
let width = storedWidth || currentCol?.width || existing?.width || defaultWidth
// If width is not a number or is 'full', use default width
if (typeof width !== 'number' || isNaN(width)) {
width = defaultWidth
}
return {
...col,
width,
cell_width: width
width
}
})
}
@@ -187,8 +230,8 @@ watch(() => props.columns, (newColumns) => {
const widths = {}
newColumns.forEach(col => {
if (col.cell_width) {
widths[col.id] = col.cell_width
if (col.width) {
widths[col.id] = col.width
}
})
@@ -199,42 +242,63 @@ watch(() => props.columns, (newColumns) => {
watch(() => props.form, (newForm) => {
if (!newForm) return
const properties = newForm.properties || []
const properties = candidatesProperties.value
const storedPrefs = columnPreferences.value
const removedProperties = newForm.removed_properties || []
// Initialize display columns if not set
if (!Object.keys(storedPrefs.display).length) {
// Set all non-removed properties to visible by default
properties.forEach((field) => {
storedPrefs.display[field.id] = true
})
// Also handle removed properties
removedProperties.forEach((field) => {
storedPrefs.display[field.id] = false
})
}
// Initialize wrap columns if not set
if (!Object.keys(storedPrefs.wrap).length) {
properties.forEach((field) => {
[...properties, ...removedProperties].forEach((field) => {
storedPrefs.wrap[field.id] = false
})
}
// Initialize widths if not set
if (!Object.keys(storedPrefs.widths).length) {
[...properties, ...removedProperties].forEach((field) => {
const defaultWidth = 150
storedPrefs.widths[field.id] = field.width || defaultWidth
})
}
// Emit initial values
emit('update:displayColumns', storedPrefs.display)
emit('update:wrapColumns', storedPrefs.wrap)
// Emit initial columns (all visible by default)
const initialColumns = clonedeep(candidatesProperties.value)
.concat(props.form?.removed_properties || [])
.filter((field) => storedPrefs.display[field.id] !== false) // Show all columns by default unless explicitly hidden
// Emit initial columns (all non-removed visible by default)
const initialColumns = clonedeep(properties)
.concat(removedProperties)
.filter((field) => storedPrefs.display[field.id] !== false)
// Preserve any existing column widths
const columnsWithWidths = preserveColumnWidths(initialColumns, props.form.properties)
const columnsWithWidths = preserveColumnWidths(initialColumns, properties)
emit('update:columns', columnsWithWidths)
}, { immediate: true })
function toggleAllColumns(fields, show) {
fields.forEach((field) => {
computedDisplayColumns.value[field.id] = show
})
onChangeDisplayColumns()
}
function onChangeDisplayColumns() {
if (!import.meta.client) return
const properties = clonedeep(candidatesProperties.value)
.concat(props.form?.removed_properties || [])
.filter((field) => displayColumns.value[field.id] === true)
.filter((field) => computedDisplayColumns.value[field.id] === true)
// Preserve existing column widths when toggling visibility
const columnsWithWidths = preserveColumnWidths(properties, props.form.properties)

View File

@@ -10,11 +10,14 @@
<!-- Settings Modal -->
<form-columns-settings-modal
v-if="form"
:show="showColumnsModal"
:form="form"
:columns="properties"
v-model:display-columns="displayColumns"
v-model:wrap-columns="wrapColumns"
:display-columns="displayColumns"
:wrap-columns="wrapColumns"
@update:display-columns="displayColumns = $event"
@update:wrap-columns="wrapColumns = $event"
@close="showColumnsModal = false"
@update:columns="onColumnUpdated"
/>
@@ -225,6 +228,7 @@ export default {
},
onColumnUpdated(columns) {
this.properties = columns
this.dataChanged()
},
onUpdateRecord(submission) {
this.recordStore.save(submission)