Files
dbx/apps/desktop/src/components/generate/params/ForeignKeyParams.vue
T

122 lines
4.7 KiB
Vue

<script setup lang="ts">
import { ref, onMounted, computed } from "vue";
import { Label } from "@/components/ui/label";
import type { GeneratorParams } from "@/lib/dataGrid/dataGenerate";
import * as api from "@/lib/backend/api";
import { useI18n } from "vue-i18n";
const props = defineProps<{ params: GeneratorParams; config: any; connectionId?: string; database?: string }>();
const { t } = useI18n();
const schemas = ref<string[]>([]);
const tables = ref<{ name: string }[]>([]);
const columns = ref<{ name: string }[]>([]);
const loadingSchemas = ref(false);
const loadingTables = ref(false);
const loadingColumns = ref(false);
const fkModes = computed(() => [
{ value: "random", label: t("dataGenerate.genModes.random") },
{ value: "unique", label: t("dataGenerate.genModes.unique") },
{ value: "repeat", label: t("dataGenerate.genModes.repeat") },
]);
onMounted(async () => {
await loadSchemas();
});
async function loadSchemas() {
if (!props.connectionId || !props.database) return;
loadingSchemas.value = true;
try {
schemas.value = await api.listSchemas(props.connectionId, props.database);
if (schemas.value.length === 0) schemas.value = ["main"];
if (props.params.fkSchema) await loadTables();
} catch {
schemas.value = ["main"];
} finally {
loadingSchemas.value = false;
}
}
async function loadTables() {
if (!props.connectionId || !props.database || !props.params.fkSchema) return;
loadingTables.value = true;
try {
tables.value = await api.listTables(props.connectionId, props.database, props.params.fkSchema);
if (props.params.fkTable) await loadColumns();
} catch {
tables.value = [];
} finally {
loadingTables.value = false;
}
}
async function loadColumns() {
if (!props.connectionId || !props.database || !props.params.fkSchema || !props.params.fkTable) return;
loadingColumns.value = true;
try {
const cols = await api.getColumns(props.connectionId, props.database, props.params.fkSchema, props.params.fkTable);
columns.value = cols.map((c: any) => ({ name: c.name }));
} catch {
columns.value = [];
} finally {
loadingColumns.value = false;
}
}
function onSchemaChange(val: string) {
props.params.fkSchema = val;
props.params.fkTable = undefined;
props.params.fkField = undefined;
tables.value = [];
columns.value = [];
void loadTables();
}
function onTableChange(val: string) {
props.params.fkTable = val;
props.params.fkField = undefined;
columns.value = [];
void loadColumns();
}
</script>
<template>
<div class="space-y-3">
<div class="rounded-md border bg-muted/10 p-3 space-y-2">
<div class="grid grid-cols-[60px_1fr] items-center gap-2 text-xs">
<Label class="text-muted-foreground">{{ t("dataGenerate.schema") }}</Label>
<select v-model="props.params.fkSchema" class="h-7 rounded border bg-background px-2 text-xs" @change="onSchemaChange(($event.target as HTMLSelectElement).value)">
<option v-if="loadingSchemas" disabled>{{ t("dataGenerate.loading") }}</option>
<option v-for="s in schemas" :key="s" :value="s">{{ s }}</option>
</select>
</div>
<div class="grid grid-cols-[60px_1fr] items-center gap-2 text-xs">
<Label class="text-muted-foreground">{{ t("dataGenerate.tableLabel") }}</Label>
<select v-model="props.params.fkTable" class="h-7 rounded border bg-background px-2 text-xs" @change="onTableChange(($event.target as HTMLSelectElement).value)">
<option v-if="loadingTables" disabled>{{ t("dataGenerate.loading") }}</option>
<option v-for="tbl in tables" :key="tbl.name" :value="tbl.name">{{ tbl.name }}</option>
</select>
</div>
<div class="grid grid-cols-[60px_1fr] items-center gap-2 text-xs">
<Label class="text-muted-foreground">{{ t("dataGenerate.columnLabel") }}</Label>
<select v-model="props.params.fkField" class="h-7 rounded border bg-background px-2 text-xs">
<option v-if="loadingColumns" disabled>{{ t("dataGenerate.loading") }}</option>
<option v-for="c in columns" :key="c.name" :value="c.name">{{ c.name }}</option>
</select>
</div>
</div>
<div class="rounded-md border bg-muted/10 p-3">
<div class="text-xs text-muted-foreground mb-2">{{ t("dataGenerate.genMode") }}</div>
<div class="flex items-center gap-2 text-xs flex-wrap">
<button v-for="m in fkModes" :key="m.value" type="button" class="px-2 py-1 rounded border text-xs" :class="(params.fkMode || 'random') === m.value ? 'bg-primary text-primary-foreground border-primary' : 'bg-background'" @click="params.fkMode = m.value as 'random' | 'unique' | 'repeat'">
{{ m.label }}
</button>
</div>
</div>
</div>
</template>