condtion tree
This commit is contained in:
195
frontend/src/components/main/NodeCondition.vue
Normal file
195
frontend/src/components/main/NodeCondition.vue
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
<template>
|
||||||
|
<div class="q-pa-md">
|
||||||
|
<q-tree :nodes="tree" node-key="num" v-if="tree.length" default-expand-all>
|
||||||
|
<template v-slot:header-root="prop">
|
||||||
|
<div class="row items-center" @click.stop>
|
||||||
|
<q-icon :name="prop.node.icon || 'share'" color="orange" size="28px" class="q-mr-sm" />
|
||||||
|
<div style="width:100px">
|
||||||
|
<q-select v-model="prop.node.logicalOperator" :options="logicalOperators" label="ロジクール"></q-select>
|
||||||
|
</div>
|
||||||
|
<q-btn @click="removeNode(prop.node)" class="q-ml-md" color="negative" icon="delete" size="5px"></q-btn>
|
||||||
|
<q-btn-dropdown class="q-ml-md" color="primary" icon="add" size="5px">
|
||||||
|
<q-list>
|
||||||
|
<q-item clickable v-close-popup @click="addGroup(prop.node, logicalOperators[0])">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>Group</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<q-item clickable v-close-popup @click.stop="addCondition(prop.node)">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>Condtion</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-btn-dropdown>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-slot:header-generic="prop" >
|
||||||
|
<div class="row items-center" @click.stop>
|
||||||
|
<q-icon :name="prop.node.icon || 'star'" color="orange" size="28px" class="q-mr-sm" />
|
||||||
|
<div v-if="prop.node.type === 'group'">
|
||||||
|
<q-icon :name="prop.node.icon || 'share'" color="orange" size="28px" class="q-mr-sm" />
|
||||||
|
<div style="width:100px">
|
||||||
|
<q-select v-model="prop.node.logicalOperator" :options="logicalOperators" label="ロジクール"></q-select>
|
||||||
|
</div>
|
||||||
|
<q-btn @click="removeNode(prop.node)" class="q-ml-md" color="negative" icon="delete" size="5px"></q-btn>
|
||||||
|
<q-btn-dropdown class="q-ml-md" color="primary" icon="add" size="5px">
|
||||||
|
<q-list>
|
||||||
|
<q-item clickable v-close-popup @click="addGroup(prop.node, logicalOperators[0])">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>Group</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<q-item clickable v-close-popup @click="addCondition(prop.node)">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>Condtion</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-btn-dropdown>
|
||||||
|
</div>
|
||||||
|
<div @click.stop @keypress.stop v-else >
|
||||||
|
<q-select v-model="prop.node.object" :options="objects" label="フィールド"></q-select>
|
||||||
|
<q-select v-model="prop.node.operator" :options="operators" label="オペレーター"></q-select>
|
||||||
|
<q-input v-model="prop.node.value" label="値"></q-input>
|
||||||
|
<q-btn @click="removeNode(prop.node)" class="q-ml-md" color="negative" icon="delete" size="5px"></q-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</q-tree>
|
||||||
|
<q-btn @click="addGroup(null, logicalOperators[0])" 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>
|
||||||
|
<p>{{ conditionString }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const conditionString = ref('');
|
||||||
|
const tree = ref([]);
|
||||||
|
let num = 0;
|
||||||
|
|
||||||
|
const logicalOperators = [
|
||||||
|
{ label: 'AND', value: 'AND' },
|
||||||
|
{ label: 'OR', value: 'OR' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const objects = [
|
||||||
|
{ label: 'Field 1', value: 'field1' },
|
||||||
|
{ label: 'Field 2', value: 'field2' },
|
||||||
|
{ label: 'Field 3', value: 'field3' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const operators = [
|
||||||
|
{ label: 'Equals', value: '=' },
|
||||||
|
{ label: 'Not Equals', value: '<>' },
|
||||||
|
{ label: 'Greater Than', value: '>' },
|
||||||
|
{ label: 'Less Than', value: '<' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const buildConditionString = (node) => {
|
||||||
|
if (node.type === 'group') {
|
||||||
|
let conditionString = '(';
|
||||||
|
for (let i = 0; i < node.children.length; i++) {
|
||||||
|
let childConditionString = buildConditionString(node.children[i]);
|
||||||
|
if (childConditionString !== '') {
|
||||||
|
conditionString += childConditionString;
|
||||||
|
if (i < node.children.length - 1) {
|
||||||
|
conditionString += ` ${node.logicalOperator.value} `;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
conditionString += ')';
|
||||||
|
return conditionString;
|
||||||
|
} else {
|
||||||
|
if (node.object && node.operator && node.value) {
|
||||||
|
return `${node.object.value} ${node.operator.value} '${node.value}'`;
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getConditionString = () => {
|
||||||
|
conditionString.value = buildConditionString(tree.value[0]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addGroup = (node, logicalOperator = 'AND') => {
|
||||||
|
const newNode = {
|
||||||
|
header: 'generic',
|
||||||
|
num: num,
|
||||||
|
type: 'group',
|
||||||
|
logicalOperator: logicalOperator,
|
||||||
|
children: [],
|
||||||
|
parent: node,
|
||||||
|
};
|
||||||
|
num++;
|
||||||
|
const childNode = {
|
||||||
|
header: 'generic',
|
||||||
|
index: num,
|
||||||
|
type: 'condition',
|
||||||
|
logicalOperator: logicalOperator,
|
||||||
|
object: objects[0],
|
||||||
|
operator: operators[0],
|
||||||
|
value: '',
|
||||||
|
children: [],
|
||||||
|
parent: newNode,
|
||||||
|
};
|
||||||
|
newNode.children.push(childNode);
|
||||||
|
if (node === null) {
|
||||||
|
newNode.header = 'root';
|
||||||
|
tree.value.push(newNode);
|
||||||
|
} else {
|
||||||
|
node.children.push(newNode);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const addCondition = (node) => {
|
||||||
|
const newNode = {
|
||||||
|
header: 'generic',
|
||||||
|
num: num,
|
||||||
|
type: 'condition',
|
||||||
|
object: objects[0],
|
||||||
|
operator: operators[0],
|
||||||
|
value: '',
|
||||||
|
children: [],
|
||||||
|
parent: node,
|
||||||
|
};
|
||||||
|
num++;
|
||||||
|
node.children.push(newNode);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeNode = (node) => {
|
||||||
|
if (node.header === 'root') {
|
||||||
|
tree.value = [];
|
||||||
|
} else {
|
||||||
|
const index = node.parent.children.indexOf(node);
|
||||||
|
if (index != -1) {
|
||||||
|
node.parent.children.splice(index, 1);
|
||||||
|
if (node.parent.children.length == 0) {
|
||||||
|
removeNode(node.parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
conditionString,
|
||||||
|
tree,
|
||||||
|
num,
|
||||||
|
logicalOperators,
|
||||||
|
objects,
|
||||||
|
operators,
|
||||||
|
buildConditionString,
|
||||||
|
getConditionString,
|
||||||
|
addGroup,
|
||||||
|
addCondition,
|
||||||
|
removeNode,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
18
frontend/src/pages/conditionPage.vue
Normal file
18
frontend/src/pages/conditionPage.vue
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<template>
|
||||||
|
<q-page>
|
||||||
|
<div class="flowchart">
|
||||||
|
<node-condition></node-condition>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</q-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import NodeCondition from 'src/components/main/NodeCondition.vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.flowchart {
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user