feat:lookup同期アクション
This commit is contained in:
@@ -18,119 +18,68 @@
|
||||
<q-separator />
|
||||
<q-card-section class="q-pa-none q-ma-none">
|
||||
<div style="">
|
||||
<div v-if="selectedField.fields && selectedField.fields.length > 0 ">
|
||||
<q-list bordered>
|
||||
<q-virtual-scroll style="max-height: 160px;" :items="selectedField.fields" separator v-slot="{ item, index }">
|
||||
<q-item :key="index" dense clickable >
|
||||
<q-item-section>
|
||||
<div v-if="selectedField.fields && selectedField.fields.length > 0">
|
||||
<q-list bordered>
|
||||
<q-virtual-scroll style="max-height: 160px;" :items="selectedField.fields" separator
|
||||
v-slot="{ item, index }">
|
||||
<q-item :key="index" dense clickable>
|
||||
<q-item-section>
|
||||
<q-item-label>
|
||||
{{ item.label }}
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-btn round flat size="sm" icon="clear" @click="removeField(index)" />
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-virtual-scroll>
|
||||
</q-list>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-btn round flat size="sm" icon="clear" @click="removeField(index)" />
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-virtual-scroll>
|
||||
</q-list>
|
||||
</div>
|
||||
<!-- <div v-else class="row q-mt-lg">
|
||||
</div> -->
|
||||
</div>
|
||||
<!-- <q-separator /> -->
|
||||
</q-card-section>
|
||||
<q-card-section class="q-px-none q-py-xs" v-if="selectedField.fields && selectedField.fields.length===0">
|
||||
<q-card-section class="q-px-none q-py-xs" v-if="selectedField.fields && selectedField.fields.length === 0">
|
||||
<div class="row">
|
||||
<div class="text-grey text-caption"> {{ $props.placeholder }}</div>
|
||||
<!-- <q-btn flat color="grey" label="clear" @click="clear" /> -->
|
||||
</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
|
||||
<show-dialog v-model:visible="show" name="フィールド一覧" @close="closeFieldDialog" ref="fieldDlg">
|
||||
|
||||
<div class="q-mx-md q-mb-lg">
|
||||
<div class="q-mb-xs q-ml-md text-primary">アプリ選択</div>
|
||||
|
||||
<div class="q-pa-md row" style="border: 1px solid rgba(0, 0, 0, 0.12); border-radius: 4px;">
|
||||
<div v-if="!showSelectApp && selectedField.app">{{ selectedField.app?.name }}</div>
|
||||
<q-space />
|
||||
<div>
|
||||
<q-btn outline dense label="選 択" padding="none sm" color="primary" @click="() => {
|
||||
showSelectApp = true;
|
||||
}"></q-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!showSelectApp && selectedField.app?.name">
|
||||
<div>
|
||||
<div class="row q-mb-md">
|
||||
<!-- <div class="col"> -->
|
||||
<div class="q-mb-xs q-ml-md text-primary">フィールド選択</div>
|
||||
<!-- </div> -->
|
||||
<q-space />
|
||||
<!-- <div class="col"> -->
|
||||
<div class="q-mr-md">
|
||||
<q-input dense debounce="300" v-model="fieldFilter" placeholder="フィールド検索" clearable>
|
||||
<template v-slot:before>
|
||||
<q-icon name="search" />
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<field-select ref="fieldDlg" name="フィールド" :type="selectType"
|
||||
:appId="selectedField.app?.id" not_page :filter="fieldFilter" :selectedFields="selectedField.fields" :fieldTypes="fieldTypes"></field-select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="min-width: 45vw;" v-else>
|
||||
</div>
|
||||
|
||||
</show-dialog>
|
||||
|
||||
<show-dialog v-model:visible="showSelectApp" name="アプリ選択" @close="closeAppDlg">
|
||||
<template v-slot:toolbar>
|
||||
<q-input dense debounce="300" v-model="filter" placeholder="検索" clearable>
|
||||
<template v-slot:before>
|
||||
<q-icon name="search" />
|
||||
</template>
|
||||
</q-input>
|
||||
</template>
|
||||
<AppSelect ref="appDlg" name="アプリ" type="single" :filter="filter" ></AppSelect>
|
||||
</div>
|
||||
<show-dialog v-model:visible="show" name="フィールド一覧" @close="closeAFBox">
|
||||
<AppFieldSelectBox v-model:selectedField="selectedField" :selectType="selectType" ref="afBox" :fieldTypes="fieldTypes"/>
|
||||
</show-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, watchEffect, computed } from 'vue';
|
||||
import { defineComponent, ref, watchEffect } from 'vue';
|
||||
import AppFieldSelectBox from '../AppFieldSelectBox.vue';
|
||||
import ShowDialog from '../ShowDialog.vue';
|
||||
import FieldSelect from '../FieldSelect.vue';
|
||||
import { useFlowEditorStore } from 'stores/flowEditor';
|
||||
import AppSelect from '../AppSelect.vue';
|
||||
interface IApp{
|
||||
id:string,
|
||||
name:string
|
||||
|
||||
export interface IApp {
|
||||
id: string,
|
||||
name: string
|
||||
}
|
||||
interface IField {
|
||||
export interface IField {
|
||||
name: string,
|
||||
code: string,
|
||||
type: string
|
||||
}
|
||||
|
||||
interface IAppFields{
|
||||
app?:IApp,
|
||||
fields:IField[]
|
||||
export interface IAppFields {
|
||||
app?: IApp,
|
||||
fields: IField[]
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
inheritAttrs:false,
|
||||
inheritAttrs: false,
|
||||
name: 'AppFieldSelect',
|
||||
components: {
|
||||
ShowDialog,
|
||||
FieldSelect,
|
||||
AppSelect,
|
||||
AppFieldSelectBox
|
||||
},
|
||||
props: {
|
||||
displayName: {
|
||||
@@ -149,9 +98,9 @@ export default defineComponent({
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
selectType:{
|
||||
type:String,
|
||||
default:'single'
|
||||
selectType: {
|
||||
type: String,
|
||||
default: 'single'
|
||||
},
|
||||
fieldTypes:{
|
||||
type:Array,
|
||||
@@ -159,69 +108,48 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const appDlg = ref();
|
||||
const fieldDlg = ref();
|
||||
const show = ref(false);
|
||||
const showSelectApp = ref(false);
|
||||
const selectedField = ref<IAppFields>({
|
||||
app:undefined,
|
||||
fields:[]
|
||||
});
|
||||
if(props.modelValue && "app" in props.modelValue && "fields" in props.modelValue){
|
||||
selectedField.value=props.modelValue as IAppFields;
|
||||
}
|
||||
const afBox = ref();
|
||||
const selectedField = ref<IAppFields>({
|
||||
app: undefined,
|
||||
fields: []
|
||||
});
|
||||
if (props.modelValue && 'app' in props.modelValue && 'fields' in props.modelValue) {
|
||||
selectedField.value = props.modelValue as IAppFields;
|
||||
}
|
||||
const store = useFlowEditorStore();
|
||||
|
||||
const isSelected = computed(() => {
|
||||
return selectedField.value !== null && typeof selectedField.value === 'object' && ('app' in selectedField.value)
|
||||
});
|
||||
|
||||
const showDg = () => {
|
||||
show.value = true;
|
||||
};
|
||||
|
||||
const clear = () => {
|
||||
selectedField.value ={
|
||||
fields:[]
|
||||
} ;
|
||||
selectedField.value = {
|
||||
fields: []
|
||||
};
|
||||
}
|
||||
|
||||
const closeAppDlg = (val: string) => {
|
||||
const removeField = (index: number) => {
|
||||
selectedField.value.fields.splice(index, 1);
|
||||
}
|
||||
|
||||
const closeAFBox = (val: string) => {
|
||||
if (val == 'OK') {
|
||||
selectedField.value.app = appDlg.value.selected[0];
|
||||
selectedField.value.fields=[];
|
||||
showSelectApp.value=false;
|
||||
console.log(afBox.value);
|
||||
|
||||
selectedField.value = afBox.value.selField;
|
||||
}
|
||||
};
|
||||
|
||||
const closeFieldDialog=(val:string)=>{
|
||||
if (val == 'OK') {
|
||||
selectedField.value.fields = fieldDlg.value.selected;
|
||||
}
|
||||
};
|
||||
|
||||
const removeField=(index:number)=>{
|
||||
selectedField.value.fields.splice(index,1);
|
||||
}
|
||||
watchEffect(() => {
|
||||
emit('update:modelValue', selectedField.value);
|
||||
});
|
||||
|
||||
return {
|
||||
store,
|
||||
appDlg,
|
||||
fieldDlg,
|
||||
afBox,
|
||||
show,
|
||||
showDg,
|
||||
closeAppDlg,
|
||||
closeFieldDialog,
|
||||
showDg: () => { show.value = true },
|
||||
selectedField,
|
||||
showSelectApp,
|
||||
isSelected,
|
||||
filter: ref(),
|
||||
clear,
|
||||
fieldFilter: ref(),
|
||||
removeField
|
||||
removeField,
|
||||
closeAFBox,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
93
frontend/src/components/right/AppSelect.vue
Normal file
93
frontend/src/components/right/AppSelect.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<div>
|
||||
<q-field :label="displayName" labelColor="primary" stack-label>
|
||||
<template v-slot:control>
|
||||
<q-card flat class="full-width">
|
||||
<q-card-actions vertical>
|
||||
<q-btn color="grey-3" text-color="black" @click="() => { dgIsShow = true }">アプリ選択</q-btn>
|
||||
</q-card-actions>
|
||||
<q-card-section class="text-caption">
|
||||
<div v-if="selectedField.app.name">
|
||||
{{ selectedField.app.name }}
|
||||
</div>
|
||||
<div v-else>{{ placeholder }}</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
</q-field>
|
||||
</div>
|
||||
|
||||
<ShowDialog v-model:visible="dgIsShow" name="アプリ選択" @close="closeDg" min-width="50vw" min-height="50vh">
|
||||
<template v-slot:toolbar>
|
||||
<q-input dense debounce="300" v-model="filter" placeholder="検索" clearable>
|
||||
<template v-slot:before>
|
||||
<q-icon name="search" />
|
||||
</template>
|
||||
</q-input>
|
||||
</template>
|
||||
<AppSelectBox ref="appDg" name="アプリ" type="single" :filter="filter"></AppSelectBox>
|
||||
</ShowDialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, reactive, ref, watchEffect } from 'vue';
|
||||
import ShowDialog from '../ShowDialog.vue';
|
||||
import AppSelectBox from '../AppSelectBox.vue';
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
inheritAttrs: false,
|
||||
name: 'AppSelect',
|
||||
components: {
|
||||
ShowDialog,
|
||||
AppSelectBox
|
||||
},
|
||||
props: {
|
||||
context: {
|
||||
type: Array<Props>,
|
||||
default: '',
|
||||
},
|
||||
displayName: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const appDg = ref()
|
||||
const dgIsShow = ref(false)
|
||||
const selectedField = props.modelValue && props.modelValue.app ? props.modelValue : reactive({app:{}});
|
||||
const closeDg = (state: string) => {
|
||||
dgIsShow.value = false;
|
||||
if (state == 'OK') {
|
||||
selectedField.app = appDg.value.selected[0];
|
||||
}
|
||||
};
|
||||
|
||||
console.log(selectedField);
|
||||
|
||||
watchEffect(() => {
|
||||
emit('update:modelValue', selectedField);
|
||||
});
|
||||
|
||||
return {
|
||||
filter: ref(''),
|
||||
dgIsShow,
|
||||
appDg,
|
||||
closeDg,
|
||||
selectedField
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -4,7 +4,8 @@
|
||||
<template v-slot:control>
|
||||
<q-card flat class="full-width">
|
||||
<q-card-actions vertical>
|
||||
<q-btn color="grey-3" text-color="black" @click="showDg()">クリックで設定:{{ isSetted ? '設定済み' : '未設定' }}</q-btn>
|
||||
<q-btn color="grey-3" text-color="black" :disable="btnDisable" @click="showDg()">クリックで設定:{{ isSetted ?
|
||||
'設定済み' : '未設定' }}</q-btn>
|
||||
</q-card-actions>
|
||||
<q-card-section class="text-caption">
|
||||
<div v-if="!isSetted">{{ placeholder }}</div>
|
||||
@@ -20,7 +21,7 @@
|
||||
|
||||
|
||||
<script lang="ts">
|
||||
import { ConditionNode, ConditionTree, Operator } from 'app/src/types/Conditions';
|
||||
import { ConditionNode, ConditionTree, Operator, OperatorListItem } from 'app/src/types/Conditions';
|
||||
import { computed, defineComponent, provide, reactive, ref, watchEffect } from 'vue';
|
||||
import ConditionEditor from '../ConditionEditor/ConditionEditor.vue';
|
||||
|
||||
@@ -28,6 +29,10 @@ type Props = {
|
||||
props?: {
|
||||
name: string;
|
||||
modelValue?: {
|
||||
app: {
|
||||
id: string;
|
||||
name: string;
|
||||
},
|
||||
fields: {
|
||||
type: string;
|
||||
label: string;
|
||||
@@ -37,6 +42,15 @@ type Props = {
|
||||
}
|
||||
};
|
||||
|
||||
type InputConfg = {
|
||||
canInput: boolean;
|
||||
buttonsConfig: {
|
||||
label: string;
|
||||
color: string;
|
||||
type: string;
|
||||
}[]
|
||||
};
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
name: 'FieldInput',
|
||||
@@ -72,28 +86,71 @@ export default defineComponent({
|
||||
sourceType: {
|
||||
type: String,
|
||||
default: 'field'
|
||||
},
|
||||
onlySourceSelect: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
operatorList: {
|
||||
type: Array,
|
||||
},
|
||||
inputConfig: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
left: {
|
||||
canInput: false,
|
||||
buttonsConfig: [
|
||||
{ label: 'フィールド', color: 'primary', type: 'FieldAdd' },
|
||||
{ label: '変数', color: 'green', type: 'VariableAdd' },
|
||||
]
|
||||
},
|
||||
right: {
|
||||
canInput: true,
|
||||
buttonsConfig: [
|
||||
{ label: '変数', color: 'green', type: 'VariableAdd' },
|
||||
]
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
setup(props, { emit }) {
|
||||
const source = props.context.find(element => element?.props?.name === 'sources')
|
||||
|
||||
|
||||
if (source) {
|
||||
if(props.sourceType === 'field'){
|
||||
provide('sourceFields', computed( () => source.props?.modelValue?.fields ?? []));
|
||||
} else if(props.sourceType === 'app'){
|
||||
console.log('sourceApp', source.props?.modelValue);
|
||||
provide('sourceApp', computed( () => source.props?.modelValue?.app?.id));
|
||||
if (props.sourceType === 'field') {
|
||||
provide('sourceFields', computed(() => source.props?.modelValue?.fields ?? []));
|
||||
} else if (props.sourceType === 'app') {
|
||||
provide('sourceApp', computed(() => source.props?.modelValue?.app?.id));
|
||||
}
|
||||
}
|
||||
|
||||
provide('leftDynamicItemConfig', props.inputConfig.left);
|
||||
provide('rightDynamicItemConfig', props.inputConfig.right);
|
||||
provide('Operator', props.operatorList);
|
||||
|
||||
const btnDisable = computed(() => {
|
||||
const onlySourceSelect = props.onlySourceSelect;
|
||||
|
||||
if (!onlySourceSelect) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (props.sourceType === 'field') {
|
||||
return source?.props?.modelValue?.fields?.length ?? 0 > 0;
|
||||
} else if (props.sourceType === 'app') {
|
||||
return source?.props?.modelValue?.app?.id ? false : true
|
||||
}
|
||||
return true;
|
||||
})
|
||||
|
||||
const appDg = ref();
|
||||
const show = ref(false);
|
||||
const tree = reactive(new ConditionTree());
|
||||
if (props.modelValue && props.modelValue !== '') {
|
||||
tree.fromJson(props.modelValue);
|
||||
} else {
|
||||
const newNode = new ConditionNode({}, Operator.Equal, '', tree.root);
|
||||
const newNode = new ConditionNode({}, (props.operatorList && props.operatorList.length > 0) ? props.operatorList[0] as OperatorListItem : Operator.Equal, '', tree.root);
|
||||
tree.addNode(tree.root, newNode);
|
||||
}
|
||||
|
||||
@@ -109,13 +166,15 @@ export default defineComponent({
|
||||
|
||||
const onClosed = (val: string) => {
|
||||
if (val == 'OK') {
|
||||
const conditionJson = tree.toJson();
|
||||
isSetted.value = true;
|
||||
tree.setQuery(tree.buildConditionQueryString(tree.root));
|
||||
const conditionJson = tree.toJson();
|
||||
emit('update:modelValue', conditionJson);
|
||||
}
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
tree.setQuery(tree.buildConditionQueryString(tree.root));
|
||||
const conditionJson = tree.toJson();
|
||||
emit('update:modelValue', conditionJson);
|
||||
});
|
||||
@@ -127,7 +186,8 @@ export default defineComponent({
|
||||
showDg,
|
||||
onClosed,
|
||||
tree,
|
||||
conditionString
|
||||
conditionString,
|
||||
btnDisable
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
250
frontend/src/components/right/DataMapping.vue
Normal file
250
frontend/src/components/right/DataMapping.vue
Normal file
@@ -0,0 +1,250 @@
|
||||
<template>
|
||||
<div>
|
||||
<q-field :label="displayName" labelColor="primary" stack-label>
|
||||
<template v-slot:control>
|
||||
<q-card flat class="full-width">
|
||||
<q-card-actions vertical>
|
||||
<q-btn color="grey-3" text-color="black" :disable="btnDisable"
|
||||
@click="() => { dgIsShow = true }">クリックで設定</q-btn>
|
||||
</q-card-actions>
|
||||
<q-card-section class="text-caption">
|
||||
<div v-if="mappingObjectsInputDisplay && mappingObjectsInputDisplay.length > 0">
|
||||
<div v-for="(item) in mappingObjectsInputDisplay" :key="item">{{ item }}</div>
|
||||
</div>
|
||||
<div v-else>{{ placeholder }}</div>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
</q-field>
|
||||
<show-dialog v-model:visible="dgIsShow" name="データマッピング" @close="closeDg" min-width="50vw" min-height="60vh">
|
||||
|
||||
<div class="q-mx-md">
|
||||
<div class="row q-col-gutter-x-xs flex-center">
|
||||
<div class="col-6">
|
||||
<div class="q-mx-xs">ソース</div>
|
||||
</div>
|
||||
<!-- <div class="col-1">
|
||||
</div> -->
|
||||
<div class="col-6">
|
||||
<div class="q-mx-xs">目標</div>
|
||||
</div>
|
||||
<!-- <div class="col-1"><q-btn flat round dense icon="add" size="sm" @click="addMappingObject" /> -->
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
<q-virtual-scroll style="max-height: 75vh;" :items="mappingProps" separator v-slot="{ item, index }">
|
||||
<!-- <div class="q-my-sm" v-for="(item, index) in mappingProps" :key="item.id"> -->
|
||||
<div class="row q-my-md q-col-gutter-x-md flex-center">
|
||||
<div class="col-6">
|
||||
<ConditionObject :config="config" v-model="item.from" />
|
||||
</div>
|
||||
<!-- <div class="col-1">
|
||||
</div> -->
|
||||
<div class="col-6">
|
||||
<q-field v-model="item.vName" type="text" outlined dense>
|
||||
<!-- <template v-slot:append>
|
||||
<q-icon name="search" class="cursor-pointer"
|
||||
@click="() => { mappingProps[index].to.isDialogVisible = true }" />
|
||||
</template> -->
|
||||
<template v-slot:control>
|
||||
<div class="self-center full-width no-outline" tabindex="0"
|
||||
v-if="item.to.app?.name && item.to.fields?.length > 0 && item.to.fields[0].label">
|
||||
{{ `${item.to.fields[0].label}` }}
|
||||
<q-tooltip>
|
||||
<div>アプリ : {{ item.to.app.name }}</div>
|
||||
<div>フィールドのコード : {{ item.to.fields[0].code }}</div>
|
||||
<div>フィールドのタイプ : {{ item.to.fields[0].type }}</div>
|
||||
<div>フィールド : {{ item.to.fields[0] }}</div>
|
||||
</q-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
</q-field>
|
||||
</div>
|
||||
<!-- <div class="col-1">
|
||||
<q-btn flat round dense icon="delete" size="sm" @click="() => deleteMappingObject(index)" />
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<show-dialog v-model:visible="mappingProps[index].to.isDialogVisible" name="フィールド一覧"
|
||||
@close="closeToDg" ref="fieldDlg">
|
||||
<FieldSelect v-if="onlySourceSelect" ref="fieldDlg" name="フィールド" :appId="sourceAppId" not_page
|
||||
:selectedFields="mappingProps[index].to.fields"
|
||||
:updateSelects="(fields) => { mappingProps[index].to.fields = fields; mappingProps[index].to.app = sourceApp }">
|
||||
</FieldSelect>
|
||||
<AppFieldSelectBox v-else v-model:selectedField="mappingProps[index].to" />
|
||||
</show-dialog>
|
||||
<!-- </div> -->
|
||||
</q-virtual-scroll>
|
||||
</div>
|
||||
</show-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { computed, defineComponent, watch, isRef, reactive, ref, watchEffect } from 'vue';
|
||||
import ConditionObject from '../ConditionEditor/ConditionObject.vue';
|
||||
import ShowDialog from '../ShowDialog.vue';
|
||||
import AppFieldSelectBox from '../AppFieldSelectBox.vue';
|
||||
import FieldSelect from '../FieldSelect.vue';
|
||||
import IAppFields from './AppFieldSelect.vue';
|
||||
import { api } from 'boot/axios';
|
||||
|
||||
type Props = {
|
||||
props?: {
|
||||
name: string;
|
||||
modelValue?: {
|
||||
app: {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
type ValueType = {
|
||||
id: string;
|
||||
from: object;
|
||||
to: typeof IAppFields & {
|
||||
isDialogVisible: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export default defineComponent({
|
||||
name: 'DataMapping',
|
||||
inheritAttrs: false,
|
||||
components: {
|
||||
ShowDialog,
|
||||
ConditionObject,
|
||||
AppFieldSelectBox,
|
||||
FieldSelect
|
||||
},
|
||||
props: {
|
||||
context: {
|
||||
type: Array<Props>,
|
||||
default: '',
|
||||
},
|
||||
displayName: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
modelValue: {
|
||||
type: Object as () => ValueType[],
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
onlySourceSelect: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
setup(props, { emit }) {
|
||||
const source = props.context.find(element => element?.props?.name === 'sources')
|
||||
|
||||
const sourceApp = computed(() => source?.props?.modelValue?.app);
|
||||
|
||||
const sourceAppId = computed(() => sourceApp.value?.id);
|
||||
|
||||
const closeDg = () => {
|
||||
emit('update:modelValue', mappingProps.value
|
||||
);
|
||||
}
|
||||
|
||||
const closeToDg = () => {
|
||||
emit('update:modelValue', mappingProps.value
|
||||
);
|
||||
}
|
||||
|
||||
const mappingProps = computed(() => props.modelValue ?? []);
|
||||
|
||||
watch(() => sourceAppId.value, async (newId, oldId) => {
|
||||
if (!newId) return;
|
||||
const a = await api.get('api/v1/appfields', {
|
||||
params: {
|
||||
app: newId
|
||||
}
|
||||
}).then(res => {
|
||||
return Object.values(res.data.properties)
|
||||
.map(f => ({ name: f.label, objectType: 'field', ...f }))
|
||||
.map(f => {
|
||||
return {
|
||||
id: uuidv4(),
|
||||
from: {},
|
||||
to: {
|
||||
app: sourceApp.value,
|
||||
fields: [f],
|
||||
isDialogVisible: false
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
const modelValue = props.modelValue ?? [];
|
||||
|
||||
if (modelValue.length === 0 || newId !== oldId) {
|
||||
emit('update:modelValue', a);
|
||||
return;
|
||||
}
|
||||
const modelValueFieldNames = modelValue.map(item => item.to.fields[0].name);
|
||||
|
||||
const newFields = a.filter(field => !modelValueFieldNames.includes(field.to.fields[0].name));
|
||||
|
||||
const updatedModelValue = [...modelValue, ...newFields];
|
||||
|
||||
emit('update:modelValue', updatedModelValue);
|
||||
})
|
||||
|
||||
console.log(mappingProps.value);
|
||||
|
||||
// const deleteMappingObject = (index: number) => mappingProps.length === 1
|
||||
// ? mappingProps.splice(0, mappingProps.length, defaultMappingProp())
|
||||
// : mappingProps.splice(index, 1);
|
||||
|
||||
const mappingObjectsInputDisplay = computed(() =>
|
||||
(mappingProps.value && Array.isArray(mappingProps.value)) ?
|
||||
mappingProps.value
|
||||
.filter(item => item.from?.sharedText && item.to.fields?.length > 0)
|
||||
.map(item => {
|
||||
return `field(${item.to.app?.id},${item.to.fields[0].label}) = ${item.from.sharedText} `;
|
||||
})
|
||||
: []
|
||||
);
|
||||
|
||||
|
||||
|
||||
const btnDisable = computed(() => props.onlySourceSelect ? !(source?.props?.modelValue?.app?.id) : false);
|
||||
|
||||
//集計処理方法
|
||||
|
||||
watchEffect(() => {
|
||||
emit('update:modelValue', mappingProps.value);
|
||||
});
|
||||
return {
|
||||
uuidv4,
|
||||
dgIsShow: ref(false),
|
||||
closeDg,
|
||||
toDgIsShow: ref(false),
|
||||
closeToDg,
|
||||
mappingProps,
|
||||
// addMappingObject: () => mappingProps.push(defaultMappingProp()),
|
||||
// deleteMappingObject,
|
||||
mappingObjectsInputDisplay,
|
||||
sourceApp,
|
||||
sourceAppId,
|
||||
btnDisable,
|
||||
config: {
|
||||
canInput: false,
|
||||
buttonsConfig: [
|
||||
{ label: '変数', color: 'green', type: 'VariableAdd',editable:false },
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="scss"></style>
|
||||
@@ -139,6 +139,7 @@ export default defineComponent({
|
||||
}
|
||||
return null;
|
||||
}));
|
||||
provide('sourceApp', computed(() => source.props?.modelValue?.app?.id));
|
||||
}
|
||||
|
||||
const actionName = props.context.find(element => element?.props?.name === 'displayName')
|
||||
@@ -168,12 +169,7 @@ export default defineComponent({
|
||||
processingObjects
|
||||
.filter(item => item.field && item.logicalOperator && item.vName)
|
||||
.map(item => {
|
||||
const name = typeof item.field?.name === 'string'
|
||||
? item.field.name
|
||||
: item.field?.name.name;
|
||||
return item.logicalOperator.operator!==''?
|
||||
`${processingProps.name}.${item.vName} = ${item.logicalOperator.operator}(${name})`
|
||||
:`${processingProps.name}.${item.vName} = ${name}`
|
||||
return`var(${processingProps.name}.${item.vName}) = ${item.field.sharedText}`
|
||||
})
|
||||
: []
|
||||
);
|
||||
|
||||
@@ -22,6 +22,8 @@ import EventSetter from '../right/EventSetter.vue';
|
||||
import ColorPicker from './ColorPicker.vue';
|
||||
import NumInput from './NumInput.vue';
|
||||
import DataProcessing from './DataProcessing.vue';
|
||||
import DataMapping from './DataMapping.vue';
|
||||
import AppSelect from './AppSelect.vue';
|
||||
import { IActionNode,IActionProperty,IProp } from 'src/types/ActionTypes';
|
||||
|
||||
export default defineComponent({
|
||||
@@ -37,7 +39,9 @@ export default defineComponent({
|
||||
EventSetter,
|
||||
ColorPicker,
|
||||
NumInput,
|
||||
DataProcessing
|
||||
DataProcessing,
|
||||
DataMapping,
|
||||
AppSelect
|
||||
},
|
||||
props: {
|
||||
nodeProps: {
|
||||
|
||||
Reference in New Issue
Block a user