add new export option with permissions close #13

This commit is contained in:
Adrian Zürcher
2025-11-12 17:17:43 +01:00
parent 14d2270260
commit fb27e9c026
10 changed files with 87 additions and 6 deletions

View File

@@ -4,6 +4,7 @@ import type { Member, Members } from 'src/vueLib/models/member';
import { useNotify } from 'src/vueLib/general/useNotify';
import { i18n } from 'boot/lang';
import { useResponsibleTable } from '../responsible/ResponsibleTable';
import { appName } from 'src/vueLib/models/settings';
export function useMemberTable() {
const members = ref<Members>([]);
@@ -253,6 +254,47 @@ export function useMemberTable() {
});
}
function exportCsv() {
const comma = ';';
// Extract only columns that have a field (not icons/options)
const exportableColumns = columns.value.filter(
(col) => typeof col.field === 'string' && col.field !== 'cake' && col.field !== 'option',
) as { field: keyof Member; label: string }[];
// Build CSV header row
const header = exportableColumns.map((col) => col.field).join(comma);
// Build CSV rows
const data = members.value.map((member) =>
exportableColumns
.map((col) => {
const value = member[col.field];
// handle nested objects (e.g. responsiblePerson)
if (typeof value === 'object' && value !== null) {
if ('firstName' in value && 'lastName' in value)
return `"${value.firstName} ${value.lastName}"`;
return `"${JSON.stringify(value)}"`;
}
return `"${value ?? ''}"`;
})
.join(comma),
);
// Combine into CSV string
const csv = [header, ...data].join('\n');
// Create blob and trigger download
const BOM = '\uFEFF';
const blob = new Blob([BOM + csv], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', i18n.global.t(appName.value) + '.csv');
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
return {
members,
responsibles,
@@ -263,5 +305,6 @@ export function useMemberTable() {
updateMembers,
isXDaysBeforeAnnualDate,
disableColumns,
exportCsv,
};
}

View File

@@ -43,7 +43,7 @@
<q-tooltip>{{ $t('selectMemberOptions') }}</q-tooltip>
</q-btn>
<q-btn
v-if="user.isPermittedTo('members', 'write')"
v-if="user.isPermittedTo('members', 'import')"
dense
flat
icon="upload"
@@ -51,6 +51,15 @@
>
<q-tooltip>{{ $t('importCSV') }}</q-tooltip>
</q-btn>
<q-btn
v-if="user.isPermittedTo('members', 'export')"
dense
flat
icon="download"
@click="exportCsv"
>
<q-tooltip>{{ $t('exportCSV') }}</q-tooltip>
</q-btn>
</q-btn-group>
<div v-if="selectOption && selected.length > 0">
<q-btn
@@ -240,6 +249,7 @@ const {
updateMembers,
isXDaysBeforeAnnualDate,
disableColumns,
exportCsv,
} = useMemberTable();
//load on mounting page