fixed some bugs with dialog and viewing docx works again
This commit is contained in:
parent
ad0f7a7a01
commit
2968bcf3f8
|
|
@ -69,7 +69,7 @@ const maxWidthClass = computed(() => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Dialog v-model:open="open">
|
<Dialog v-model:open="open">
|
||||||
<DialogContent :class="maxWidthClass">
|
<DialogContent class="overflow-auto max-h-3/4" :class="maxWidthClass">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
|
|
|
||||||
|
|
@ -6,34 +6,40 @@ import {
|
||||||
DialogFooter,
|
DialogFooter,
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from '@/Components/ui/dialog';
|
} from "@/Components/ui/dialog";
|
||||||
import { Button } from '@/Components/ui/button';
|
import { Button } from "@/Components/ui/button";
|
||||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
|
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||||
import { faTrashCan, faTriangleExclamation } from '@fortawesome/free-solid-svg-icons';
|
import { faTrashCan, faTriangleExclamation } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from "vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
show: { type: Boolean, default: false },
|
show: { type: Boolean, default: false },
|
||||||
title: { type: String, default: 'Izbriši' },
|
title: { type: String, default: "Izbriši" },
|
||||||
message: { type: String, default: 'Ali ste prepričani, da želite izbrisati ta element?' },
|
message: {
|
||||||
confirmText: { type: String, default: 'Izbriši' },
|
type: String,
|
||||||
cancelText: { type: String, default: 'Prekliči' },
|
default: "Ali ste prepričani, da želite izbrisati ta element?",
|
||||||
|
},
|
||||||
|
confirmText: { type: String, default: "Izbriši" },
|
||||||
|
cancelText: { type: String, default: "Prekliči" },
|
||||||
processing: { type: Boolean, default: false },
|
processing: { type: Boolean, default: false },
|
||||||
itemName: { type: String, default: null }, // Optional name to show in confirmation
|
itemName: { type: String, default: null }, // Optional name to show in confirmation
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['update:show', 'close', 'confirm']);
|
const emit = defineEmits(["update:show", "close", "confirm"]);
|
||||||
|
|
||||||
const open = ref(props.show);
|
const open = ref(props.show);
|
||||||
|
|
||||||
watch(() => props.show, (newVal) => {
|
watch(
|
||||||
open.value = newVal;
|
() => props.show,
|
||||||
});
|
(newVal) => {
|
||||||
|
open.value = newVal;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
watch(open, (newVal) => {
|
watch(open, (newVal) => {
|
||||||
emit('update:show', newVal);
|
emit("update:show", newVal);
|
||||||
if (!newVal) {
|
if (!newVal) {
|
||||||
emit('close');
|
emit("close");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -42,7 +48,7 @@ const onClose = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const onConfirm = () => {
|
const onConfirm = () => {
|
||||||
emit('confirm');
|
emit("confirm");
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -59,8 +65,13 @@ const onConfirm = () => {
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
<div class="flex items-start gap-4 pt-4">
|
<div class="flex items-start gap-4 pt-4">
|
||||||
<div class="flex-shrink-0">
|
<div class="flex-shrink-0">
|
||||||
<div class="flex items-center justify-center h-12 w-12 rounded-full bg-red-100">
|
<div
|
||||||
<FontAwesomeIcon :icon="faTriangleExclamation" class="h-6 w-6 text-red-600" />
|
class="flex items-center justify-center h-12 w-12 rounded-full bg-red-100"
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon
|
||||||
|
:icon="faTriangleExclamation"
|
||||||
|
class="h-6 w-6 text-red-600"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1 space-y-2">
|
<div class="flex-1 space-y-2">
|
||||||
|
|
@ -70,9 +81,7 @@ const onConfirm = () => {
|
||||||
<p v-if="itemName" class="text-sm font-medium text-gray-900">
|
<p v-if="itemName" class="text-sm font-medium text-gray-900">
|
||||||
{{ itemName }}
|
{{ itemName }}
|
||||||
</p>
|
</p>
|
||||||
<p class="text-sm text-gray-500">
|
<p class="text-sm text-gray-500">Ta dejanje ni mogoče razveljaviti.</p>
|
||||||
Ta dejanje ni mogoče razveljaviti.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
|
|
@ -82,15 +91,10 @@ const onConfirm = () => {
|
||||||
<Button variant="outline" @click="onClose" :disabled="processing">
|
<Button variant="outline" @click="onClose" :disabled="processing">
|
||||||
{{ cancelText }}
|
{{ cancelText }}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button variant="destructive" @click="onConfirm" :disabled="processing">
|
||||||
variant="destructive"
|
|
||||||
@click="onConfirm"
|
|
||||||
:disabled="processing"
|
|
||||||
>
|
|
||||||
{{ confirmText }}
|
{{ confirmText }}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ const maxWidthClass = computed(() => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Dialog v-model:open="open">
|
<Dialog v-model:open="open">
|
||||||
<DialogContent :class="maxWidthClass">
|
<DialogContent class="overflow-auto max-h-3/4" :class="maxWidthClass">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ import {
|
||||||
} from "@/Components/ui/dialog";
|
} from "@/Components/ui/dialog";
|
||||||
import { Button } from "@/Components/ui/button";
|
import { Button } from "@/Components/ui/button";
|
||||||
import { Badge } from "../ui/badge";
|
import { Badge } from "../ui/badge";
|
||||||
|
import { Loader2 } from "lucide-vue-next";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
show: { type: Boolean, default: false },
|
show: { type: Boolean, default: false },
|
||||||
|
|
@ -21,6 +23,8 @@ const emit = defineEmits(["close"]);
|
||||||
|
|
||||||
const textContent = ref("");
|
const textContent = ref("");
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
const previewGenerating = ref(false);
|
||||||
|
const previewError = ref("");
|
||||||
|
|
||||||
const fileExtension = computed(() => {
|
const fileExtension = computed(() => {
|
||||||
if (props.filename) {
|
if (props.filename) {
|
||||||
|
|
@ -34,6 +38,9 @@ const viewerType = computed(() => {
|
||||||
const mime = props.mimeType.toLowerCase();
|
const mime = props.mimeType.toLowerCase();
|
||||||
|
|
||||||
if (ext === "pdf" || mime === "application/pdf") return "pdf";
|
if (ext === "pdf" || mime === "application/pdf") return "pdf";
|
||||||
|
// DOCX/DOC files are converted to PDF by backend - treat as PDF viewer
|
||||||
|
if (["doc", "docx"].includes(ext) || mime.includes("word") || mime.includes("msword"))
|
||||||
|
return "docx";
|
||||||
if (["jpg", "jpeg", "png", "gif", "webp"].includes(ext) || mime.startsWith("image/"))
|
if (["jpg", "jpeg", "png", "gif", "webp"].includes(ext) || mime.startsWith("image/"))
|
||||||
return "image";
|
return "image";
|
||||||
if (["txt", "csv", "xml"].includes(ext) || mime.startsWith("text/")) return "text";
|
if (["txt", "csv", "xml"].includes(ext) || mime.startsWith("text/")) return "text";
|
||||||
|
|
@ -45,8 +52,8 @@ const loadTextContent = async () => {
|
||||||
if (!props.src || viewerType.value !== "text") return;
|
if (!props.src || viewerType.value !== "text") return;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
const response = await fetch(props.src);
|
const response = await axios.get(props.src);
|
||||||
textContent.value = await response.text();
|
textContent.value = response.data;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
textContent.value = "Napaka pri nalaganju vsebine.";
|
textContent.value = "Napaka pri nalaganju vsebine.";
|
||||||
} finally {
|
} finally {
|
||||||
|
|
@ -54,12 +61,64 @@ const loadTextContent = async () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// For DOCX files, the backend converts to PDF. If the preview isn't ready yet (202 status),
|
||||||
|
// we poll until it's available.
|
||||||
|
const docxPreviewUrl = ref("");
|
||||||
|
const loadDocxPreview = async () => {
|
||||||
|
if (!props.src || viewerType.value !== "docx") return;
|
||||||
|
|
||||||
|
previewGenerating.value = true;
|
||||||
|
previewError.value = "";
|
||||||
|
docxPreviewUrl.value = "";
|
||||||
|
|
||||||
|
const maxRetries = 15;
|
||||||
|
const retryDelay = 2000; // 2 seconds between retries
|
||||||
|
|
||||||
|
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
||||||
|
try {
|
||||||
|
const response = await axios.head(props.src, { validateStatus: () => true });
|
||||||
|
|
||||||
|
if (response.status >= 200 && response.status < 300) {
|
||||||
|
// Preview is ready
|
||||||
|
docxPreviewUrl.value = props.src;
|
||||||
|
previewGenerating.value = false;
|
||||||
|
return;
|
||||||
|
} else if (response.status === 202) {
|
||||||
|
// Preview is being generated, wait and retry
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
||||||
|
} else {
|
||||||
|
// Other error
|
||||||
|
previewError.value = "Napaka pri nalaganju predogleda.";
|
||||||
|
previewGenerating.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
previewError.value = "Napaka pri nalaganju predogleda.";
|
||||||
|
previewGenerating.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Max retries reached
|
||||||
|
previewError.value = "Predogled ni na voljo. Prosimo poskusite znova kasneje.";
|
||||||
|
previewGenerating.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => [props.show, props.src],
|
() => [props.show, props.src],
|
||||||
([show]) => {
|
([show]) => {
|
||||||
if (show && viewerType.value === "text") {
|
if (show && viewerType.value === "text") {
|
||||||
loadTextContent();
|
loadTextContent();
|
||||||
}
|
}
|
||||||
|
if (show && viewerType.value === "docx") {
|
||||||
|
loadDocxPreview();
|
||||||
|
}
|
||||||
|
// Reset states when dialog closes
|
||||||
|
if (!show) {
|
||||||
|
previewGenerating.value = false;
|
||||||
|
previewError.value = "";
|
||||||
|
docxPreviewUrl.value = "";
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
|
@ -89,6 +148,35 @@ watch(
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- DOCX Viewer (converted to PDF by backend) -->
|
||||||
|
<template v-else-if="viewerType === 'docx'">
|
||||||
|
<!-- Loading/generating state -->
|
||||||
|
<div
|
||||||
|
v-if="previewGenerating"
|
||||||
|
class="flex flex-col items-center justify-center h-full gap-4"
|
||||||
|
>
|
||||||
|
<Loader2 class="h-8 w-8 animate-spin text-indigo-600" />
|
||||||
|
<span class="text-gray-500">Priprava predogleda dokumenta...</span>
|
||||||
|
</div>
|
||||||
|
<!-- Error state -->
|
||||||
|
<div
|
||||||
|
v-else-if="previewError"
|
||||||
|
class="flex flex-col items-center justify-center h-full gap-4 text-gray-500"
|
||||||
|
>
|
||||||
|
<span>{{ previewError }}</span>
|
||||||
|
<Button as="a" :href="props.src" target="_blank" variant="outline">
|
||||||
|
Prenesi datoteko
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<!-- Preview ready -->
|
||||||
|
<iframe
|
||||||
|
v-else-if="docxPreviewUrl"
|
||||||
|
:src="docxPreviewUrl"
|
||||||
|
class="w-full h-full rounded border"
|
||||||
|
type="application/pdf"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- Image Viewer -->
|
<!-- Image Viewer -->
|
||||||
<template v-else-if="viewerType === 'image' && props.src">
|
<template v-else-if="viewerType === 'image' && props.src">
|
||||||
<img
|
<img
|
||||||
|
|
|
||||||
|
|
@ -120,9 +120,10 @@ const store = async () => {
|
||||||
return `${y}-${m}-${day}`;
|
return `${y}-${m}-${day}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const contractUuids = Array.isArray(form.contract_uuids) && form.contract_uuids.length > 0
|
const contractUuids =
|
||||||
? form.contract_uuids
|
Array.isArray(form.contract_uuids) && form.contract_uuids.length > 0
|
||||||
: null;
|
? form.contract_uuids
|
||||||
|
: null;
|
||||||
|
|
||||||
const isMultipleContracts = contractUuids && contractUuids.length > 1;
|
const isMultipleContracts = contractUuids && contractUuids.length > 1;
|
||||||
|
|
||||||
|
|
@ -175,9 +176,9 @@ const autoMailRequiresContract = computed(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const contractItems = computed(() => {
|
const contractItems = computed(() => {
|
||||||
return pageContracts.value.map(c => ({
|
return pageContracts.value.map((c) => ({
|
||||||
value: c.uuid,
|
value: c.uuid,
|
||||||
label: `${c.reference}${c.name ? ` - ${c.name}` : ''}`
|
label: `${c.reference}${c.name ? ` - ${c.name}` : ""}`,
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -188,7 +189,10 @@ const autoMailDisabled = computed(() => {
|
||||||
if (form.contract_uuids && form.contract_uuids.length > 1) return true;
|
if (form.contract_uuids && form.contract_uuids.length > 1) return true;
|
||||||
|
|
||||||
// Disable if template requires contract but none selected
|
// Disable if template requires contract but none selected
|
||||||
if (autoMailRequiresContract.value && (!form.contract_uuids || form.contract_uuids.length === 0)) {
|
if (
|
||||||
|
autoMailRequiresContract.value &&
|
||||||
|
(!form.contract_uuids || form.contract_uuids.length === 0)
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,7 +206,10 @@ const autoMailDisabledHint = computed(() => {
|
||||||
return "Avtomatska e-pošta ni na voljo pri več pogodbah.";
|
return "Avtomatska e-pošta ni na voljo pri več pogodbah.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autoMailRequiresContract.value && (!form.contract_uuids || form.contract_uuids.length === 0)) {
|
if (
|
||||||
|
autoMailRequiresContract.value &&
|
||||||
|
(!form.contract_uuids || form.contract_uuids.length === 0)
|
||||||
|
) {
|
||||||
return "Ta e-poštna predloga zahteva pogodbo. Najprej izberite pogodbo.";
|
return "Ta e-poštna predloga zahteva pogodbo. Najprej izberite pogodbo.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -333,133 +340,148 @@ watch(
|
||||||
@confirm="store"
|
@confirm="store"
|
||||||
>
|
>
|
||||||
<form @submit.prevent="store">
|
<form @submit.prevent="store">
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<Label>Akcija</Label>
|
<Label>Akcija</Label>
|
||||||
<Select v-model="form.action_id" :disabled="!actions || !actions.length">
|
<Select v-model="form.action_id" :disabled="!actions || !actions.length">
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue placeholder="Izberi akcijo" />
|
<SelectValue placeholder="Izberi akcijo" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem v-for="a in actions" :key="a.id" :value="a.id">
|
<SelectItem v-for="a in actions" :key="a.id" :value="a.id">
|
||||||
{{ a.name }}
|
{{ a.name }}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<Label>Odločitev</Label>
|
<Label>Odločitev</Label>
|
||||||
<Select v-model="form.decision_id" :disabled="!decisions || !decisions.length">
|
<Select v-model="form.decision_id" :disabled="!decisions || !decisions.length">
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue placeholder="Izberi odločitev" />
|
<SelectValue placeholder="Izberi odločitev" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem v-for="d in decisions" :key="d.id" :value="d.id">
|
<SelectItem v-for="d in decisions" :key="d.id" :value="d.id">
|
||||||
{{ d.name }}
|
{{ d.name }}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<Label>Pogodbe</Label>
|
<Label>Pogodbe</Label>
|
||||||
<AppMultiSelect
|
<AppMultiSelect
|
||||||
v-model="form.contract_uuids"
|
v-model="form.contract_uuids"
|
||||||
:items="contractItems"
|
:items="contractItems"
|
||||||
placeholder="Izberi pogodbe (neobvezno)"
|
placeholder="Izberi pogodbe (neobvezno)"
|
||||||
search-placeholder="Išči pogodbo..."
|
search-placeholder="Išči pogodbo..."
|
||||||
empty-text="Ni pogodb."
|
empty-text="Ni pogodb."
|
||||||
:clearable="true"
|
:clearable="true"
|
||||||
:show-selected-chips="true"
|
:show-selected-chips="true"
|
||||||
/>
|
/>
|
||||||
<p v-if="form.contract_uuids && form.contract_uuids.length > 1" class="text-xs text-muted-foreground">
|
<p
|
||||||
Bo ustvarjenih {{ form.contract_uuids.length }} aktivnosti (ena za vsako pogodbo).
|
v-if="form.contract_uuids && form.contract_uuids.length > 1"
|
||||||
</p>
|
class="text-xs text-muted-foreground"
|
||||||
</div>
|
>
|
||||||
|
Bo ustvarjenih {{ form.contract_uuids.length }} aktivnosti (ena za vsako
|
||||||
|
pogodbo).
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<Label for="activityNote">Opomba</Label>
|
<Label for="activityNote">Opomba</Label>
|
||||||
<Textarea
|
<Textarea
|
||||||
id="activityNote"
|
id="activityNote"
|
||||||
v-model="form.note"
|
v-model="form.note"
|
||||||
class="block w-full"
|
class="block w-full max-h-72"
|
||||||
placeholder="Opomba"
|
placeholder="Opomba"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<Label for="activityDueDate">Datum zapadlosti</Label>
|
<Label for="activityDueDate">Datum zapadlosti</Label>
|
||||||
<DatePicker
|
<DatePicker
|
||||||
id="activityDueDate"
|
id="activityDueDate"
|
||||||
v-model="form.due_date"
|
v-model="form.due_date"
|
||||||
format="dd.MM.yyyy"
|
format="dd.MM.yyyy"
|
||||||
:error="form.errors.due_date"
|
:error="form.errors.due_date"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<Label for="activityAmount">Znesek</Label>
|
<Label for="activityAmount">Znesek</Label>
|
||||||
<CurrencyInput
|
<CurrencyInput
|
||||||
id="activityAmount"
|
id="activityAmount"
|
||||||
v-model="form.amount"
|
v-model="form.amount"
|
||||||
:precision="{ min: 0, max: 4 }"
|
:precision="{ min: 0, max: 4 }"
|
||||||
placeholder="0,00"
|
placeholder="0,00"
|
||||||
class="w-full"
|
class="w-full"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="showSendAutoMail()" class="space-y-2">
|
<div v-if="showSendAutoMail()" class="space-y-2">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<Switch
|
<Switch v-model="form.send_auto_mail" :disabled="autoMailDisabled" />
|
||||||
v-model="form.send_auto_mail"
|
<Label class="cursor-pointer">Send auto email</Label>
|
||||||
:disabled="autoMailDisabled"
|
|
||||||
/>
|
|
||||||
<Label class="cursor-pointer">Send auto email</Label>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<p v-if="autoMailDisabled" class="text-xs text-amber-600">
|
</div>
|
||||||
{{ autoMailDisabledHint }}
|
<p v-if="autoMailDisabled" class="text-xs text-amber-600">
|
||||||
</p>
|
{{ autoMailDisabledHint }}
|
||||||
|
</p>
|
||||||
|
|
||||||
<div v-if="templateAllowsAttachments && form.contract_uuids && form.contract_uuids.length === 1" class="mt-3">
|
<div
|
||||||
<label class="inline-flex items-center gap-2">
|
v-if="
|
||||||
<Switch v-model="form.attach_documents" />
|
templateAllowsAttachments &&
|
||||||
<span class="text-sm">Dodaj priponke iz izbrane pogodbe</span>
|
form.contract_uuids &&
|
||||||
</label>
|
form.contract_uuids.length === 1
|
||||||
<div
|
"
|
||||||
v-if="form.attach_documents"
|
class="mt-3"
|
||||||
class="mt-2 border rounded p-2 max-h-48 overflow-auto"
|
>
|
||||||
>
|
<label class="inline-flex items-center gap-2">
|
||||||
<div class="text-xs text-gray-600 mb-2">
|
<Switch v-model="form.attach_documents" />
|
||||||
Izberite dokumente, ki bodo poslani kot priponke:
|
<span class="text-sm">Dodaj priponke iz izbrane pogodbe</span>
|
||||||
</div>
|
</label>
|
||||||
<div class="space-y-1">
|
<div
|
||||||
<template v-for="c in pageContracts" :key="c.uuid || c.id">
|
v-if="form.attach_documents"
|
||||||
<div v-if="c.uuid === form.contract_uuids[0]">
|
class="mt-2 border rounded p-2 max-h-48 overflow-auto"
|
||||||
<div class="font-medium text-sm text-gray-700 mb-1">
|
>
|
||||||
Pogodba {{ c.reference }}
|
<div class="text-xs text-gray-600 mb-2">
|
||||||
</div>
|
Izberite dokumente, ki bodo poslani kot priponke:
|
||||||
<div class="space-y-1">
|
</div>
|
||||||
<div
|
<div class="space-y-1">
|
||||||
v-for="doc in availableContractDocs"
|
<template v-for="c in pageContracts" :key="c.uuid || c.id">
|
||||||
:key="doc.uuid || doc.id"
|
<div v-if="c.uuid === form.contract_uuids[0]">
|
||||||
class="flex items-center gap-2 text-sm"
|
<div class="font-medium text-sm text-gray-700 mb-1">
|
||||||
>
|
Pogodba {{ c.reference }}
|
||||||
<Switch
|
</div>
|
||||||
:model-value="form.attachment_document_ids.includes(doc.id)"
|
<div class="space-y-1">
|
||||||
@update:model-value="(checked) => {
|
<div
|
||||||
|
v-for="doc in availableContractDocs"
|
||||||
|
:key="doc.uuid || doc.id"
|
||||||
|
class="flex items-center max-w-sm gap-2 text-sm"
|
||||||
|
>
|
||||||
|
<Switch
|
||||||
|
:model-value="form.attachment_document_ids.includes(doc.id)"
|
||||||
|
@update:model-value="
|
||||||
|
(checked) => {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
if (!form.attachment_document_ids.includes(doc.id)) {
|
if (!form.attachment_document_ids.includes(doc.id)) {
|
||||||
form.attachment_document_ids.push(doc.id);
|
form.attachment_document_ids.push(doc.id);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
form.attachment_document_ids = form.attachment_document_ids.filter(id => id !== doc.id);
|
form.attachment_document_ids = form.attachment_document_ids.filter(
|
||||||
|
(id) => id !== doc.id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}"
|
}
|
||||||
/>
|
"
|
||||||
<span>{{ doc.original_name || doc.name }}</span>
|
/>
|
||||||
|
<div class="wrap-anywhere">
|
||||||
|
<p>
|
||||||
|
{{ doc.original_name || doc.name }}
|
||||||
|
</p>
|
||||||
<span class="text-xs text-gray-400"
|
<span class="text-xs text-gray-400"
|
||||||
>({{ doc.extension?.toUpperCase() || "" }},
|
>({{ doc.extension?.toUpperCase() || "" }},
|
||||||
{{ (doc.size / 1024 / 1024).toFixed(2) }} MB)</span
|
{{ (doc.size / 1024 / 1024).toFixed(2) }} MB)</span
|
||||||
|
|
@ -467,22 +489,23 @@ watch(
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
|
||||||
<div
|
|
||||||
v-if="availableContractDocs.length === 0"
|
|
||||||
class="text-sm text-gray-500"
|
|
||||||
>
|
|
||||||
Ni dokumentov, povezanih s to pogodbo.
|
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
|
<div
|
||||||
|
v-if="availableContractDocs.length === 0"
|
||||||
|
class="text-sm text-gray-500"
|
||||||
|
>
|
||||||
|
Ni dokumentov, povezanih s to pogodbo.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ActionMessage :on="form.recentlySuccessful" class="text-sm text-green-600">
|
|
||||||
Shranjuje.
|
|
||||||
</ActionMessage>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
|
||||||
</CreateDialog>
|
<ActionMessage :on="form.recentlySuccessful" class="text-sm text-green-600">
|
||||||
|
Shranjuje.
|
||||||
|
</ActionMessage>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</CreateDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user