1<template>
2 <div
3 class="rounded-6 border border-outline-gray-2 p-3 flex flex-col gap-4 w-full"
4 >
5 <template v-for="(condition, i) in props.conditions" :key="condition.field">
6 <CFCondition
7 v-if="Array.isArray(condition)"
8 :condition="condition"
9 :isChild="props.isChild"
10 :itemIndex="i"
11 @remove="removeCondition(condition)"
12 @unGroupConditions="unGroupConditions(condition)"
13 :level="props.level + 1"
14 @toggleConjunction="toggleConjunction"
15 :isGroup="isGroupCondition(condition[0])"
16 :conjunction="getConjunction()"
17 @turnIntoGroup="turnIntoGroup(condition)"
18 :disableAddCondition="props.disableAddCondition"
19 />
20 </template>
21 <div v-if="props.isChild" class="flex">
22 <Dropdown v-slot="{ open }" :options="dropdownOptions">
23 <Button
24 :disabled="props.disableAddCondition"
25 label="Add condition"
26 icon-left="lucide-plus"
27 :icon-right="open ? 'lucide-chevron-up' : 'lucide-chevron-down'"
28 />
29 </Dropdown>
30 </div>
31 </div>
32</template>
33
34<script setup lang="ts">
35import { Button, Dropdown } from "frappe-ui";
36import { computed, onMounted } from "vue";
37import CFCondition from "./CFCondition.vue";
38import { filterableFields } from "./filterableFields";
39
40const props = defineProps({
41 conditions: {
42 type: Array<any>,
43 required: true,
44 },
45 isChild: {
46 type: Boolean,
47 default: false,
48 },
49 level: {
50 type: Number,
51 default: 0,
52 },
53 disableAddCondition: {
54 type: Boolean,
55 default: false,
56 },
57});
58
59const getConjunction = () => {
60 let conjunction = "and";
61 props.conditions.forEach((condition) => {
62 if (typeof condition == "string") {
63 conjunction = condition;
64 }
65 });
66 return conjunction;
67};
68
69const turnIntoGroup = (condition) => {
70 props.conditions.splice(props.conditions.indexOf(condition), 1, [condition]);
71};
72
73const isGroupCondition = (condition) => {
74 return Array.isArray(condition);
75};
76
77const dropdownOptions = computed(() => {
78 const options = [
79 {
80 label: "Add condition",
81 onClick: () => {
82 const conjunction = getConjunction();
83 props.conditions.push(conjunction, ["", "", ""]);
84 },
85 },
86 ];
87 if (props.level < 3) {
88 options.push({
89 label: "Add condition group",
90 onClick: () => {
91 const conjunction = getConjunction();
92 props.conditions.push(conjunction, [[]]);
93 },
94 });
95 }
96 return options;
97});
98
99function removeCondition(condition) {
100 const conditionIndex = props.conditions.indexOf(condition);
101 if (conditionIndex == 0) {
102 props.conditions.splice(conditionIndex, 2);
103 } else {
104 props.conditions.splice(conditionIndex - 1, 2);
105 }
106}
107
108function unGroupConditions(condition) {
109 const conjunction = getConjunction();
110 const newConditions = condition.map((c) => {
111 if (typeof c == "string") {
112 return conjunction;
113 }
114 return c;
115 });
116
117 const index = props.conditions.indexOf(condition);
118 if (index !== -1) {
119 props.conditions.splice(index, 1, ...newConditions);
120 }
121}
122
123function toggleConjunction(conjunction) {
124 for (let i = 0; i < props.conditions.length; i++) {
125 if (typeof props.conditions[i] == "string") {
126 props.conditions[i] = conjunction == "and" ? "or" : "and";
127 }
128 }
129}
130
131onMounted(() => {
132 if (!filterableFields.fetched) {
133 filterableFields.submit();
134 }
135});
136</script>
137