条件エディタ追加

This commit is contained in:
2024-01-22 10:52:55 +09:00
parent 276e5e9122
commit 5cd6d02f6e
29 changed files with 1209 additions and 382 deletions

View File

@@ -0,0 +1,235 @@
<template>
<!-- <q-toolbar class="bg-grey-3" flat dense round icon="menu" aria-label="Menu" @click.stop>
<q-toolbar-title>条件エディタ</q-toolbar-title>
<q-space></q-space>
<q-btn flat round dense icon="info" color="blue" @click="showingCondition=!showingCondition"></q-btn>
</q-toolbar> -->
<div class="q-pa-md">
<q-tree :nodes="[tree.root]" node-key="index" children-key="children"
tick-strategy="strict" v-model:ticked="ticked" :expanded="expanded" default-expand-all dense color="primary" >
<template v-slot:header-root="prop">
<!-- root -->
<div class="row items-center" @click.stop>
<q-select v-model="prop.node.logicalOperator" :options="logicalOperators" filled outlined dense></q-select>
<q-btn flat round dense icon="more_horiz" size="sm" >
<q-menu auto-close anchor="top right">
<q-list>
<q-item clickable @click="addGroup(prop.node, LogicalOperator.AND)">
<q-item-section avatar><q-icon name="playlist_add" ></q-icon></q-item-section>
<q-item-section>グループの追加</q-item-section>
</q-item>
<q-item clickable @click="addCondition(prop.node)">
<q-item-section avatar><q-icon name="add_circle_outline" ></q-icon></q-item-section>
<q-item-section >条件式の追加</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</div>
</template>
<template v-slot:header-generic="prop">
<!-- logic group -->
<div v-if="prop.node.type !== NodeType.Condition" class="row items-center" @click.stop>
<q-select v-model="prop.node.logicalOperator" :options="logicalOperators" :outlined="true" :filled="true" :dense="true"></q-select>
<q-btn flat round dense icon="more_horiz" size="sm" >
<q-menu auto-close anchor="top right">
<q-list>
<q-item clickable @click="addGroup(prop.node, LogicalOperator.AND)">
<q-item-section avatar><q-icon name="playlist_add" ></q-icon></q-item-section>
<q-item-section >グループ追加</q-item-section>
</q-item>
<q-item clickable @click="addCondition(prop.node)">
<q-item-section avatar><q-icon name="add_circle_outline" ></q-icon></q-item-section>
<q-item-section >条件式追加</q-item-section>
</q-item>
<q-separator inset/>
<q-item clickable @click="moveUp(prop.node)">
<q-item-section avatar><q-icon name="arrow_upward" ></q-icon></q-item-section>
<q-item-section >一つ上に移動</q-item-section>
</q-item>
<q-item clickable @click="moveDown(prop.node)">
<q-item-section avatar><q-icon name="arrow_downward" ></q-icon></q-item-section>
<q-item-section >一つ下に移動</q-item-section>
</q-item>
<q-separator inset/>
<q-item clickable @click="removeNode(prop.node)">
<q-item-section avatar><q-icon name="delete" color="negative"></q-icon></q-item-section>
<q-item-section >削除</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</div>
<!-- condition -->
<div @click.stop @keypress.stop v-else >
<div class="row no-wrap items-center">
<ConditionObject v-bind="prop.node" v-model="prop.node.object" class="col-4"></ConditionObject>
<q-select v-model="prop.node.operator" :options="operators" class="operator" :outlined="true" :dense="true"></q-select>
<q-input v-if="!prop.node.object || !('options' in prop.node.object)"
v-model="prop.node.value"
class="condition-value" :outlined="true" :dense="true" ></q-input>
<q-select v-if="prop.node.object && ('options' in prop.node.object)"
v-model="prop.node.value"
:options="objectValueOptions(prop.node.object.options)"
clearable
value-key="index"
class="condition-value" :outlined="true" :dense="true" ></q-select>
<q-btn flat round dense icon="more_horiz" size="sm" >
<q-menu auto-close anchor="top right">
<q-list>
<q-item clickable @click="moveUp(prop.node)">
<q-item-section avatar><q-icon name="arrow_upward" ></q-icon></q-item-section>
<q-item-section >一つ上に移動</q-item-section>
</q-item>
<q-item clickable @click="moveDown(prop.node)">
<q-item-section avatar><q-icon name="arrow_downward" ></q-icon></q-item-section>
<q-item-section >一つ下に移動</q-item-section>
</q-item>
<q-separator inset/>
<q-item clickable @click="removeNode(prop.node)">
<q-item-section avatar><q-icon name="delete" color="negative"></q-icon></q-item-section>
<q-item-section>削除</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</div>
</div>
</template>
</q-tree>
<!-- <q-btn @click="addCondition(tree.root)" class="q-mt-md" color="primary" icon="mdi-plus">Add Condition</q-btn> -->
<!-- <q-btn @click="getConditionString()" class="q-mt-md" color="primary" icon="mdi-plus">Show Condtion</q-btn>
<q-btn @click="getConditionJson()" class="q-mt-md" color="primary" icon="mdi-plus">Show Condtion data</q-btn>
<q-btn @click="LoadCondition()" class="q-mt-md" color="primary" icon="mdi-plus">Load Condition</q-btn> -->
<q-tooltip anchor="center middle" v-model="showingCondition" no-parent-event>
{{ conditionString }}
</q-tooltip>
</div>
</template>
<script lang="ts">
import { defineComponent,ref,reactive, computed } from 'vue';
import { INode,ConditionTree,GroupNode,ConditionNode, LogicalOperator,Operator,NodeType } from '../../types/Conditions';
import ConditionObject from './ConditionObject.vue';
export default defineComponent( {
name: 'NodeCondition',
components: {
ConditionObject
},
props:{
conditionTree: {
type: ConditionTree,
default: null
},
show:{
type:Boolean,
default:false
}
},
setup(props) {
const ticked= ref([]);
const showingCondition=ref(false);
const logicalOperators = computed(()=>{
const opts=[];
for(const op in LogicalOperator){
opts.push(LogicalOperator[op as keyof typeof LogicalOperator]);
}
return opts;
});
const operators =computed(()=>{
const opts=[];
for(const op in Operator){
opts.push(Operator[op as keyof typeof Operator]);
}
return opts;
});
const tree = reactive(props.conditionTree);
const conditionString = computed(()=>{
return tree.buildConditionString(tree.root);
});
const objectValueOptions=(options:any):any[]=>{
const opts:any[] =[];
Object.keys(options).forEach((key) =>
{
const opt=options[key];
opts.push(opt);
});
return opts;
};
const addGroup = (parent:GroupNode, logicOp:LogicalOperator) => {
if(!parent){
parent=tree.root;
}
tree.addNode(parent,new GroupNode(logicOp,parent));
};
const addCondition = (parent:GroupNode) => {
const newNode = new ConditionNode(LogicalOperator.AND,{},Operator.Equal,'',parent);
tree.addNode(parent,newNode);
};
const removeNode = (node:INode) => {
tree.removeNode(node);
};
const moveUp =(node:INode)=>{
tree.moveNode(node,'up');
}
const moveDown =(node:INode)=>{
tree.moveNode(node,'down');
}
const getConditionJson=()=>{
return tree.toJson();
}
const LoadCondition=()=>{
tree.fromJson(conditionString.value);
}
const expanded=computed(()=>tree.getGroups(tree.root));
// addCondition(tree.root);
return {
showingCondition,
conditionString,
tree,
ticked,
logicalOperators,
operators,
addGroup,
addCondition,
removeNode,
moveUp,
moveDown,
LogicalOperator,
Operator,
NodeType,
getConditionJson,
LoadCondition,
objectValueOptions,
expanded
};
},
});
</script>
<style lang="scss">
.condition-value{
min-width: 200px;
max-height: 40px;
padding: 2px;
}
.operator{
min-width: 150px;
max-height: 40px;
padding: 2px;
text-align: center;
font-size: 12pt;
}
</style>