Skip to content

Commit

Permalink
feat: add left_keys, right_keys to JOIN DT (#5263)
Browse files Browse the repository at this point in the history
* feat: add `left_keys`, `right_keys` to JOIN DT

Signed-off-by: yuda <[email protected]>

* chore: update language

Signed-off-by: yuda <[email protected]>

---------

Signed-off-by: yuda <[email protected]>
  • Loading branch information
yuda110 authored Dec 19, 2024
1 parent 6f03ec5 commit c1c9718
Show file tree
Hide file tree
Showing 7 changed files with 283 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
computed, reactive, ref, watch,
} from 'vue';
import { PI, PContextMenu } from '@cloudforet/mirinae';
import { PI, PContextMenu, PFieldTitle } from '@cloudforet/mirinae';
import type { MenuItem } from '@cloudforet/mirinae/src/controls/context-menu/type';
import { useProxyValue } from '@/common/composables/proxy-state';
Expand Down Expand Up @@ -152,6 +152,13 @@ watch(() => props.dataTableInfo, (newVal) => {
<div ref="containerRef"
class="dropdown-container"
>
<p-field-title v-if="props.operator === 'JOIN'"
size="sm"
color="gray"
class="join-table-text"
>
{{ $t('COMMON.WIDGETS.DATA_TABLE.FORM.LEFT_TABLE') }}
</p-field-title>
<div ref="targetRef"
:class="{'select-button': true,
selected: !!state.selected,
Expand Down Expand Up @@ -188,11 +195,19 @@ watch(() => props.dataTableInfo, (newVal) => {
ref="secondContainerRef"
class="dropdown-container"
>
<p-field-title v-if="props.operator === 'JOIN'"
size="sm"
color="gray"
class="join-table-text"
>
{{ $t('COMMON.WIDGETS.DATA_TABLE.FORM.RIGHT_TABLE') }}
</p-field-title>
<div ref="targetRef"
:class="{'select-button': true,
selected: !!state.secondarySelected,
error: (state.secondarySelected && !storeState.dataTables.some((dataTable) => dataTable.data_table_id === state.secondarySelected?.[0]?.name))
|| storeState.isJoinRestricted
|| storeState.isJoinRestricted,
[props.operator]: true
}"
@click="handleClickSelectButton(true)"
>
Expand Down Expand Up @@ -237,6 +252,9 @@ watch(() => props.dataTableInfo, (newVal) => {
.dropdown-container {
@apply relative;
.join-table-text {
margin-bottom: 0.125rem;
}
.select-button {
@apply flex justify-between items-center bg-gray-100 border border-gray-300 rounded-xl w-full cursor-pointer;
border-left-width: 0.375rem;
Expand All @@ -261,6 +279,9 @@ watch(() => props.dataTableInfo, (newVal) => {
&.selected {
@apply bg-indigo-100 border-indigo-400;
&.JOIN {
@apply bg-peacock-100 border-peacock-400;
}
.text {
@apply text-gray-800;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
<script setup lang="ts">
import {
computed, reactive, ref, watch,
computed, onMounted, reactive, ref, watch,
} from 'vue';
import { PFieldGroup, PI, PSelectDropdown } from '@cloudforet/mirinae';
import { random } from 'lodash';
import {
PFieldGroup, PI, PSelectDropdown, PFieldTitle, PButton, PIconButton,
} from '@cloudforet/mirinae';
import type { SelectDropdownMenuItem } from '@cloudforet/mirinae/src/controls/dropdown/select-dropdown/type';
import type { PrivateDataTableModel } from '@/schema/dashboard/private-data-table/model';
import type { PublicDataTableModel } from '@/schema/dashboard/public-data-table/model';
import { useProxyValue } from '@/common/composables/proxy-state';
import WidgetFormDataTableCardTransformFormWrapper
from '@/common/modules/widgets/_components/WidgetFormDataTableCardTransformFormWrapper.vue';
import {
DATA_TABLE_OPERATOR, JOIN_TYPE,
} from '@/common/modules/widgets/_constants/data-table-constant';
import { useWidgetGenerateStore } from '@/common/modules/widgets/_store/widget-generate-store';
import type { TransformDataTableInfo, TransformDataTableProps } from '@/common/modules/widgets/types/widget-data-table-type';
import type { JoinOptions, JoinType } from '@/common/modules/widgets/types/widget-model';
interface OnKeyItem {
leftKey?: string;
rightKey?: string;
}
const COMPONENT_RANDOM_KEY = `add-labels-${random()}`;
const props = defineProps<TransformDataTableProps<JoinOptions>>();
const emit = defineEmits<{(e: 'update:operator-options', value: JoinOptions): void;
(e: 'update:invalid', value: boolean): void;
Expand All @@ -26,6 +39,14 @@ const dataTableInfo = ref<TransformDataTableInfo>({
dataTables: props.originData?.data_tables,
});
const howInfo = ref<JoinOptions['how']>(props.originData.how);
const leftKeyInfo = ref<JoinOptions['left_keys']>(props.originData.left_keys);
const rightKeyInfo = ref<JoinOptions['right_keys']>(props.originData.right_keys);
const widgetGenerateStore = useWidgetGenerateStore();
const widgetGenerateState = widgetGenerateStore.state;
const storeState = reactive({
dataTables: computed<Partial<PublicDataTableModel|PrivateDataTableModel>[]>(() => widgetGenerateState.dataTables),
});
const state = reactive({
proxyOperatorOptions: useProxyValue<JoinOptions>('operator-options', props, emit),
joinTypeItems: computed<SelectDropdownMenuItem[]>(() => [
Expand All @@ -37,34 +58,89 @@ const state = reactive({
invalid: computed<boolean>(() => {
if (state.proxyOperatorOptions.data_tables.length < 2) return true;
if (!state.proxyOperatorOptions.data_tables.every((d) => !!d)) return true;
if (!state.selectedOnKeyList.length) return true;
if (state.selectedOnKeyList.some((d) => !d.leftKey || !d.rightKey)) return true;
return !howInfo.value;
}),
leftKeyMenuItems: computed<SelectDropdownMenuItem[]>(() => {
if (state.proxyOperatorOptions.data_tables.length < 1) return [];
const _targetDataTableId = state.proxyOperatorOptions.data_tables[0];
const _targetDataTable = storeState.dataTables.find((d) => d.data_table_id === _targetDataTableId);
return Object.keys(_targetDataTable?.labels_info ?? {})?.map((d) => ({
name: d,
label: d,
})) ?? [];
}),
rightKeyMenuItems: computed(() => {
if (state.proxyOperatorOptions.data_tables.length < 2) return [];
const _targetDataTableId = state.proxyOperatorOptions.data_tables[1];
const _targetDataTable = storeState.dataTables.find((d) => d.data_table_id === _targetDataTableId);
return Object.keys(_targetDataTable?.labels_info ?? {})?.map((d) => ({
name: d,
label: d,
})) ?? [];
}),
selectedOnKeyList: [{}] as OnKeyItem[],
});
/* Event */
const handleUpdateHow = (val: JoinType) => {
howInfo.value = val;
};
const handleClickAddKey = () => {
state.selectedOnKeyList.push({});
};
const handleUpdateOnKey = (key: 'leftKey'|'rightKey', idx: number, val: string) => {
state.selectedOnKeyList[idx][key] = val;
state.selectedOnKeyList = [...state.selectedOnKeyList];
};
const handleRemoveKey = (idx: number) => {
state.selectedOnKeyList.splice(idx, 1);
state.selectedOnKeyList = [...state.selectedOnKeyList];
};
/* Watcher */
watch([dataTableInfo, howInfo], ([_dataTableInfo, _howInfo]) => {
watch([dataTableInfo, howInfo, () => state.selectedOnKeyList], ([_dataTableInfo, _howInfo, _selectedOnKeyList]) => {
state.proxyOperatorOptions = {
data_tables: _dataTableInfo.dataTables || [],
how: _howInfo,
left_keys: _selectedOnKeyList.map((d) => d.leftKey || ''),
right_keys: _selectedOnKeyList.map((d) => d.rightKey || ''),
};
}, { deep: true, immediate: true });
watch(dataTableInfo, (_curr, _prev) => {
if (_curr?.dataTables?.[0] !== _prev?.dataTables?.[0]) {
state.selectedOnKeyList = state.selectedOnKeyList.map((d) => ({
leftKey: d.leftKey,
rightKey: '',
}));
}
if (_curr?.dataTables?.[1] !== _prev?.dataTables?.[1]) {
state.selectedOnKeyList = state.selectedOnKeyList.map((d) => ({
leftKey: d.leftKey,
rightKey: '',
}));
}
}, { deep: true });
watch(() => state.invalid, (_invalid) => {
emit('update:invalid', _invalid);
}, { immediate: true });
onMounted(() => {
state.selectedOnKeyList = leftKeyInfo.value?.map((d, idx) => ({
leftKey: d,
rightKey: rightKeyInfo.value[idx],
})) ?? [{}];
});
</script>
<template>
<div class="widget-form-data-table-card-transform-concatenate">
<div class="widget-form-data-table-card-transform-join">
<widget-form-data-table-card-transform-form-wrapper :data-table-id="props.baseDataTableId"
:operator="DATA_TABLE_OPERATOR.CONCAT"
:operator="DATA_TABLE_OPERATOR.JOIN"
:data-table-info.sync="dataTableInfo"
>
<p-field-group :label="'How'"
<p-field-group label="How"
required
>
<p-select-dropdown class="join-type-dropdown"
Expand All @@ -84,6 +160,86 @@ watch(() => state.invalid, (_invalid) => {
</template>
</p-select-dropdown>
</p-field-group>
<p-field-group label="On"
required
>
<div class="on-field-name-wrapper">
<p-field-title size="sm"
color="gray"
class="col-span-6"
>
{{ $t('COMMON.WIDGETS.DATA_TABLE.FORM.LEFT_KEY') }}
</p-field-title>
<p-field-title size="sm"
color="gray"
class="col-span-5"
>
{{ $t('COMMON.WIDGETS.DATA_TABLE.FORM.RIGHT_KEY') }}
</p-field-title>
</div>
<div v-for="(onKey, oIdx) in state.selectedOnKeyList"
:key="`${COMPONENT_RANDOM_KEY}-${oIdx}`"
class="on-form-wrapper"
>
<p-select-dropdown :menu="state.leftKeyMenuItems"
:selected="onKey.leftKey"
class="select-dropdown"
@update:selected="handleUpdateOnKey('leftKey', oIdx, $event)"
/>
<span class="equal-text">=</span>
<p-select-dropdown :menu="state.rightKeyMenuItems"
:selected="onKey.rightKey"
class="select-dropdown right-key"
@update:selected="handleUpdateOnKey('rightKey', oIdx, $event)"
/>
<p-icon-button name="ic_delete"
size="sm"
class="delete-button"
:disabled="state.selectedOnKeyList.length === 1"
@click="handleRemoveKey(oIdx)"
/>
</div>
</p-field-group>
<p-button class="add-key-button"
style-type="tertiary"
icon-left="ic_plus_bold"
@click="handleClickAddKey"
>
{{ $t('COMMON.WIDGETS.DATA_TABLE.FORM.ADD_LABELS.ADD_LABEL') }}
</p-button>
</widget-form-data-table-card-transform-form-wrapper>
</div>
</template>
<style lang="postcss" scoped>
.widget-form-data-table-card-transform-join {
.on-field-name-wrapper {
@apply grid grid-cols-12;
margin-bottom: 0.25rem;
}
.on-form-wrapper {
@apply grid grid-cols-12 gap-1;
.select-dropdown {
@apply col-span-5 bg-indigo-100 rounded;
padding: 0.25rem;
&.right-key {
@apply bg-peacock-100;
}
}
.equal-text {
@apply col-span-1 text-gray-500;
display: flex;
align-items: center;
justify-content: center;
}
.delete-button {
@apply col-span-1;
display: flex;
margin: auto 0;
}
}
.add-key-button {
width: 6.8125rem;
}
}
</style>
2 changes: 2 additions & 0 deletions apps/web/src/common/modules/widgets/types/widget-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ export interface ConcatOptions {
export interface JoinOptions {
data_tables: string[];
how?: JoinType;
left_keys: string[];
right_keys: string[];
}

export interface QueryOptions {
Expand Down
Loading

0 comments on commit c1c9718

Please sign in to comment.