feat(settings): add global date and time formats

This commit is contained in:
zipg authored and GitHub committed 2026-07-16 14:49:28 +08:00
1 parent df0415333a
commit 0a1efdcb85
31 files changed
+1109 -88

No files matched your search

@@ -112,6 +112,7 @@ import { DEFAULT_WEB_DAV_AUTO_UPLOAD_INTERVAL_MINUTES, DEFAULT_WEB_DAV_REMOTE_PA
import { apiUrl } from "@/lib/common/webPath";
import { DEFAULT_UI_FONT_FAMILY, SYSTEM_UI_FONT_FAMILY } from "@/lib/app/appFonts";
import { buildAppSupportInfoRows, formatAppSupportInfoForClipboard, type AppSupportInfoLabels } from "@/lib/app/supportInfo";
import { DateTimePatterns, normalizeSupportedDateTimePattern } from "@/lib/dataGrid/columnFormatter";
const { t } = useI18n();
const { toast } = useToast();
@@ -340,6 +341,9 @@ const editSidebarHiddenTablePrefixes = ref(settingsStore.editorSettings.sidebarH
const editSidebarHideTableComments = ref(settingsStore.editorSettings.sidebarHideTableComments);
const editSidebarAllowHorizontalScroll = ref(settingsStore.editorSettings.sidebarAllowHorizontalScroll);
const editExportBatchSize = ref(settingsStore.editorSettings.exportBatchSize);
const editGlobalDateTimeDisplayFormat = ref(settingsStore.editorSettings.globalDateTimeDisplayFormat);
const editGlobalDateTimeExportFormat = ref(settingsStore.editorSettings.globalDateTimeExportFormat);
const editGlobalDateTimeImportFormat = ref(settingsStore.editorSettings.globalDateTimeImportFormat);
const editExportRowLimitEnabled = ref(settingsStore.editorSettings.exportRowLimitEnabled);
const editExportRowLimit = ref(settingsStore.editorSettings.exportRowLimit);
const editQueryExportKeysetOptimizationEnabled = ref(settingsStore.editorSettings.queryExportKeysetOptimizationEnabled);
@@ -427,6 +431,9 @@ function currentEditorSettingsDraft(): EditorSettingsDraft {
sidebarAllowHorizontalScroll: editSidebarAllowHorizontalScroll.value,
sidebarHiddenTablePrefixes: normalizeSidebarHiddenTablePrefixes(editSidebarHiddenTablePrefixes.value),
exportBatchSize: editExportBatchSize.value,
globalDateTimeDisplayFormat: editGlobalDateTimeDisplayFormat.value,
globalDateTimeExportFormat: editGlobalDateTimeExportFormat.value,
globalDateTimeImportFormat: editGlobalDateTimeImportFormat.value,
exportRowLimitEnabled: editExportRowLimitEnabled.value,
exportRowLimit: editExportRowLimit.value,
queryExportKeysetOptimizationEnabled: editQueryExportKeysetOptimizationEnabled.value,
@@ -704,6 +711,9 @@ function syncEditorSettingsDraftFromStore() {
editSidebarHideTableComments.value = settingsStore.editorSettings.sidebarHideTableComments;
editSidebarAllowHorizontalScroll.value = settingsStore.editorSettings.sidebarAllowHorizontalScroll;
editExportBatchSize.value = settingsStore.editorSettings.exportBatchSize;
editGlobalDateTimeDisplayFormat.value = settingsStore.editorSettings.globalDateTimeDisplayFormat;
editGlobalDateTimeExportFormat.value = settingsStore.editorSettings.globalDateTimeExportFormat;
editGlobalDateTimeImportFormat.value = settingsStore.editorSettings.globalDateTimeImportFormat;
editExportRowLimitEnabled.value = settingsStore.editorSettings.exportRowLimitEnabled;
editExportRowLimit.value = settingsStore.editorSettings.exportRowLimit;
editQueryExportKeysetOptimizationEnabled.value = settingsStore.editorSettings.queryExportKeysetOptimizationEnabled;
@@ -910,6 +920,9 @@ function resetDefaultsForTab(tab: SettingsCategory) {
editDuckDbWorkerMaxProcesses.value = DEFAULT_DESKTOP_SETTINGS.duckdb_worker_max_processes;
editTableColumnTemplateRows.value = tableColumnTemplateRowsFromSettings(DEFAULT_EDITOR_SETTINGS.tableColumnTemplateFields);
editExportBatchSize.value = DEFAULT_EDITOR_SETTINGS.exportBatchSize;
editGlobalDateTimeDisplayFormat.value = DEFAULT_EDITOR_SETTINGS.globalDateTimeDisplayFormat;
editGlobalDateTimeExportFormat.value = DEFAULT_EDITOR_SETTINGS.globalDateTimeExportFormat;
editGlobalDateTimeImportFormat.value = DEFAULT_EDITOR_SETTINGS.globalDateTimeImportFormat;
editExportRowLimitEnabled.value = DEFAULT_EDITOR_SETTINGS.exportRowLimitEnabled;
editExportRowLimit.value = DEFAULT_EDITOR_SETTINGS.exportRowLimit;
editQueryExportKeysetOptimizationEnabled.value = DEFAULT_EDITOR_SETTINGS.queryExportKeysetOptimizationEnabled;
@@ -977,6 +990,9 @@ function resetAllDefaults() {
editSidebarAllowHorizontalScroll.value = DEFAULT_EDITOR_SETTINGS.sidebarAllowHorizontalScroll;
editSidebarHiddenTablePrefixes.value = DEFAULT_EDITOR_SETTINGS.sidebarHiddenTablePrefixes.join("\n");
editExportBatchSize.value = DEFAULT_EDITOR_SETTINGS.exportBatchSize;
editGlobalDateTimeDisplayFormat.value = DEFAULT_EDITOR_SETTINGS.globalDateTimeDisplayFormat;
editGlobalDateTimeExportFormat.value = DEFAULT_EDITOR_SETTINGS.globalDateTimeExportFormat;
editGlobalDateTimeImportFormat.value = DEFAULT_EDITOR_SETTINGS.globalDateTimeImportFormat;
editExportRowLimitEnabled.value = DEFAULT_EDITOR_SETTINGS.exportRowLimitEnabled;
editExportRowLimit.value = DEFAULT_EDITOR_SETTINGS.exportRowLimit;
editQueryExportKeysetOptimizationEnabled.value = DEFAULT_EDITOR_SETTINGS.queryExportKeysetOptimizationEnabled;
@@ -3590,6 +3606,62 @@ onUnmounted(cleanupPreviewEditor);
<Separator />
</template>
<div class="space-y-3">
<div class="text-sm font-medium text-muted-foreground">{{ t("settings.dateTimeSection") }}</div>
<div class="grid gap-3 rounded-md border bg-muted/20 px-3 py-3 sm:grid-cols-[minmax(0,1fr)_minmax(220px,0.8fr)] sm:items-center">
<div>
<Label>{{ t("settings.globalDateTimeDisplayFormat") }}</Label>
<p class="mt-1 text-xs text-muted-foreground">{{ t("settings.globalDateTimeDisplayFormatDescription") }}</p>
</div>
<SearchableSelect
v-model="editGlobalDateTimeDisplayFormat"
:options="DateTimePatterns"
:placeholder="t('settings.dateTimeFormatRaw')"
:search-placeholder="t('settings.dateTimeFormatSearchPlaceholder')"
:empty-text="t('settings.dateTimeFormatEmpty')"
:normalize-custom="normalizeSupportedDateTimePattern"
allow-custom
clearable
trigger-variant="outline"
trigger-class="h-9 w-full max-w-none justify-between"
/>
<div>
<Label>{{ t("settings.globalDateTimeExportFormat") }}</Label>
<p class="mt-1 text-xs text-muted-foreground">{{ t("settings.globalDateTimeExportFormatDescription") }}</p>
</div>
<SearchableSelect
v-model="editGlobalDateTimeExportFormat"
:options="DateTimePatterns"
:placeholder="t('settings.dateTimeFormatRaw')"
:search-placeholder="t('settings.dateTimeFormatSearchPlaceholder')"
:empty-text="t('settings.dateTimeFormatEmpty')"
:normalize-custom="normalizeSupportedDateTimePattern"
allow-custom
clearable
trigger-variant="outline"
trigger-class="h-9 w-full max-w-none justify-between"
/>
<div>
<Label>{{ t("settings.globalDateTimeImportFormat") }}</Label>
<p class="mt-1 text-xs text-muted-foreground">{{ t("settings.globalDateTimeImportFormatDescription") }}</p>
</div>
<SearchableSelect
v-model="editGlobalDateTimeImportFormat"
:options="DateTimePatterns"
:placeholder="t('settings.dateTimeFormatAuto')"
:search-placeholder="t('settings.dateTimeFormatSearchPlaceholder')"
:empty-text="t('settings.dateTimeFormatEmpty')"
:normalize-custom="normalizeSupportedDateTimePattern"
allow-custom
clearable
trigger-variant="outline"
trigger-class="h-9 w-full max-w-none justify-between"
/>
</div>
</div>
<Separator />
<div class="space-y-3">
<div class="text-sm font-medium text-muted-foreground">{{ t("settings.exportSection") }}</div>
<div class="space-y-2">
@@ -963,7 +963,10 @@ function columnFormatter(columnIndex: number): ColumnFormatterConfig | undefined
const column = props.result.columns[columnIndex];
if (!column) return undefined;
const key = formatterKeyForColumn(column);
return key ? resolveColumnFormatter(settingsStore.editorSettings.columnFormatters[key], settingsStore.editorSettings.customColumnFormatters) : undefined;
return resolveColumnFormatter(key ? settingsStore.editorSettings.columnFormatters[key] : undefined, settingsStore.editorSettings.customColumnFormatters, {
pattern: settingsStore.editorSettings.globalDateTimeDisplayFormat,
columnType: props.result.column_types?.[columnIndex] ?? tableColumnForGridColumn(columnIndex)?.data_type,
});
}
function savedColumnFormatter(columnIndex: number): ColumnFormatterConfig | undefined {
@@ -11,6 +11,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
import { SearchableSelect } from "@/components/ui/searchable-select";
import { AlertTriangle, ArrowLeft, ArrowRight, Check, CheckCircle2, FileJson, FileSpreadsheet, FileText, FileUp, Loader2, RefreshCw, Square, Upload, X } from "@lucide/vue";
import { useConnectionStore } from "@/stores/connectionStore";
import { useSettingsStore } from "@/stores/settingsStore";
import { useToast } from "@/composables/useToast";
import { autoMapImportColumns, nextTableImportWizardStep, previousTableImportWizardStep, requiredImportTargetColumns, suggestImportTargetDataTypes, validateImportMappings, type TableImportWizardStep } from "@/lib/table/tableImport";
import { getDataTypeOptions } from "@/lib/table/tableStructureEditorState";
@@ -20,6 +21,7 @@ import * as api from "@/lib/backend/api";
const { t } = useI18n();
const store = useConnectionStore();
const settingsStore = useSettingsStore();
const { toast } = useToast();
const open = defineModel<boolean>("open", { default: false });
@@ -625,6 +627,7 @@ async function startImport() {
mode: targetMode.value === "create" ? "append" : importMode.value,
createTable: targetMode.value === "create",
batchSize: Math.max(1, Number(batchSize.value) || 500),
dateTimeFormat: settingsStore.editorSettings.globalDateTimeImportFormat || undefined,
},
(nextProgress) => {
progress.value = nextProgress;
@@ -700,6 +703,7 @@ async function startBatchImport() {
mode: "append",
createTable: true,
batchSize: Math.max(1, Number(batchSize.value) || 500),
dateTimeFormat: settingsStore.editorSettings.globalDateTimeImportFormat || undefined,
},
(nextProgress) => {
task.rowsImported = nextProgress.rowsImported;