Merged PR 83: 属性UI(プロパティ)にチェックルール設定追加
属性UI(プロパティ)にチェックルール設定追加
属性UIのJSON定義に下記のフィールドを追加しました。
1.required : boolean 入力必須かどうかを設定する
2.requiredMessage: string 未入力の場合表示するエラーメッセージを設定する
(未設定の場合既定メッセージを表示する)
3. rules: [アロー関数]
必須チェック以外に、入力範囲など制限したい場合下記のように指定する
[val=>!!val ||'数値を入力してください',val=>val<=100 && val>=1 || '1-100の範囲内の数値を入力してください']
Related work items: #299
This commit is contained in:
@@ -52,12 +52,12 @@ import { useQuasar } from 'quasar';
|
|||||||
const tree = ref(props.conditionTree);
|
const tree = ref(props.conditionTree);
|
||||||
const closeDg = (val:string) => {
|
const closeDg = (val:string) => {
|
||||||
if (val == 'OK') {
|
if (val == 'OK') {
|
||||||
if(tree.value.root.children.length===0){
|
// if(tree.value.root.children.length===0){
|
||||||
$q.notify({
|
// $q.notify({
|
||||||
type: 'negative',
|
// type: 'negative',
|
||||||
message: `条件式を設定してください。`
|
// message: `条件式を設定してください。`
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
context.emit("update:conditionTree",tree.value);
|
context.emit("update:conditionTree",tree.value);
|
||||||
}
|
}
|
||||||
showflg.value=false;
|
showflg.value=false;
|
||||||
|
|||||||
@@ -1,157 +1,165 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="q-my-md" v-bind="$attrs">
|
<div class="q-my-md" v-bind="$attrs">
|
||||||
<q-card flat>
|
<q-field v-model="selectedField" :label="displayName" labelColor="primary" :clearable="isSelected" stack-label
|
||||||
<q-card-section class="q-pa-none q-my-sm q-mr-md">
|
:rules="rulesExp" lazy-rules="ondemand" @clear="clear" ref="fieldRef">
|
||||||
<!-- <div class=" q-my-none ">App Field Select</div> -->
|
<template v-slot:control>
|
||||||
<div class="row q-mb-xs">
|
{{ isSelected ? selectedField.app?.name : "(未選択)" }}
|
||||||
<div class="text-primary q-mb-xs text-caption">{{ $props.displayName }}</div>
|
</template>
|
||||||
</div>
|
<template v-slot:hint v-if="!isSelected">
|
||||||
<div class="row">
|
{{ placeholder }}
|
||||||
<div class="col">
|
</template>
|
||||||
<div class="q-mb-xs">{{ selectedField.app?.name || '未選択' }}</div>
|
<template v-slot:append>
|
||||||
</div>
|
<q-icon name="search" class="cursor-pointer" color="primary" @click="showDg" />
|
||||||
<div class="col-1">
|
</template>
|
||||||
<q-btn round flat size="sm" color="primary" icon="search" @click="showDg" />
|
</q-field>
|
||||||
</div>
|
<div v-if="selectedField.fields && selectedField.fields.length > 0">
|
||||||
</div>
|
<q-list bordered>
|
||||||
</q-card-section>
|
<q-virtual-scroll style="max-height: 160px;" :items="selectedField.fields" separator v-slot="{ item, index }">
|
||||||
<q-separator />
|
<q-item :key="index" dense clickable>
|
||||||
<q-card-section class="q-pa-none q-ma-none">
|
<q-item-section>
|
||||||
<div style="">
|
<q-item-label>
|
||||||
<div v-if="selectedField.fields && selectedField.fields.length > 0">
|
{{ item.label }}
|
||||||
<q-list bordered>
|
</q-item-label>
|
||||||
<q-virtual-scroll style="max-height: 160px;" :items="selectedField.fields" separator
|
</q-item-section>
|
||||||
v-slot="{ item, index }">
|
<q-item-section side>
|
||||||
<q-item :key="index" dense clickable>
|
<q-btn round flat size="sm" icon="clear" @click="removeField(index)" />
|
||||||
<q-item-section>
|
</q-item-section>
|
||||||
<q-item-label>
|
</q-item>
|
||||||
{{ item.label }}
|
</q-virtual-scroll>
|
||||||
</q-item-label>
|
</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">
|
|
||||||
<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>
|
</div>
|
||||||
<show-dialog v-model:visible="show" name="フィールド一覧" @close="closeAFBox">
|
<show-dialog v-model:visible="show" name="フィールド一覧" @close="closeAFBox">
|
||||||
<AppFieldSelectBox v-model:selectedField="selectedField" :selectType="selectType" ref="afBox" :fieldTypes="fieldTypes"/>
|
<AppFieldSelectBox v-model:selectedField="selectedField" :selectType="selectType" ref="afBox"
|
||||||
|
:fieldTypes="fieldTypes" />
|
||||||
</show-dialog>
|
</show-dialog>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, ref, watchEffect } from 'vue';
|
import { computed, defineComponent, ref, watchEffect } from 'vue';
|
||||||
import AppFieldSelectBox from '../AppFieldSelectBox.vue';
|
import AppFieldSelectBox from '../AppFieldSelectBox.vue';
|
||||||
import ShowDialog from '../ShowDialog.vue';
|
import ShowDialog from '../ShowDialog.vue';
|
||||||
import { useFlowEditorStore } from 'stores/flowEditor';
|
import { useFlowEditorStore } from 'stores/flowEditor';
|
||||||
|
|
||||||
export interface IApp {
|
export interface IApp {
|
||||||
id: string,
|
id: string,
|
||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
export interface IField {
|
export interface IField {
|
||||||
name: string,
|
name: string,
|
||||||
code: string,
|
code: string,
|
||||||
type: string,
|
type: string,
|
||||||
label?:string
|
label?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAppFields {
|
export interface IAppFields {
|
||||||
app?: IApp,
|
app?: IApp,
|
||||||
fields: IField[]
|
fields: IField[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
name: 'AppFieldSelect',
|
name: 'AppFieldSelect2',
|
||||||
components: {
|
components: {
|
||||||
ShowDialog,
|
ShowDialog,
|
||||||
AppFieldSelectBox
|
AppFieldSelectBox
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
displayName: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
},
|
},
|
||||||
props: {
|
name: {
|
||||||
displayName: {
|
type: String,
|
||||||
type: String,
|
default: '',
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
placeholder: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
modelValue: {
|
|
||||||
type: Object,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
selectType: {
|
|
||||||
type: String,
|
|
||||||
default: 'single'
|
|
||||||
},
|
|
||||||
fieldTypes:{
|
|
||||||
type:Array,
|
|
||||||
default:()=>[]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
setup(props, { emit }) {
|
placeholder: {
|
||||||
const show = ref(false);
|
type: String,
|
||||||
const afBox = ref();
|
default: '',
|
||||||
const selectedField = ref<IAppFields>({
|
},
|
||||||
app: undefined,
|
modelValue: {
|
||||||
fields: []
|
type: Object,
|
||||||
});
|
default: null
|
||||||
if (props.modelValue && 'app' in props.modelValue && 'fields' in props.modelValue) {
|
},
|
||||||
selectedField.value = props.modelValue as IAppFields;
|
selectType: {
|
||||||
}
|
type: String,
|
||||||
const store = useFlowEditorStore();
|
default: 'single'
|
||||||
|
},
|
||||||
const clear = () => {
|
fieldTypes: {
|
||||||
selectedField.value = {
|
type: Array,
|
||||||
fields: []
|
default: () => []
|
||||||
};
|
},
|
||||||
}
|
//例:[val=>!!val ||'入力してください']
|
||||||
|
rules: {
|
||||||
const removeField = (index: number) => {
|
type: String,
|
||||||
selectedField.value.fields.splice(index, 1);
|
default: undefined
|
||||||
}
|
},
|
||||||
|
required: {
|
||||||
const closeAFBox = (val: string) => {
|
type: Boolean,
|
||||||
if (val == 'OK') {
|
default: false
|
||||||
console.log(afBox.value);
|
},
|
||||||
|
requiredMessage: {
|
||||||
selectedField.value = afBox.value.selField;
|
type: String,
|
||||||
}
|
default: ''
|
||||||
};
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
emit('update:modelValue', selectedField.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
store,
|
|
||||||
afBox,
|
|
||||||
show,
|
|
||||||
showDg: () => { show.value = true },
|
|
||||||
selectedField,
|
|
||||||
clear,
|
|
||||||
removeField,
|
|
||||||
closeAFBox,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const show = ref(false);
|
||||||
|
const afBox = ref();
|
||||||
|
const fieldRef = 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 clear = () => {
|
||||||
|
selectedField.value = {
|
||||||
|
fields: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeField = (index: number) => {
|
||||||
|
selectedField.value.fields.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeAFBox = (val: string) => {
|
||||||
|
if (val == 'OK') {
|
||||||
|
console.log(afBox.value);
|
||||||
|
selectedField.value = afBox.value.selField;
|
||||||
|
fieldRef.value.validate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const isSelected = computed(() => {
|
||||||
|
return !!selectedField.value.app
|
||||||
|
});
|
||||||
|
|
||||||
|
const customExp = props.rules === undefined ? [] : eval(props.rules);
|
||||||
|
const errmsg = props.requiredMessage?props.requiredMessage:`${props.displayName}が必須です。`;
|
||||||
|
const requiredExp = props.required ? [((val: any) => (val && val.app && val.fields && val.fields.length > 0) || errmsg)] : [];
|
||||||
|
const rulesExp = [...requiredExp, ...customExp];
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
emit('update:modelValue', selectedField.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
store,
|
||||||
|
afBox,
|
||||||
|
show,
|
||||||
|
showDg: () => { show.value = true },
|
||||||
|
selectedField,
|
||||||
|
clear,
|
||||||
|
removeField,
|
||||||
|
closeAFBox,
|
||||||
|
isSelected,
|
||||||
|
rulesExp,
|
||||||
|
fieldRef
|
||||||
|
};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div v-bind="$attrs">
|
||||||
<q-field :label="displayName" labelColor="primary" stack-label>
|
<q-field :label="displayName" labelColor="primary" stack-label
|
||||||
|
:rules="rulesExp"
|
||||||
|
lazy-rules="ondemand"
|
||||||
|
v-model="selectedApp"
|
||||||
|
ref="fieldRef">
|
||||||
<template v-slot:control>
|
<template v-slot:control>
|
||||||
<q-card flat class="full-width">
|
<q-card flat class="full-width">
|
||||||
<q-card-actions vertical>
|
<q-card-actions vertical>
|
||||||
<q-btn color="grey-3" text-color="black" @click="() => { dgIsShow = true }">アプリ選択</q-btn>
|
<q-btn color="grey-3" text-color="black" @click="() => { dgIsShow = true }">アプリ選択</q-btn>
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
<q-card-section class="text-caption">
|
<q-card-section class="text-caption">
|
||||||
<div v-if="selectedField.app.name">
|
<div v-if="selectedApp.app.name">
|
||||||
{{ selectedField.app.name }}
|
{{ selectedApp.app.name }}
|
||||||
</div>
|
</div>
|
||||||
<div v-else>{{ placeholder }}</div>
|
<div v-else>{{ placeholder }}</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
@@ -43,10 +47,6 @@ export default defineComponent({
|
|||||||
AppSelectBox
|
AppSelectBox
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
context: {
|
|
||||||
type: Array<Props>,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
displayName: {
|
displayName: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
@@ -62,31 +62,50 @@ export default defineComponent({
|
|||||||
modelValue: {
|
modelValue: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null
|
default: null
|
||||||
|
},
|
||||||
|
//例:[val=>!!val ||'入力してください']
|
||||||
|
rules: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
required: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
requiredMessage: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const appDg = ref()
|
const appDg = ref();
|
||||||
|
const fieldRef=ref();
|
||||||
const dgIsShow = ref(false)
|
const dgIsShow = ref(false)
|
||||||
const selectedField = props.modelValue && props.modelValue.app ? props.modelValue : reactive({app:{}});
|
const selectedApp = props.modelValue && props.modelValue.app ? props.modelValue : reactive({app:{}});
|
||||||
const closeDg = (state: string) => {
|
const closeDg = (state: string) => {
|
||||||
dgIsShow.value = false;
|
dgIsShow.value = false;
|
||||||
if (state == 'OK') {
|
if (state == 'OK') {
|
||||||
selectedField.app = appDg.value.selected[0];
|
selectedApp.app = appDg.value.selected[0];
|
||||||
|
fieldRef.value.validate();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
//ルール設定
|
||||||
console.log(selectedField);
|
const customExp = props.rules === undefined ? [] : eval(props.rules);
|
||||||
|
const errmsg = props.requiredMessage?props.requiredMessage:`${props.displayName}を選択してください。`;
|
||||||
|
const requiredExp = props.required ? [((val: any) => (!!val && !!val.app && !!val.app.name) || errmsg)] : [];
|
||||||
|
const rulesExp = [...requiredExp, ...customExp];
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
emit('update:modelValue', selectedField);
|
emit('update:modelValue', selectedApp);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
filter: ref(''),
|
filter: ref(''),
|
||||||
dgIsShow,
|
dgIsShow,
|
||||||
appDg,
|
appDg,
|
||||||
|
fieldRef,
|
||||||
closeDg,
|
closeDg,
|
||||||
selectedField
|
selectedApp,
|
||||||
|
rulesExp
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,9 +23,6 @@ import { ConditionNode, ConditionTree, Operator, OperatorListItem } from 'app/sr
|
|||||||
import { computed, defineComponent, provide, reactive, ref, watchEffect } from 'vue';
|
import { computed, defineComponent, provide, reactive, ref, watchEffect } from 'vue';
|
||||||
import ConditionEditor from '../ConditionEditor/ConditionEditor.vue';
|
import ConditionEditor from '../ConditionEditor/ConditionEditor.vue';
|
||||||
import { IActionProperty } from 'src/types/ActionTypes';
|
import { IActionProperty } from 'src/types/ActionTypes';
|
||||||
import { } from 'src/types/';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'FieldInput',
|
name: 'FieldInput',
|
||||||
@@ -132,7 +129,8 @@ export default defineComponent({
|
|||||||
const isSetted = ref(props.modelValue && props.modelValue !== '');
|
const isSetted = ref(props.modelValue && props.modelValue !== '');
|
||||||
|
|
||||||
const conditionString = computed(() => {
|
const conditionString = computed(() => {
|
||||||
return tree.buildConditionString(tree.root);
|
const condiStr= tree.buildConditionString(tree.root);
|
||||||
|
return condiStr==='()'?'(条件なし)':condiStr;
|
||||||
});
|
});
|
||||||
|
|
||||||
const showDg = () => {
|
const showDg = () => {
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="q-my-md" v-bind="$attrs">
|
||||||
<q-field :label="displayName" labelColor="primary" stack-label>
|
<q-field :label="displayName" labelColor="primary" stack-label
|
||||||
|
v-model="mappingProps"
|
||||||
|
:rules="rulesExp"
|
||||||
|
ref="fieldRef"
|
||||||
|
>
|
||||||
<template v-slot:control>
|
<template v-slot:control>
|
||||||
<q-card flat class="full-width">
|
<q-card flat class="full-width">
|
||||||
<q-card-actions vertical>
|
<q-card-actions vertical>
|
||||||
@@ -17,7 +21,6 @@
|
|||||||
</template>
|
</template>
|
||||||
</q-field>
|
</q-field>
|
||||||
<show-dialog v-model:visible="dgIsShow" name="データマッピング" @close="closeDg" min-width="55vw" min-height="60vh">
|
<show-dialog v-model:visible="dgIsShow" name="データマッピング" @close="closeDg" min-width="55vw" min-height="60vh">
|
||||||
|
|
||||||
<div class="">
|
<div class="">
|
||||||
<div class="row q-col-gutter-x-xs flex-center">
|
<div class="row q-col-gutter-x-xs flex-center">
|
||||||
<div class="col-5">
|
<div class="col-5">
|
||||||
@@ -36,7 +39,7 @@
|
|||||||
キー
|
キー
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<q-virtual-scroll style="max-height: 60vh;" :items="mappingProps" separator v-slot="{ item, index }">
|
<q-virtual-scroll style="max-height: 60vh;" :items="mappingProps.data" separator v-slot="{ item, index }">
|
||||||
<!-- <div class="q-my-sm" v-for="(item, index) in mappingProps" :key="item.id"> -->
|
<!-- <div class="q-my-sm" v-for="(item, index) in mappingProps" :key="item.id"> -->
|
||||||
<div class="row q-pa-sm q-col-gutter-x-md flex-center">
|
<div class="row q-pa-sm q-col-gutter-x-md flex-center">
|
||||||
<div class="col-5">
|
<div class="col-5">
|
||||||
@@ -74,19 +77,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<show-dialog v-model:visible="mappingProps[index].to.isDialogVisible" name="フィールド一覧"
|
<show-dialog v-model:visible="mappingProps.data[index].to.isDialogVisible" name="フィールド一覧"
|
||||||
@close="closeToDg" ref="fieldDlg">
|
@close="closeToDg" ref="fieldDlg">
|
||||||
<FieldSelect v-if="onlySourceSelect" ref="fieldDlg" name="フィールド" :appId="sourceAppId" not_page
|
<FieldSelect v-if="onlySourceSelect" ref="fieldDlg" name="フィールド" :appId="sourceAppId" not_page
|
||||||
:selectedFields="mappingProps[index].to.fields"
|
:selectedFields="mappingProps.data[index].to.fields"
|
||||||
:updateSelects="(fields) => { mappingProps[index].to.fields = fields; mappingProps[index].to.app = sourceApp }">
|
:updateSelects="(fields) => { mappingProps.data[index].to.fields = fields; mappingProps.data[index].to.app = sourceApp }">
|
||||||
</FieldSelect>
|
</FieldSelect>
|
||||||
<AppFieldSelectBox v-else v-model:selectedField="mappingProps[index].to" />
|
<AppFieldSelectBox v-else v-model:selectedField="mappingProps.data[index].to" />
|
||||||
</show-dialog>
|
</show-dialog>
|
||||||
<!-- </div> -->
|
<!-- </div> -->
|
||||||
</q-virtual-scroll>
|
</q-virtual-scroll>
|
||||||
|
|
||||||
<div class="q-mt-lg q-ml-md row ">
|
<div class="q-mt-lg q-ml-md row ">
|
||||||
<q-checkbox size="sm" v-model="createWithNull" label="キーが存在しない場合は新規に作成され、存在する場合はデータが更新されます。" />
|
<q-checkbox size="sm" v-model="mappingProps.createWithNull" label="キーが存在しない場合は新規に作成され、存在する場合はデータが更新されます。" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</show-dialog>
|
</show-dialog>
|
||||||
@@ -115,12 +118,12 @@ type ContextProps = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
type CurrentModelValueType = {
|
interface IMappingSetting {
|
||||||
data: MappingValueType[];
|
data: IMappingValueType[];
|
||||||
createWithNull: boolean;
|
createWithNull: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
type MappingValueType = {
|
interface IMappingValueType {
|
||||||
id: string;
|
id: string;
|
||||||
from: { sharedText?: string };
|
from: { sharedText?: string };
|
||||||
to: {
|
to: {
|
||||||
@@ -157,7 +160,7 @@ export default defineComponent({
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Object as () => CurrentModelValueType,
|
type: Object as () => IMappingSetting,
|
||||||
},
|
},
|
||||||
placeholder: {
|
placeholder: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -171,27 +174,60 @@ export default defineComponent({
|
|||||||
type:Array,
|
type:Array,
|
||||||
default:()=>[]
|
default:()=>[]
|
||||||
},
|
},
|
||||||
|
//例:[val=>!!val ||'入力してください']
|
||||||
|
rules: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
required: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
requiredMessage: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
const fieldRef=ref();
|
||||||
const source = props.context.find(element => element?.props?.name === 'sources')
|
const source = props.context.find(element => element?.props?.name === 'sources')
|
||||||
|
|
||||||
const sourceApp = computed(() => source?.props?.modelValue?.app);
|
const sourceApp = computed(() => source?.props?.modelValue?.app);
|
||||||
|
|
||||||
const sourceAppId = computed(() => sourceApp.value?.id);
|
const sourceAppId = computed(() => sourceApp.value?.id);
|
||||||
|
|
||||||
|
//ルール設定
|
||||||
|
const checkMapping = (val:IMappingSetting)=>{
|
||||||
|
if(!val || !val.data){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
console.log(val);
|
||||||
|
const mappingDatas = val.data.filter(item=>item.from?.sharedText && item.to.fields?.length > 0);
|
||||||
|
return mappingDatas.length>0;
|
||||||
|
}
|
||||||
|
const customExp = props.rules === undefined ? [] : eval(props.rules);
|
||||||
|
const errmsg = props.requiredMessage?props.requiredMessage:`${props.displayName}を選択してください。`;
|
||||||
|
const requiredExp = props.required ? [((val: any) => checkMapping(val) || errmsg)] : [];
|
||||||
|
const rulesExp = [...requiredExp, ...customExp];
|
||||||
|
|
||||||
|
// const mappingProps = ref(props.modelValue?.data ?? []);
|
||||||
|
|
||||||
|
// const createWithNull = ref(props.modelValue?.createWithNull ?? false);
|
||||||
|
|
||||||
|
const mappingProps = reactive<IMappingSetting>({
|
||||||
|
data:props.modelValue?.data ?? [],
|
||||||
|
createWithNull:props.modelValue?.createWithNull ?? false
|
||||||
|
});
|
||||||
|
|
||||||
const closeDg = () => {
|
const closeDg = () => {
|
||||||
emit('update:modelValue', { data: mappingProps.value, createWithNull: createWithNull.value });
|
fieldRef.value.validate();
|
||||||
|
emit('update:modelValue',mappingProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
const closeToDg = () => {
|
const closeToDg = () => {
|
||||||
emit('update:modelValue', { data: mappingProps.value, createWithNull: createWithNull.value });
|
emit('update:modelValue',mappingProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
const mappingProps = ref(props.modelValue?.data ?? []);
|
|
||||||
|
|
||||||
const createWithNull = ref(props.modelValue?.createWithNull ?? false)
|
|
||||||
|
|
||||||
// 外部ソースコンポーネントの appid をリッスンし、変更されたときに現在のコンポーネントを更新します
|
// 外部ソースコンポーネントの appid をリッスンし、変更されたときに現在のコンポーネントを更新します
|
||||||
watch(() => sourceAppId.value, async (newId,) => {
|
watch(() => sourceAppId.value, async (newId,) => {
|
||||||
if (!newId) return;
|
if (!newId) return;
|
||||||
@@ -210,7 +246,7 @@ export default defineComponent({
|
|||||||
.map(f => ({ name: f.label, objectType: 'field', ...f }))
|
.map(f => ({ name: f.label, objectType: 'field', ...f }))
|
||||||
.map(f => {
|
.map(f => {
|
||||||
// 更新前の値を求める
|
// 更新前の値を求める
|
||||||
const beforeData = mappingProps.value.find(m => m.to.fields[0].code === f.code)
|
const beforeData = mappingProps.data.find(m => m.to.fields[0].code === f.code)
|
||||||
return {
|
return {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
from: beforeData?.from ?? {}, // 以前のデータを入力します
|
from: beforeData?.from ?? {}, // 以前のデータを入力します
|
||||||
@@ -235,12 +271,12 @@ export default defineComponent({
|
|||||||
ktAppFields.filter(f => lookupFixedField.includes(f.to.fields[0].code)).forEach(f => f.disabled = true)
|
ktAppFields.filter(f => lookupFixedField.includes(f.to.fields[0].code)).forEach(f => f.disabled = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
mappingProps.value = ktAppFields
|
mappingProps.data = ktAppFields
|
||||||
}
|
}
|
||||||
|
|
||||||
const mappingObjectsInputDisplay = computed(() =>
|
const mappingObjectsInputDisplay = computed(() =>
|
||||||
(mappingProps.value && Array.isArray(mappingProps.value)) ?
|
(mappingProps.data && Array.isArray(mappingProps.data)) ?
|
||||||
mappingProps.value
|
mappingProps.data
|
||||||
.filter(item => item.from?.sharedText && item.to.fields?.length > 0)
|
.filter(item => item.from?.sharedText && item.to.fields?.length > 0)
|
||||||
.map(item => {
|
.map(item => {
|
||||||
return `field(${item.to.app?.id},${item.to.fields[0].label}) = ${item.from.sharedText} `;
|
return `field(${item.to.app?.id},${item.to.fields[0].label}) = ${item.from.sharedText} `;
|
||||||
@@ -251,17 +287,17 @@ export default defineComponent({
|
|||||||
const btnDisable = computed(() => props.onlySourceSelect ? !(source?.props?.modelValue?.app?.id) : false);
|
const btnDisable = computed(() => props.onlySourceSelect ? !(source?.props?.modelValue?.app?.id) : false);
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
emit('update:modelValue', { data: mappingProps.value, createWithNull: createWithNull.value });
|
emit('update:modelValue', mappingProps);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
uuidv4,
|
uuidv4,
|
||||||
dgIsShow: ref(false),
|
dgIsShow: ref(false),
|
||||||
|
fieldRef,
|
||||||
closeDg,
|
closeDg,
|
||||||
toDgIsShow: ref(false),
|
toDgIsShow: ref(false),
|
||||||
closeToDg,
|
closeToDg,
|
||||||
mappingProps,
|
mappingProps,
|
||||||
createWithNull,
|
|
||||||
updateFields,
|
updateFields,
|
||||||
// addMappingObject: () => mappingProps.push(defaultMappingProp()),
|
// addMappingObject: () => mappingProps.push(defaultMappingProp()),
|
||||||
// deleteMappingObject,
|
// deleteMappingObject,
|
||||||
@@ -269,6 +305,8 @@ export default defineComponent({
|
|||||||
sourceApp,
|
sourceApp,
|
||||||
sourceAppId,
|
sourceAppId,
|
||||||
btnDisable,
|
btnDisable,
|
||||||
|
rulesExp,
|
||||||
|
checkMapping,
|
||||||
config: {
|
config: {
|
||||||
canInput: false,
|
canInput: false,
|
||||||
buttonsConfig: [
|
buttonsConfig: [
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<q-field :label="displayName" labelColor="primary" stack-label>
|
<q-field :label="displayName" labelColor="primary" stack-label
|
||||||
|
v-model="processingProps"
|
||||||
|
:rules="rulesExp"
|
||||||
|
lazy-rules="ondemand"
|
||||||
|
ref="fieldRef"
|
||||||
|
>
|
||||||
<template v-slot:control>
|
<template v-slot:control>
|
||||||
<q-card flat class="full-width">
|
<q-card flat class="full-width">
|
||||||
<q-card-actions vertical>
|
<q-card-actions vertical>
|
||||||
@@ -120,9 +125,19 @@ export default defineComponent({
|
|||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
//例:[val=>!!val ||'入力してください']
|
||||||
|
rules: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
required: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
|
const fieldRef=ref();
|
||||||
const source = props.context.find(element => element?.props?.name === 'sources')
|
const source = props.context.find(element => element?.props?.name === 'sources')
|
||||||
|
|
||||||
if (source) {
|
if (source) {
|
||||||
@@ -155,6 +170,7 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const closeDg = () => {
|
const closeDg = () => {
|
||||||
|
fieldRef.value.validate();
|
||||||
emit('update:modelValue', processingProps);
|
emit('update:modelValue', processingProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,6 +234,24 @@ export default defineComponent({
|
|||||||
"label": "最初の値"
|
"label": "最初の値"
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
const checkInput=(val:ValueType)=>{
|
||||||
|
if(!val){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!val.name){
|
||||||
|
return "集計結果の変数名を入力してください";
|
||||||
|
}
|
||||||
|
if(!val.vars || val.vars.length==0){
|
||||||
|
return "集計処理を設定してください";
|
||||||
|
}
|
||||||
|
if(val.vars.some((x)=>!x.vName)){
|
||||||
|
return "集計結果変数名を入力してください";
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const customExp = props.rules === undefined ? [] : eval(props.rules);
|
||||||
|
const requiredExp = props.required ? [(val: any) => checkInput(val)] : [];
|
||||||
|
const rulesExp = [...requiredExp, ...customExp];
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
emit('update:modelValue', processingProps);
|
emit('update:modelValue', processingProps);
|
||||||
@@ -232,6 +266,8 @@ export default defineComponent({
|
|||||||
deleteProcessingObject,
|
deleteProcessingObject,
|
||||||
logicalOperators,
|
logicalOperators,
|
||||||
processingObjectsInputDisplay,
|
processingObjectsInputDisplay,
|
||||||
|
rulesExp,
|
||||||
|
fieldRef
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-bind="$attrs">
|
<div v-bind="$attrs">
|
||||||
<q-input v-model="selectedDate" :label="displayName" :placeholder="placeholder" label-color="primary" mask="date" :rules="['date']" stack-label>
|
<q-input v-model="selectedDate" :label="displayName" :placeholder="placeholder" label-color="primary" mask="date" :rules="rulesExp" stack-label>
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<q-icon name="event" class="cursor-pointer">
|
<q-icon name="event" class="cursor-pointer">
|
||||||
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
<q-popup-proxy cover transition-show="scale" transition-hide="scale">
|
||||||
@@ -43,16 +43,32 @@ export default defineComponent({
|
|||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
//例:[val=>!!val ||'入力してください']
|
||||||
|
rules: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
required:{
|
||||||
|
type:Boolean,
|
||||||
|
default:false
|
||||||
|
},
|
||||||
|
requiredMessage: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const selectedDate = ref(props.modelValue);
|
const selectedDate = ref(props.modelValue);
|
||||||
|
const customExp = props.rules === undefined ? [] : eval(props.rules);
|
||||||
|
const requiredExp = props.required?[((val:any)=>!!val||`${props.displayName}が必須です。`),'date']:['date'];
|
||||||
|
const rulesExp=[...requiredExp,...customExp];
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
emit('update:modelValue', selectedDate.value);
|
emit('update:modelValue', selectedDate.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
selectedDate
|
selectedDate,
|
||||||
|
rulesExp
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-bind="$attrs">
|
<div v-bind="$attrs">
|
||||||
<q-input :label="displayName" v-model="inputValue" label-color="primary" :placeholder="placeholder" stack-label>
|
<q-input :label="displayName" v-model="inputValue" label-color="primary"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:rules="rulesExp"
|
||||||
|
stack-label>
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<q-btn round dense flat icon="add" @click="addButtonEvent()" />
|
<q-btn round dense flat icon="add" @click="addButtonEvent()" />
|
||||||
</template>
|
</template>
|
||||||
@@ -40,12 +43,29 @@ export default defineComponent({
|
|||||||
connectProps:{
|
connectProps:{
|
||||||
type:Object,
|
type:Object,
|
||||||
default:undefined
|
default:undefined
|
||||||
|
},
|
||||||
|
//例:[val=>!!val ||'入力してください']
|
||||||
|
rules: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
required:{
|
||||||
|
type:Boolean,
|
||||||
|
default:false
|
||||||
|
},
|
||||||
|
requiredMessage: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setup(props , { emit }) {
|
setup(props , { emit }) {
|
||||||
const inputValue = ref(props.modelValue);
|
const inputValue = ref(props.modelValue);
|
||||||
const store = useFlowEditorStore();
|
const store = useFlowEditorStore();
|
||||||
|
const customExp = props.rules === undefined ? [] : eval(props.rules);
|
||||||
|
const errmsg = props.requiredMessage?props.requiredMessage:`${props.displayName}を入力してください。`;
|
||||||
|
const requiredExp = props.required ? [((val: any) => !!val || errmsg)] : [];
|
||||||
|
const rulesExp = [...requiredExp, ...customExp];
|
||||||
const addButtonEvent=()=>{
|
const addButtonEvent=()=>{
|
||||||
const eventId =store.currentFlow?.getRoot()?.name;
|
const eventId =store.currentFlow?.getRoot()?.name;
|
||||||
if(eventId===undefined){return;}
|
if(eventId===undefined){return;}
|
||||||
@@ -69,14 +89,14 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
emit('update:modelValue', inputValue.value);
|
emit('update:modelValue', inputValue.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
inputValue,
|
inputValue,
|
||||||
addButtonEvent
|
addButtonEvent,
|
||||||
|
rulesExp
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-bind="$attrs">
|
<div v-bind="$attrs">
|
||||||
<q-field v-model="selectedField" :label="displayName" labelColor="primary" :clearable="isSelected" stack-label
|
<q-field v-model="selectedField" :label="displayName" labelColor="primary" :clearable="isSelected" stack-label
|
||||||
:bottom-slots="!isSelected">
|
:bottom-slots="!isSelected"
|
||||||
|
:rules="rulesExp"
|
||||||
|
>
|
||||||
<template v-slot:control>
|
<template v-slot:control>
|
||||||
<q-chip color="primary" text-color="white" v-if="isSelected">
|
<q-chip color="primary" text-color="white" v-if="isSelected">
|
||||||
{{ selectedField.name }}
|
{{ selectedField.name }}
|
||||||
@@ -74,6 +76,19 @@ export default defineComponent({
|
|||||||
type: Object,
|
type: Object,
|
||||||
default: null
|
default: null
|
||||||
},
|
},
|
||||||
|
//例:[val=>!!val ||'入力してください']
|
||||||
|
rules: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
required: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
requiredMessage: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
@@ -85,6 +100,11 @@ export default defineComponent({
|
|||||||
const isSelected = computed(() => {
|
const isSelected = computed(() => {
|
||||||
return selectedField.value !== null && typeof selectedField.value === 'object' && ('name' in selectedField.value)
|
return selectedField.value !== null && typeof selectedField.value === 'object' && ('name' in selectedField.value)
|
||||||
});
|
});
|
||||||
|
//ルール設定
|
||||||
|
const customExp = props.rules === undefined ? [] : eval(props.rules);
|
||||||
|
const errmsg = props.requiredMessage?props.requiredMessage:`${props.displayName}が必須です。`;
|
||||||
|
const requiredExp = props.required ? [((val: any) => (!!val && typeof val==='object' && !!val.name) || errmsg)] : [];
|
||||||
|
const rulesExp = [...requiredExp, ...customExp];
|
||||||
|
|
||||||
const showDg = () => {
|
const showDg = () => {
|
||||||
show.value = true;
|
show.value = true;
|
||||||
@@ -109,7 +129,8 @@ export default defineComponent({
|
|||||||
selectedField,
|
selectedField,
|
||||||
isSelected,
|
isSelected,
|
||||||
filter:ref(''),
|
filter:ref(''),
|
||||||
selectedFields
|
selectedFields,
|
||||||
|
rulesExp
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { kMaxLength } from 'buffer';
|
|
||||||
import { defineComponent, ref, watchEffect, computed } from 'vue';
|
import { defineComponent, ref, watchEffect, computed } from 'vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@@ -50,8 +49,16 @@ export default defineComponent({
|
|||||||
type: String,
|
type: String,
|
||||||
default: undefined
|
default: undefined
|
||||||
},
|
},
|
||||||
|
required:{
|
||||||
|
type:Boolean,
|
||||||
|
default:false
|
||||||
|
},
|
||||||
|
requiredMessage: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
modelValue: {
|
modelValue: {
|
||||||
// type: Any,
|
type: null as any,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -75,8 +82,11 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
// const inputValue = ref(props.modelValue);
|
// const inputValue = ref(props.modelValue);
|
||||||
const rulesExp = props.rules === undefined ? null : eval(props.rules);
|
|
||||||
|
|
||||||
|
const customExp = props.rules === undefined ? [] : eval(props.rules);
|
||||||
|
const errmsg = props.requiredMessage?props.requiredMessage:`${props.displayName}が必須です。`;
|
||||||
|
const requiredExp = props.required?[((val:any)=>!!val || errmsg )]:[];
|
||||||
|
const rulesExp=[...requiredExp,...customExp];
|
||||||
// const finalValue = computed(() => {
|
// const finalValue = computed(() => {
|
||||||
// return props.name !== 'verName' ? inputValue.value : {
|
// return props.name !== 'verName' ? inputValue.value : {
|
||||||
// name: inputValue.value,
|
// name: inputValue.value,
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-bind="$attrs">
|
<div v-bind="$attrs">
|
||||||
<q-input :label="displayName" label-color="primary" v-model="inputValue" :placeholder="placeholder" autogrow
|
<q-input :label="displayName" label-color="primary" v-model="inputValue"
|
||||||
stack-label />
|
:placeholder="placeholder"
|
||||||
|
:rules="rulesExp"
|
||||||
|
autogrow
|
||||||
|
stack-label />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -32,17 +35,34 @@ export default defineComponent({
|
|||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
//例:[val=>!!val ||'入力してください']
|
||||||
|
rules: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
required:{
|
||||||
|
type:Boolean,
|
||||||
|
default:false
|
||||||
|
},
|
||||||
|
requiredMessage: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const inputValue = ref(props.modelValue);
|
const inputValue = ref(props.modelValue);
|
||||||
|
const customExp = props.rules === undefined ? [] : eval(props.rules);
|
||||||
|
const errmsg = props.requiredMessage?props.requiredMessage:`${props.displayName}が必須です。`;
|
||||||
|
const requiredExp = props.required?[((val:any)=>!!val || errmsg )]:[];
|
||||||
|
const rulesExp=[...requiredExp,...customExp];
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
emit('update:modelValue', inputValue.value);
|
emit('update:modelValue', inputValue.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
inputValue,
|
inputValue,
|
||||||
|
rulesExp
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -49,6 +49,14 @@ export default defineComponent({
|
|||||||
type:String,
|
type:String,
|
||||||
default:undefined
|
default:undefined
|
||||||
},
|
},
|
||||||
|
required:{
|
||||||
|
type:Boolean,
|
||||||
|
default:false
|
||||||
|
},
|
||||||
|
requiredMessage: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: [Number , String],
|
type: [Number , String],
|
||||||
default: undefined
|
default: undefined
|
||||||
@@ -57,23 +65,10 @@ export default defineComponent({
|
|||||||
|
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const numValue = ref(props.modelValue);
|
const numValue = ref(props.modelValue);
|
||||||
const rulesExp = props.rules===undefined?null : eval(props.rules);
|
const customExp = props.rules === undefined ? [] : eval(props.rules);
|
||||||
const isError = computed(()=>{
|
const errmsg = props.requiredMessage?props.requiredMessage:`${props.displayName}が必須です。`;
|
||||||
const val = numValue.value;
|
const requiredExp = props.required?[((val:any)=>!!val || errmsg )]:[];
|
||||||
if (val === undefined) {
|
const rulesExp=[...requiredExp,...customExp];
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const numVal = typeof val === "string" ? parseInt(val) : val;
|
|
||||||
// Ensure parsed value is a valid number
|
|
||||||
if (isNaN(numVal)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Check against min and max boundaries, if defined
|
|
||||||
if ((props.min !== undefined && numVal < props.min) || (props.max !== undefined && numVal > props.max)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
watchEffect(()=>{
|
watchEffect(()=>{
|
||||||
emit("update:modelValue",numValue.value);
|
emit("update:modelValue",numValue.value);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
elevated
|
elevated
|
||||||
overlay
|
overlay
|
||||||
>
|
>
|
||||||
|
<q-form @submit="save" autocomplete="off" class="full-height">
|
||||||
<q-card class="column" style="max-width: 300px;min-height: 100%">
|
<q-card class="column" style="max-width: 300px;min-height: 100%">
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<div class="text-h6">{{ actionNode?.subTitle }}:設定</div>
|
<div class="text-h6">{{ actionNode?.subTitle }}:設定</div>
|
||||||
@@ -21,16 +22,17 @@
|
|||||||
|
|
||||||
<q-card-actions align="right" class="bg-white text-teal">
|
<q-card-actions align="right" class="bg-white text-teal">
|
||||||
<q-btn flat label="キャンセル" @click="cancel" outline dense padding="none sm" color="primary"/>
|
<q-btn flat label="キャンセル" @click="cancel" outline dense padding="none sm" color="primary"/>
|
||||||
<q-btn flat label="更新" @click="save" outline dense padding="none sm" color="primary" />
|
<q-btn flat label="更新" type="submit" outline dense padding="none sm" color="primary" />
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
</q-card>
|
</q-card>
|
||||||
|
</q-form>
|
||||||
</q-drawer>
|
</q-drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { ref,defineComponent, PropType ,watchEffect} from 'vue'
|
import { ref,defineComponent, PropType ,watchEffect} from 'vue'
|
||||||
import PropertyList from 'components/right/PropertyList.vue';
|
import PropertyList from 'components/right/PropertyList.vue';
|
||||||
import { IActionNode } from 'src/types/ActionTypes';
|
import { IActionNode, IActionProperty } from 'src/types/ActionTypes';
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'PropertyPanel',
|
name: 'PropertyPanel',
|
||||||
components: {
|
components: {
|
||||||
@@ -47,14 +49,28 @@ import { IActionNode } from 'src/types/ActionTypes';
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: [
|
emits: [
|
||||||
'update:drawerRight'
|
'update:drawerRight',
|
||||||
|
'saveActionProps'
|
||||||
],
|
],
|
||||||
setup(props,{emit}) {
|
setup(props,{emit}) {
|
||||||
const showPanel =ref(props.drawerRight);
|
const showPanel =ref(props.drawerRight);
|
||||||
const actionProps =ref(props.actionNode?.actionProps);
|
|
||||||
|
const cloneProps = (actionProps:IActionProperty[]):IActionProperty[]|null=>{
|
||||||
|
if(!actionProps){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const json=JSON.stringify(actionProps);
|
||||||
|
return JSON.parse(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
const actionProps =ref(cloneProps(props.actionNode?.actionProps));
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
|
if(showPanel.value!==undefined){
|
||||||
|
showPanel.value = props.drawerRight;
|
||||||
|
}
|
||||||
showPanel.value = props.drawerRight;
|
showPanel.value = props.drawerRight;
|
||||||
actionProps.value= props.actionNode?.actionProps;
|
actionProps.value= cloneProps(props.actionNode?.actionProps);
|
||||||
});
|
});
|
||||||
|
|
||||||
const cancel = async() =>{
|
const cancel = async() =>{
|
||||||
@@ -64,6 +80,7 @@ import { IActionNode } from 'src/types/ActionTypes';
|
|||||||
|
|
||||||
const save = async () =>{
|
const save = async () =>{
|
||||||
showPanel.value=false;
|
showPanel.value=false;
|
||||||
|
emit('saveActionProps', actionProps.value);
|
||||||
emit('update:drawerRight',false )
|
emit('update:drawerRight',false )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-bind="$attrs">
|
<div v-bind="$attrs">
|
||||||
<q-select v-model="selectedValue" :use-chips="multiple" :label="displayName" label-color="primary" :options="options" stack-label
|
<q-select v-model="selectedValue" :use-chips="multiple" :label="displayName" label-color="primary"
|
||||||
|
:options="options"
|
||||||
|
stack-label
|
||||||
|
:rules="rulesExp"
|
||||||
:multiple="multiple"/>
|
:multiple="multiple"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -32,6 +35,19 @@ export default defineComponent({
|
|||||||
type: [Array,String],
|
type: [Array,String],
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
//例:[val=>!!val ||'入力してください']
|
||||||
|
rules: {
|
||||||
|
type: String,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
required:{
|
||||||
|
type:Boolean,
|
||||||
|
default:false
|
||||||
|
},
|
||||||
|
requiredMessage: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
},
|
},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const selectedValue = ref(props.modelValue);
|
const selectedValue = ref(props.modelValue);
|
||||||
@@ -41,10 +57,14 @@ export default defineComponent({
|
|||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
emit('update:modelValue', selectedValue.value);
|
emit('update:modelValue', selectedValue.value);
|
||||||
});
|
});
|
||||||
|
const customExp = props.rules === undefined ? [] : eval(props.rules);
|
||||||
|
const errmsg = props.requiredMessage?props.requiredMessage:`${props.displayName}を選択してください。`;
|
||||||
|
const requiredExp = props.required?[((val:any)=>!!val || errmsg )]:[];
|
||||||
|
const rulesExp=[...requiredExp,...customExp];
|
||||||
return {
|
return {
|
||||||
selectedValue,
|
selectedValue,
|
||||||
multiple
|
multiple,
|
||||||
|
rulesExp
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
@deleteNode="onDeleteNode" @deleteAllNextNodes="onDeleteAllNextNodes" @copyFlow="onCopyFlow"></node-item>
|
@deleteNode="onDeleteNode" @deleteAllNextNodes="onDeleteAllNextNodes" @copyFlow="onCopyFlow"></node-item>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<PropertyPanel :actionNode="store.activeNode" v-model:drawerRight="drawerRight"></PropertyPanel>
|
<PropertyPanel :actionNode="store.activeNode" v-model:drawerRight="drawerRight" @save-action-props="onSaveActionProps"></PropertyPanel>
|
||||||
</q-layout>
|
</q-layout>
|
||||||
<ShowDialog v-model:visible="showAddAction" name="アクション" @close="closeDg" min-width="500px" min-height="500px">
|
<ShowDialog v-model:visible="showAddAction" name="アクション" @close="closeDg" min-width="500px" min-height="500px">
|
||||||
<template v-slot:toolbar>
|
<template v-slot:toolbar>
|
||||||
@@ -193,6 +193,12 @@ const onDeploy = async () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onSaveActionProps=(props:IActionProperty[])=>{
|
||||||
|
if(store.activeNode){
|
||||||
|
store.activeNode.actionProps=props;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const onSaveFlow = async () => {
|
const onSaveFlow = async () => {
|
||||||
const targetFlow = store.selectedFlow;
|
const targetFlow = store.selectedFlow;
|
||||||
if (targetFlow === undefined) {
|
if (targetFlow === undefined) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export interface FlowEditorState {
|
|||||||
activeNode: IActionNode | undefined;
|
activeNode: IActionNode | undefined;
|
||||||
eventTree: KintoneEventManager;
|
eventTree: KintoneEventManager;
|
||||||
selectedEvent: IKintoneEvent | undefined;
|
selectedEvent: IKintoneEvent | undefined;
|
||||||
expandedScreen: any[];
|
expandedScreen: string[];
|
||||||
}
|
}
|
||||||
const flowCtrl = new FlowCtrl();
|
const flowCtrl = new FlowCtrl();
|
||||||
const eventTree = new KintoneEventManager();
|
const eventTree = new KintoneEventManager();
|
||||||
@@ -62,6 +62,10 @@ export const useFlowEditorStore = defineStore('flowEditor', {
|
|||||||
},
|
},
|
||||||
selectFlow(flow: IActionFlow | undefined) {
|
selectFlow(flow: IActionFlow | undefined) {
|
||||||
this.selectedFlow = flow;
|
this.selectedFlow = flow;
|
||||||
|
if(flow!==undefined){
|
||||||
|
const eventId = flow.getRoot()?.name;
|
||||||
|
this.selectedEvent=this.eventTree.findEventById(eventId) as IKintoneEvent;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setActiveNode(node: IActionNode) {
|
setActiveNode(node: IActionNode) {
|
||||||
this.activeNode = node;
|
this.activeNode = node;
|
||||||
@@ -84,15 +88,23 @@ export const useFlowEditorStore = defineStore('flowEditor', {
|
|||||||
if (actionFlows === undefined || actionFlows.length === 0) {
|
if (actionFlows === undefined || actionFlows.length === 0) {
|
||||||
this.flows = [];
|
this.flows = [];
|
||||||
this.selectedFlow = undefined;
|
this.selectedFlow = undefined;
|
||||||
|
this.expandedScreen =[];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setFlows(actionFlows);
|
this.setFlows(actionFlows);
|
||||||
if (actionFlows && actionFlows.length > 0) {
|
if (actionFlows && actionFlows.length > 0) {
|
||||||
this.selectFlow(actionFlows[0]);
|
this.selectFlow(actionFlows[0]);
|
||||||
}
|
}
|
||||||
const expandNames = actionFlows.map((flow) => flow.getRoot()?.title);
|
const expandEventIds = actionFlows.map((flow) => flow.getRoot()?.name);
|
||||||
|
const expandScreens:string[]=[];
|
||||||
|
expandEventIds.forEach((eventid)=>{
|
||||||
|
const eventNode=this.eventTree.findEventById(eventid||'');
|
||||||
|
if(eventNode){
|
||||||
|
expandScreens.push(eventNode.parentId);
|
||||||
|
}
|
||||||
|
});
|
||||||
// const expandName =actionFlows[0].getRoot()?.title;
|
// const expandName =actionFlows[0].getRoot()?.title;
|
||||||
this.expandedScreen = expandNames;
|
this.expandedScreen = expandScreens;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* フローをDBに保存及び更新する
|
* フローをDBに保存及び更新する
|
||||||
|
|||||||
@@ -200,12 +200,13 @@ export class ConditionTree {
|
|||||||
return conditionString;
|
return conditionString;
|
||||||
} else {
|
} else {
|
||||||
const condNode=node as ConditionNode;
|
const condNode=node as ConditionNode;
|
||||||
if (condNode.object && condNode.operator ) {
|
if (condNode.object && condNode.object.sharedText && condNode.operator ) {
|
||||||
// let value=condNode.value;
|
// let value=condNode.value;
|
||||||
// if(value && typeof value ==='object' && ('label' in value)){
|
// if(value && typeof value ==='object' && ('label' in value)){
|
||||||
// value =condNode.value.label;
|
// value =condNode.value.label;
|
||||||
// }
|
// }
|
||||||
return `${condNode.object.sharedText} ${typeof condNode.operator === 'object' ? condNode.operator.label : condNode.operator} ${condNode.value.sharedText}`;
|
const rightVal = condNode.value.sharedText || '""';
|
||||||
|
return `${condNode.object.sharedText} ${typeof condNode.operator === 'object' ? condNode.operator.label : condNode.operator} ${rightVal}`;
|
||||||
// return `${typeof condNode.object.name === 'object' ? condNode.object.name.name : condNode.object.name} ${typeof condNode.operator === 'object' ? condNode.operator.label : condNode.operator} '${value}'`;
|
// return `${typeof condNode.object.name === 'object' ? condNode.object.name.name : condNode.object.name} ${typeof condNode.operator === 'object' ? condNode.operator.label : condNode.operator} '${value}'`;
|
||||||
} else {
|
} else {
|
||||||
return '';
|
return '';
|
||||||
|
|||||||
Reference in New Issue
Block a user