Added condition options for events to trigger decisions
This commit is contained in:
@@ -15,6 +15,8 @@ const props = defineProps({
|
||||
email_templates: { type: Array, default: () => [] },
|
||||
events: { type: Array, default: () => [] },
|
||||
archive_settings: { type: Array, default: () => [] },
|
||||
condition_fields: { type: Array, default: () => [] },
|
||||
condition_operators: { type: Object, default: () => ({}) },
|
||||
});
|
||||
|
||||
const activeTab = ref("actions");
|
||||
@@ -57,6 +59,8 @@ const activeTab = ref("actions");
|
||||
:available-events="events"
|
||||
:segments="segments"
|
||||
:archive-settings="archive_settings"
|
||||
:condition-fields="condition_fields"
|
||||
:condition-operators="condition_operators"
|
||||
/>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
@@ -33,7 +33,16 @@ import DataTableNew2 from "@/Components/DataTable/DataTableNew2.vue";
|
||||
import InlineColorPicker from "@/Components/InlineColorPicker.vue";
|
||||
import Dropdown from "@/Components/Dropdown.vue";
|
||||
import AppPopover from "@/Components/app/ui/AppPopover.vue";
|
||||
import { FilterIcon, MoreHorizontal, Pencil, Trash } from "lucide-vue-next";
|
||||
import {
|
||||
FilterIcon,
|
||||
MoreHorizontal,
|
||||
Pencil,
|
||||
Plus,
|
||||
Trash,
|
||||
Trash2,
|
||||
X,
|
||||
} from "lucide-vue-next";
|
||||
import { Switch } from "@/Components/ui/switch";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@@ -48,6 +57,8 @@ const props = defineProps({
|
||||
availableEvents: { type: Array, default: () => [] },
|
||||
segments: { type: Array, default: () => [] },
|
||||
archiveSettings: { type: Array, default: () => [] },
|
||||
conditionFields: { type: Array, default: () => [] },
|
||||
conditionOperators: { type: Object, default: () => ({}) },
|
||||
});
|
||||
|
||||
const drawerEdit = ref(false);
|
||||
@@ -223,6 +234,39 @@ function defaultEventPayload() {
|
||||
};
|
||||
}
|
||||
|
||||
function operatorsForField(fieldKey) {
|
||||
const field = (props.conditionFields || []).find((f) => f.key === fieldKey);
|
||||
if (!field) {
|
||||
return props.conditionOperators?.numeric ?? [];
|
||||
}
|
||||
return props.conditionOperators?.[field.type] ?? [];
|
||||
}
|
||||
|
||||
function addCondition(ev) {
|
||||
if (!Array.isArray(ev.config.conditions)) {
|
||||
ev.config.conditions = [];
|
||||
}
|
||||
const firstField = (props.conditionFields || [])[0];
|
||||
const firstOperator = firstField
|
||||
? operatorsForField(firstField.key)[0]?.key ?? "="
|
||||
: "=";
|
||||
ev.config.conditions.push({
|
||||
field: firstField?.key ?? "",
|
||||
operator: firstOperator,
|
||||
value: "",
|
||||
});
|
||||
}
|
||||
|
||||
function removeCondition(ev, idx) {
|
||||
ev.config.conditions.splice(idx, 1);
|
||||
}
|
||||
|
||||
function onConditionFieldChange(condition) {
|
||||
const ops = operatorsForField(condition.field);
|
||||
condition.operator = ops[0]?.key ?? "=";
|
||||
condition.value = "";
|
||||
}
|
||||
|
||||
function tryAdoptRaw(ev) {
|
||||
try {
|
||||
const obj = JSON.parse(ev.__rawJson || "{}");
|
||||
@@ -532,7 +576,7 @@ const destroyDecision = () => {
|
||||
<template #cell-auto_mail="{ row }">
|
||||
<div class="flex flex-col text-sm">
|
||||
<span :class="row.auto_mail ? 'text-green-700' : 'text-gray-500'">{{
|
||||
row.auto_mail ? "Enabled" : "Disabled"
|
||||
row.auto_mail ? "Vključeno" : "Izključeno"
|
||||
}}</span>
|
||||
<span v-if="row.auto_mail && row.email_template_id" class="text-gray-600">
|
||||
Template:
|
||||
@@ -568,7 +612,7 @@ const destroyDecision = () => {
|
||||
<Dialog v-model:open="drawerEdit">
|
||||
<DialogContent class="max-w-2xl max-h-[90vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Spremeni odločitev</DialogTitle>
|
||||
<DialogTitle>Uredi odločitev</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
@@ -659,9 +703,16 @@ const destroyDecision = () => {
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 self-end">
|
||||
<label class="flex items-center gap-2 text-sm">
|
||||
<Checkbox v-model="ev.active" />
|
||||
Aktivno
|
||||
<label
|
||||
class="flex items-center gap-2 text-sm cursor-pointer select-none"
|
||||
>
|
||||
<Switch v-model="ev.active" />
|
||||
<span
|
||||
:class="
|
||||
ev.active ? 'text-green-700 font-medium' : 'text-muted-foreground'
|
||||
"
|
||||
>{{ ev.active ? "Aktivno" : "Neaktivno" }}</span
|
||||
>
|
||||
</label>
|
||||
<Button
|
||||
variant="ghost"
|
||||
@@ -707,7 +758,7 @@ const destroyDecision = () => {
|
||||
<template v-else-if="eventKey(ev) === 'archive_contract'">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
<div>
|
||||
<InputLabel :for="`as-${idx}`" value="Archive setting" />
|
||||
<InputLabel :for="`as-${idx}`" value="Nastavitev arhiva" />
|
||||
<Select v-model="ev.config.archive_setting_id">
|
||||
<SelectTrigger :id="`as-${idx}`" class="w-full">
|
||||
<SelectValue placeholder="— Izberi nastavitev —" />
|
||||
@@ -731,9 +782,14 @@ const destroyDecision = () => {
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-end">
|
||||
<label class="flex items-center gap-2 text-sm mt-6">
|
||||
<Checkbox v-model:checked="ev.config.reactivate" />
|
||||
Reactivate namesto arhiva
|
||||
<label
|
||||
class="flex items-center gap-2 text-sm mt-6 cursor-pointer select-none"
|
||||
>
|
||||
<Switch
|
||||
:model-value="ev.config.reactivate"
|
||||
v-model:checked="ev.config.reactivate"
|
||||
/>
|
||||
Reaktiviraj namesto arhiviranja
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -749,7 +805,7 @@ const destroyDecision = () => {
|
||||
</p>
|
||||
</template>
|
||||
<template v-else>
|
||||
<!-- Fallback advanced editor for unknown event keys -->
|
||||
<!-- Rezervni urejevalnik za neznane ključe dogodkov -->
|
||||
<InputLabel :for="`cfg-${idx}`" value="Napredna nastavitev (JSON)" />
|
||||
<textarea
|
||||
:id="`cfg-${idx}`"
|
||||
@@ -765,6 +821,104 @@ const destroyDecision = () => {
|
||||
></textarea>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- Conditions -->
|
||||
<div v-if="conditionFields.length" class="mt-3 border-t pt-3">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span
|
||||
class="text-xs font-semibold text-muted-foreground uppercase tracking-wide"
|
||||
>Pogoji za izvajanje</span
|
||||
>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
class="h-7 gap-1 text-xs"
|
||||
@click="addCondition(ev)"
|
||||
>
|
||||
<Plus class="w-3 h-3" />
|
||||
Dodaj pogoj
|
||||
</Button>
|
||||
</div>
|
||||
<p
|
||||
v-if="!ev.config.conditions?.length"
|
||||
class="text-xs text-muted-foreground italic"
|
||||
>
|
||||
Brez pogojev — dogodek se vedno izvede.
|
||||
</p>
|
||||
<div
|
||||
v-for="(cond, cidx) in ev.config.conditions"
|
||||
:key="cidx"
|
||||
class="flex items-center gap-2 mt-1"
|
||||
>
|
||||
<Select
|
||||
v-model="cond.field"
|
||||
@update:model-value="onConditionFieldChange(cond)"
|
||||
class="w-48"
|
||||
>
|
||||
<SelectTrigger class="h-8 text-xs">
|
||||
<SelectValue placeholder="Polje" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem
|
||||
v-for="f in conditionFields"
|
||||
:key="f.key"
|
||||
:value="f.key"
|
||||
class="text-xs"
|
||||
>
|
||||
{{ f.label }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select v-model="cond.operator" class="w-36">
|
||||
<SelectTrigger class="h-8 text-xs">
|
||||
<SelectValue placeholder="Operator" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem
|
||||
v-for="op in operatorsForField(cond.field)"
|
||||
:key="op.key"
|
||||
:value="op.key"
|
||||
class="text-xs"
|
||||
>
|
||||
{{ op.label }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<template
|
||||
v-if="
|
||||
conditionFields.find((f) => f.key === cond.field)?.type ===
|
||||
'boolean'
|
||||
"
|
||||
>
|
||||
<Select v-model="cond.value" class="w-24">
|
||||
<SelectTrigger class="h-8 text-xs">
|
||||
<SelectValue placeholder="Vrednost" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="1" class="text-xs">Da</SelectItem>
|
||||
<SelectItem value="0" class="text-xs">Ne</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</template>
|
||||
<template v-else>
|
||||
<Input
|
||||
v-model="cond.value"
|
||||
class="h-8 text-xs w-28"
|
||||
placeholder="Vrednost"
|
||||
/>
|
||||
</template>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
class="h-7 w-7 text-red-500 hover:text-red-700"
|
||||
@click="removeCondition(ev, cidx)"
|
||||
>
|
||||
<X class="w-3 h-3" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
@@ -782,7 +936,7 @@ const destroyDecision = () => {
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" @click="closeEditDrawer">Cancel</Button>
|
||||
<Button variant="outline" @click="closeEditDrawer">Prekliči</Button>
|
||||
<Button @click="update" :disabled="form.processing || !eventsValidEdit"
|
||||
>Shrani</Button
|
||||
>
|
||||
@@ -891,9 +1045,16 @@ const destroyDecision = () => {
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 self-end">
|
||||
<label class="flex items-center gap-2 text-sm">
|
||||
<Checkbox v-model:checked="ev.active" />
|
||||
Aktivno
|
||||
<label
|
||||
class="flex items-center gap-2 text-sm cursor-pointer select-none"
|
||||
>
|
||||
<Switch v-model="ev.active" />
|
||||
<span
|
||||
:class="
|
||||
ev.active ? 'text-green-700 font-medium' : 'text-muted-foreground'
|
||||
"
|
||||
>{{ ev.active ? "Aktivno" : "Neaktivno" }}</span
|
||||
>
|
||||
</label>
|
||||
<Button
|
||||
variant="ghost"
|
||||
@@ -939,7 +1100,7 @@ const destroyDecision = () => {
|
||||
<template v-else-if="eventKey(ev) === 'archive_contract'">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
<div>
|
||||
<InputLabel :for="`cas-${idx}`" value="Archive setting" />
|
||||
<InputLabel :for="`cas-${idx}`" value="Nastavitev arhiva" />
|
||||
<Select v-model="ev.config.archive_setting_id">
|
||||
<SelectTrigger :id="`cas-${idx}`" class="w-full">
|
||||
<SelectValue placeholder="— Izberi nastavitev —" />
|
||||
@@ -965,9 +1126,14 @@ const destroyDecision = () => {
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-end">
|
||||
<label class="flex items-center gap-2 text-sm mt-6">
|
||||
<Checkbox v-model:checked="ev.config.reactivate" />
|
||||
Reactivate namesto arhiva
|
||||
<label
|
||||
class="flex items-center gap-2 text-sm mt-6 cursor-pointer select-none"
|
||||
>
|
||||
<Switch
|
||||
:model-value="ev.config.reactivate"
|
||||
v-model:checked="ev.config.reactivate"
|
||||
/>
|
||||
Reaktiviraj namesto arhiviranja
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -998,6 +1164,104 @@ const destroyDecision = () => {
|
||||
></textarea>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- Conditions -->
|
||||
<div v-if="conditionFields.length" class="mt-3 border-t pt-3">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<span
|
||||
class="text-xs font-semibold text-muted-foreground uppercase tracking-wide"
|
||||
>Pogoji za izvajanje</span
|
||||
>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
class="h-7 gap-1 text-xs"
|
||||
@click="addCondition(ev)"
|
||||
>
|
||||
<Plus class="w-3 h-3" />
|
||||
Dodaj pogoj
|
||||
</Button>
|
||||
</div>
|
||||
<p
|
||||
v-if="!ev.config.conditions?.length"
|
||||
class="text-xs text-muted-foreground italic"
|
||||
>
|
||||
Brez pogojev — dogodek se vedno izvede.
|
||||
</p>
|
||||
<div
|
||||
v-for="(cond, cidx) in ev.config.conditions"
|
||||
:key="cidx"
|
||||
class="flex items-center gap-2 mt-1"
|
||||
>
|
||||
<Select
|
||||
v-model="cond.field"
|
||||
@update:model-value="onConditionFieldChange(cond)"
|
||||
class="w-48"
|
||||
>
|
||||
<SelectTrigger class="h-8 text-xs">
|
||||
<SelectValue placeholder="Polje" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem
|
||||
v-for="f in conditionFields"
|
||||
:key="f.key"
|
||||
:value="f.key"
|
||||
class="text-xs"
|
||||
>
|
||||
{{ f.label }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select v-model="cond.operator" class="w-36">
|
||||
<SelectTrigger class="h-8 text-xs">
|
||||
<SelectValue placeholder="Operator" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem
|
||||
v-for="op in operatorsForField(cond.field)"
|
||||
:key="op.key"
|
||||
:value="op.key"
|
||||
class="text-xs"
|
||||
>
|
||||
{{ op.label }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<template
|
||||
v-if="
|
||||
conditionFields.find((f) => f.key === cond.field)?.type ===
|
||||
'boolean'
|
||||
"
|
||||
>
|
||||
<Select v-model="cond.value" class="w-24">
|
||||
<SelectTrigger class="h-8 text-xs">
|
||||
<SelectValue placeholder="Vrednost" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="1" class="text-xs">Da</SelectItem>
|
||||
<SelectItem value="0" class="text-xs">Ne</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</template>
|
||||
<template v-else>
|
||||
<Input
|
||||
v-model="cond.value"
|
||||
class="h-8 text-xs w-28"
|
||||
placeholder="Vrednost"
|
||||
/>
|
||||
</template>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
class="h-7 w-7 text-red-500 hover:text-red-700"
|
||||
@click="removeCondition(ev, cidx)"
|
||||
>
|
||||
<X class="w-3 h-3" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
@@ -1015,7 +1279,7 @@ const destroyDecision = () => {
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" @click="closeCreateDrawer">Cancel</Button>
|
||||
<Button variant="outline" @click="closeCreateDrawer">Prekliči</Button>
|
||||
<Button @click="store" :disabled="createForm.processing || !eventsValidCreate"
|
||||
>Dodaj</Button
|
||||
>
|
||||
@@ -1026,15 +1290,15 @@ const destroyDecision = () => {
|
||||
<AlertDialog v-model:open="showDelete">
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Delete decision</AlertDialogTitle>
|
||||
<AlertDialogTitle>Zbriši odločitev</AlertDialogTitle>
|
||||
</AlertDialogHeader>
|
||||
<div class="text-sm text-muted-foreground">
|
||||
Are you sure you want to delete decision "{{ toDelete?.name }}"? This cannot be
|
||||
undone.
|
||||
Ali ste prepričani, da želite zbrisati odločitev "{{ toDelete?.name }}"? Tega
|
||||
dejanja ni mogoče razveljaviti.
|
||||
</div>
|
||||
<AlertDialogFooter>
|
||||
<Button variant="outline" @click="cancelDelete">Cancel</Button>
|
||||
<Button variant="destructive" @click="destroyDecision">Delete</Button>
|
||||
<Button variant="outline" @click="cancelDelete">Prekliči</Button>
|
||||
<Button variant="destructive" @click="destroyDecision">Zbriši</Button>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
|
||||
Reference in New Issue
Block a user