extend query builder by custom join
This commit is contained in:
parent
d39ebc5029
commit
238a35da9f
6 changed files with 97 additions and 46 deletions
|
@ -71,7 +71,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-2 h-60 md:h-60 w-full overflow-y-auto">
|
||||
<div class="p-2 h-44 md:h-60 w-full overflow-y-auto">
|
||||
<textarea v-if="typeof value == 'string'" v-model="value" placeholder="SQL Query" class="h-full w-full" />
|
||||
<Table v-else v-model="value" enableOrder />
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="flex flex-row gap-2">
|
||||
<p class="w-14 min-w-14 pt-2">JOIN</p>
|
||||
<p class="w-14 min-w-14 pt-2">I_JOIN</p>
|
||||
<div class="flex flex-row flex-wrap gap-2 items-center w-full">
|
||||
<div class="flex flex-row flex-wrap gap-2 items-center justify-end w-full">
|
||||
<JoinTable
|
||||
|
@ -22,7 +22,7 @@
|
|||
<script setup lang="ts">
|
||||
import { defineComponent, type PropType } from "vue";
|
||||
import { mapActions, mapState } from "pinia";
|
||||
import { type DynamicQueryStructure } from "@/types/dynamicQueries";
|
||||
import { type DynamicQueryStructure, type JoinStructure } from "@/types/dynamicQueries";
|
||||
import { useQueryBuilderStore } from "@/stores/admin/club/queryBuilder";
|
||||
import { PlusIcon } from "@heroicons/vue/24/outline";
|
||||
import JoinTable from "./JoinTable.vue";
|
||||
|
@ -37,7 +37,7 @@ export default defineComponent({
|
|||
default: "",
|
||||
},
|
||||
modelValue: {
|
||||
type: Array as PropType<Array<DynamicQueryStructure & { foreignColumn: string }>>,
|
||||
type: Array as PropType<Array<DynamicQueryStructure & JoinStructure>>,
|
||||
default: [],
|
||||
},
|
||||
alreadyJoined: {
|
||||
|
@ -52,7 +52,7 @@ export default defineComponent({
|
|||
get() {
|
||||
return this.modelValue;
|
||||
},
|
||||
set(val: Array<DynamicQueryStructure & { foreignColumn: string }>) {
|
||||
set(val: Array<DynamicQueryStructure & JoinStructure>) {
|
||||
this.$emit("update:model-value", val);
|
||||
},
|
||||
},
|
||||
|
@ -66,6 +66,7 @@ export default defineComponent({
|
|||
where: [],
|
||||
join: [],
|
||||
orderBy: [],
|
||||
type: "defined",
|
||||
foreignColumn: "",
|
||||
});
|
||||
},
|
||||
|
|
|
@ -2,7 +2,16 @@
|
|||
<div class="flex flex-row gap-2 w-full">
|
||||
<div class="flex flex-row gap-2 w-full">
|
||||
<div class="flex flex-col gap-2 w-full">
|
||||
<select v-model="foreignColumn" class="w-full">
|
||||
<div class="flex flex-row gap-2 w-full">
|
||||
<div
|
||||
class="h-fit p-1 border border-gray-400 hover:bg-gray-200 rounded-md"
|
||||
title="Join Modus wechseln"
|
||||
@click="swapJoinType(value.type)"
|
||||
>
|
||||
<ArrowsUpDownIcon class="text-gray-500 h-6 w-6 cursor-pointer" />
|
||||
</div>
|
||||
|
||||
<select v-if="value.type == 'defined'" v-model="context" class="w-full">
|
||||
<option value="" disabled>Relation auswählen</option>
|
||||
<option
|
||||
v-for="relation in activeTable?.relations"
|
||||
|
@ -23,7 +32,21 @@
|
|||
</span>
|
||||
</option>
|
||||
</select>
|
||||
<Table v-model="value" disable-table-select />
|
||||
<div v-else class="flex flex-col w-full">
|
||||
<select v-model="joinTable">
|
||||
<option value="" disabled>Tabelle auswählen</option>
|
||||
<option
|
||||
v-for="table in tableMetas"
|
||||
:value="table.tableName"
|
||||
:disabled="alreadyJoined.includes(table.tableName) && table.tableName != value.table"
|
||||
>
|
||||
{{ table.tableName }}
|
||||
</option>
|
||||
</select>
|
||||
<input v-model="context" type="text" placeholder="Join Condition tabA.col = tabB.col" />
|
||||
</div>
|
||||
</div>
|
||||
<Table v-model="value" disable-table-select :show-table-select="false" />
|
||||
</div>
|
||||
<div class="h-fit p-1 border border-gray-400 hover:bg-gray-200 rounded-md" @click="$emit('remove')">
|
||||
<TrashIcon class="text-gray-500 h-6 w-6 cursor-pointer" />
|
||||
|
@ -35,10 +58,10 @@
|
|||
<script setup lang="ts">
|
||||
import { defineComponent, type PropType } from "vue";
|
||||
import { mapActions, mapState } from "pinia";
|
||||
import { type DynamicQueryStructure } from "@/types/dynamicQueries";
|
||||
import { type DynamicQueryStructure, type JoinStructure } from "@/types/dynamicQueries";
|
||||
import { useQueryBuilderStore } from "@/stores/admin/club/queryBuilder";
|
||||
import Table from "./Table.vue";
|
||||
import { TrashIcon } from "@heroicons/vue/24/outline";
|
||||
import { ArrowsUpDownIcon, TrashIcon } from "@heroicons/vue/24/outline";
|
||||
import { joinTableName } from "@/helpers/queryFormatter";
|
||||
import { v4 as uuid } from "uuid";
|
||||
</script>
|
||||
|
@ -51,11 +74,7 @@ export default defineComponent({
|
|||
default: "",
|
||||
},
|
||||
modelValue: {
|
||||
type: Object as PropType<
|
||||
DynamicQueryStructure & {
|
||||
foreignColumn: string;
|
||||
}
|
||||
>,
|
||||
type: Object as PropType<DynamicQueryStructure & JoinStructure>,
|
||||
required: true,
|
||||
},
|
||||
alreadyJoined: {
|
||||
|
@ -73,25 +92,44 @@ export default defineComponent({
|
|||
get() {
|
||||
return this.modelValue;
|
||||
},
|
||||
set(
|
||||
val: DynamicQueryStructure & {
|
||||
foreignColumn: string;
|
||||
}
|
||||
) {
|
||||
set(val: DynamicQueryStructure & JoinStructure) {
|
||||
this.$emit("update:model-value", val);
|
||||
},
|
||||
},
|
||||
foreignColumn: {
|
||||
context: {
|
||||
get() {
|
||||
return this.modelValue.foreignColumn;
|
||||
if (this.modelValue.type == "defined") {
|
||||
return this.modelValue.foreignColumn ?? "";
|
||||
} else {
|
||||
return this.modelValue.condition ?? "";
|
||||
}
|
||||
},
|
||||
set(val: string) {
|
||||
console.log(val, this.modelValue.type);
|
||||
if (this.modelValue.type == "defined") {
|
||||
let relTable = this.activeTable?.relations.find((r) => r.column == val);
|
||||
this.$emit("update:model-value", {
|
||||
...this.modelValue,
|
||||
foreignColumn: val,
|
||||
table: joinTableName(relTable?.referencedTableName ?? ""),
|
||||
});
|
||||
} else {
|
||||
this.$emit("update:model-value", {
|
||||
...this.modelValue,
|
||||
condition: val,
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
joinTable: {
|
||||
get(): string {
|
||||
return this.modelValue.table;
|
||||
},
|
||||
set(val: string) {
|
||||
this.$emit("update:model-value", {
|
||||
...this.modelValue,
|
||||
table: val,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -100,5 +138,14 @@ export default defineComponent({
|
|||
this.value.id = uuid();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
swapJoinType(type: string) {
|
||||
if (type == "defined") {
|
||||
this.value.type = "custom";
|
||||
} else {
|
||||
this.value.type = "defined";
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="flex flex-col gap-2 w-full">
|
||||
<TableSelect v-model="table" :disableTableSelect="disableTableSelect" />
|
||||
<TableSelect v-if="showTableSelect" v-model="table" :disableTableSelect="disableTableSelect" />
|
||||
<ColumnSelect v-if="table != ''" v-model="columnSelect" :table="table" />
|
||||
<Where v-if="table != ''" v-model="where" :table="table" />
|
||||
<Join v-if="table != ''" v-model="modelValue.join" :table="table" :alreadyJoined="alreadyJoined" />
|
||||
|
@ -34,6 +34,10 @@ export default defineComponent({
|
|||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
showTableSelect: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
emits: ["update:model-value"],
|
||||
computed: {
|
||||
|
|
|
@ -3,7 +3,7 @@ export interface DynamicQueryStructure {
|
|||
select: string[] | "*";
|
||||
table: string;
|
||||
where?: Array<ConditionStructure>;
|
||||
join?: Array<DynamicQueryStructure & { foreignColumn: string }>;
|
||||
join?: Array<DynamicQueryStructure & JoinStructure>;
|
||||
orderBy?: Array<OrderByStructure>; // only at top level
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,8 @@ export type WhereOperation =
|
|||
| "timespanEq"; // Date before x years (YYYY-01-01 <bis> YYYY-12-31)
|
||||
// TODO: age between | age equals | age greater | age smaller
|
||||
|
||||
export type JoinStructure = { foreignColumn: string; type: "defined" } | { condition: string; type: "custom" };
|
||||
|
||||
export type OrderByStructure = {
|
||||
id: string;
|
||||
depth: number;
|
||||
|
|
|
@ -70,14 +70,11 @@ import { useQueryStoreStore } from "@/stores/admin/configuration/queryStore";
|
|||
<script lang="ts">
|
||||
export default defineComponent({
|
||||
computed: {
|
||||
...mapState(useQueryBuilderStore, ["loading", "loadingData", "tableMetas", "data", "totalLength", "queryError"]),
|
||||
...mapState(useQueryBuilderStore, ["loading", "loadingData", "data", "totalLength", "queryError"]),
|
||||
...mapWritableState(useQueryBuilderStore, ["query"]),
|
||||
},
|
||||
mounted() {
|
||||
this.fetchTableMetas();
|
||||
},
|
||||
methods: {
|
||||
...mapActions(useQueryBuilderStore, ["fetchTableMetas", "sendQuery", "clearResults", "exportData"]),
|
||||
...mapActions(useQueryBuilderStore, ["sendQuery", "clearResults", "exportData"]),
|
||||
...mapActions(useQueryStoreStore, ["triggerSave"]),
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue