Select Git revision
SimpleJoin.vue 6.30 KiB
<script setup lang="ts">
import {reactive, ref, watch, watchEffect} from "vue";
import {useConstantsStore} from "@/services/constantsStore";
import {TableIdentifier, Transforms} from "@/services/api";
import {useMainStore} from "@/services/mainStore";
import TableSelector from "@/components/helpers/TableSelector.vue";
import {ColumnListItem, useColumnsOfTable} from "@/services/convenienceStore";
const store = useMainStore();
const constants = useConstantsStore();
const isValid = defineModel({type: Boolean, default: false, required: false})
const leftTable = ref<TableIdentifier>(null)
const rightTable = ref<TableIdentifier>(null)
const leftAlias = ref("")
const rightAlias = ref("")
const {columnList: leftCols} = useColumnsOfTable(leftTable, {deriveProps: (tm, c) => ({side: "left"})})
const {columnList: rightCols} = useColumnsOfTable(rightTable, {deriveProps: (tm, c) => ({side: "right"})})
const leftOn = ref<ColumnListItem[]>([])
const rightOn = ref<ColumnListItem[]>([])
const selection = reactive<{ left: ColumnListItem[], right: ColumnListItem[] }>({left: [], right: []})
const adv = reactive({isOuter: false, isFull: false})
/*
const joinedCols = computed(() => {
const res = []
leftCols.value.forEach(item => res.push({title: !!leftAlias.value ? `${leftAlias.value}.${item.colName}` : item.colName, ...item}))
rightCols.value.forEach(item => res.push({title: !!rightAlias.value ? `${rightAlias.value}.${item.colName}` : item.colName, ...item}))
return res
})
*/
watch(leftCols, () => selection.left = leftCols.value ?? [], {deep: false})
watch(rightCols, () => selection.right = rightCols.value ?? [], {deep: false})
watchEffect(() => {
const lt = !!leftTable.value
const rt = !!rightTable.value
const matchingOn = !!sameLengthOn()
isValid.value = lt && rt && matchingOn
})
function unpackColItems(cols: ColumnListItem[]): string[] {
return cols?.map(col => col.name)
}
function resetAll() {
leftOn.value = []
rightOn.value = []
selection.left = []
selection.right = []
leftAlias.value = ""
rightAlias.value = ""
leftTable.value = null
rightTable.value = null
}
function sameLengthOn(vs) {
return leftOn.value.length == rightOn.value.length || "ON column count differs"
}
function createBase(): Transforms.Base {
return {
operation: "join",
left_table: leftTable.value,
right_table: rightTable.value,
full: adv.isFull,
is_outer: adv.isOuter,
left_alias: leftAlias.value,
right_alias: rightAlias.value,
on_cols_left: unpackColItems(leftOn.value),
on_cols_right: unpackColItems(rightOn.value),
selected_cols_left: unpackColItems(selection.left),
selected_cols_right: unpackColItems(selection.right)
} as Transforms.SimpleJoin
}
defineExpose({resetAll, createBase})
</script>
<template>
<v-container class="text-center">
<v-row align="center">
<v-col cols="2">
<div class="text-body-1">Left Table</div>
</v-col>
<v-col cols="4">
<TableSelector v-model:selected-table="leftTable" source-d-b="either"
:props="{label: 'Select left table', 'hide-details': true}">
</TableSelector>
</v-col>
<v-col cols="1">
<strong>AS</strong>
</v-col>
<v-col cols="3">
<v-text-field v-model="leftAlias" label="Optional alias" hide-details></v-text-field>
</v-col>
</v-row>
<v-row align="center">
<v-col cols="2">
<div class="text-body-1">Right Table</div>
</v-col>
<v-col cols="4">
<TableSelector v-model:selected-table="rightTable" source-d-b="either"
:props="{label: 'Select right table', 'hide-details': true}">
</TableSelector>
</v-col>
<v-col cols="1">
<strong>AS</strong>
</v-col>
<v-col cols="3">
<v-text-field v-model="rightAlias" label="Optional alias" hide-details></v-text-field>
</v-col>
</v-row>
<v-row align="center">
<v-col cols="1">
<strong>ON</strong>
</v-col>
<v-col cols="4">
<v-select :items="leftCols" v-model="leftOn" multiple clearable :rules="[sameLengthOn]"
validate-on="input eager" return-object label="Columns in left table"></v-select>
</v-col>
<v-col cols="1">
<strong>=</strong>
</v-col>
<v-col cols="4">
<v-select :items="rightCols" v-model="rightOn" multiple clearable :rules="[sameLengthOn]"
validate-on="input eager" return-object label="Columns in right table"></v-select>
</v-col>
</v-row>
<v-row align="center">
<v-col cols="1">
<strong>SELECT</strong>
</v-col>
<v-col cols="3">
<v-select label="From left table" multiple chips clearable :items="leftCols" v-model="selection.left"
return-object hide-details>
<template v-slot:prepend-item>
<v-list-item title="Select All" @click="selection.left = leftCols.slice()">
<template v-slot:prepend>
<v-checkbox-btn
:indeterminate="selection.left.length > 1 && selection.left.length < leftCols.length"
:model-value="selection.left.length == leftCols.length"></v-checkbox-btn>
</template>
</v-list-item>
</template>
</v-select>
</v-col>
<v-col cols="3">
<v-select label="From right table" multiple chips clearable :items="rightCols"
v-model="selection.right" return-object hide-details>
<template v-slot:prepend-item>
<v-list-item title="Select All" @click="selection.right = rightCols.slice()">
<template v-slot:prepend>
<v-checkbox-btn
:indeterminate="selection.right.length > 1 && selection.right.length < rightCols.length"
:model-value="selection.right.length == rightCols.length"></v-checkbox-btn>
</template>
</v-list-item>
</template>
</v-select>
</v-col>
</v-row>
</v-container>
<!-- <v-expansion-panel title="Advanced">-->
<!-- <template v-slot:text>-->
<!-- <v-checkbox label="Outer Join" v-model="adv.isOuter"></v-checkbox>-->
<!-- <v-checkbox label="Full Join" v-model="adv.isFull"></v-checkbox>-->
<!-- </template>-->
<!-- </v-expansion-panel>-->
</template>
<style scoped>
</style>