import { ComputedRef, Ref, ref } from 'vue';
import { Router } from 'vue-router';
import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';
import { buildSettingsPayloadForSave } from 'src/helpers/settingsSaveHelper';
import { usePendingRowChanges } from 'src/composables/usePendingRowChanges';
import type { Table } from '../stores/main/models';
interface Params {
selectedTable: Ref
;
loading: Ref;
isAdminPage: ComputedRef;
saveTableChanges: (payload: any) => Promise;
saveTableSettings: (payload: any) => Promise;
deleteTable: (id: string) => Promise;
router: Router;
}
export function useTableActions({
selectedTable,
loading,
isAdminPage,
saveTableChanges,
saveTableSettings,
deleteTable,
router,
}: Params) {
const $q = useQuasar();
const { t } = useI18n();
const { flushPendingRowChanges } = usePendingRowChanges();
const tableMaximized: Ref = ref(false);
const showSettings: Ref = ref(false);
const showTitleDialog: Ref = ref(false);
const deleting: Ref = ref(false);
async function goBack() {
// Clear only after the navigation went through: the unsaved-changes guard
// on the table page (TablePage's onBeforeRouteLeave) may cancel it, and
// the table must stay rendered in that case.
const failure = await router.push('/');
if (!failure) selectedTable.value = null;
}
async function updateTableName(title: string) {
if (!selectedTable.value) return;
selectedTable.value.title = title;
showTitleDialog.value = false;
}
async function saveSettings() {
if (!selectedTable.value?.settings) return;
loading.value = true;
// Server-mode row changes (cell edits, added/deleted rows) are staged in
// memory until this Save; write them first. No-op when nothing is staged.
// On failure the unwritten changes stay staged, so another Save retries.
const { error: flushError } = await flushPendingRowChanges(
selectedTable.value.id
);
if (flushError) {
loading.value = false;
$q.notify({
type: 'negative',
message: t('messages.unable_to_save_changes'),
caption: t('messages.something_went_wrong'),
});
return;
}
// Server-mode tables hold one page only; their rows are written by the
// row endpoints above, never by replacing the whole source.
const source = { ...selectedTable.value.source };
if (selectedTable.value.server_mode) {
source.rows = [];
}
const { error: saveChangesError } = await saveTableChanges({
id: selectedTable.value.id,
title: selectedTable.value.title,
source,
});
if (saveChangesError) {
loading.value = false;
$q.notify({
type: 'negative',
message: t('messages.unable_to_save_changes'),
caption: t('messages.something_went_wrong'),
});
return;
}
const { error: saveSettingsError } = await saveTableSettings({
id: selectedTable.value.id,
settings: buildSettingsPayloadForSave(selectedTable.value.settings),
});
loading.value = false;
if (saveSettingsError) {
$q.notify({
type: 'negative',
message: t('messages.unable_to_save_changes'),
caption: t('messages.something_went_wrong'),
});
return;
}
$q.notify({
type: 'positive',
message: t('messages.changes_have_been_saved'),
});
}
function onShowSettings() {
showSettings.value = !showSettings.value;
}
async function onDeleteTable(id: string) {
deleting.value = true;
await deleteTable(id);
deleting.value = false;
goBack();
}
function toggleFullscreen(props: any) {
props.toggleFullscreen();
tableMaximized.value = !tableMaximized.value;
}
function toggleTitleDialog() {
if (isAdminPage.value) {
showTitleDialog.value = true;
}
}
return {
tableMaximized,
showSettings,
showTitleDialog,
deleting,
goBack,
updateTableName,
saveSettings,
onShowSettings,
onDeleteTable,
toggleFullscreen,
toggleTitleDialog,
};
}