Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc9720a67a |
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "app-ts",
|
"name": "app-ts",
|
||||||
"version": "1.3.3",
|
"version": "1.3.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "app-ts",
|
"name": "app-ts",
|
||||||
"version": "1.3.3",
|
"version": "1.3.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dnd-kit/core": "^6.3.1",
|
"@dnd-kit/core": "^6.3.1",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "app-ts",
|
"name": "app-ts",
|
||||||
"version": "1.3.3",
|
"version": "1.3.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "dist/server.js",
|
"main": "dist/server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -975,21 +975,18 @@ export default function InvoiceDetail() {
|
|||||||
|
|
||||||
// ─── Edit mode: PDF export ───
|
// ─── Edit mode: PDF export ───
|
||||||
const handleViewPdf = async (_lang = "cs") => {
|
const handleViewPdf = async (_lang = "cs") => {
|
||||||
const newWindow = window.open("", "_blank");
|
|
||||||
setPdfLoading(true);
|
setPdfLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await apiFetch(`${API_BASE}/invoices/${id}/file`);
|
const response = await apiFetch(`${API_BASE}/invoices/${id}/file`);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
newWindow?.close();
|
|
||||||
alert.error("PDF soubor nenalezen — uložte fakturu pro vygenerování");
|
alert.error("PDF soubor nenalezen — uložte fakturu pro vygenerování");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const blob = await response.blob();
|
const blob = await response.blob();
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
if (newWindow) newWindow.location.href = url;
|
window.open(url, "_blank");
|
||||||
setTimeout(() => URL.revokeObjectURL(url), 60000);
|
setTimeout(() => URL.revokeObjectURL(url), 60000);
|
||||||
} catch {
|
} catch {
|
||||||
newWindow?.close();
|
|
||||||
alert.error("Chyba připojení");
|
alert.error("Chyba připojení");
|
||||||
} finally {
|
} finally {
|
||||||
setPdfLoading(false);
|
setPdfLoading(false);
|
||||||
|
|||||||
@@ -356,7 +356,7 @@ export default function OfferDetail() {
|
|||||||
setForm((prev) => ({
|
setForm((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
currency:
|
currency:
|
||||||
prev.currency === "CZK"
|
prev.currency === "EUR"
|
||||||
? companySettings.default_currency || "CZK"
|
? companySettings.default_currency || "CZK"
|
||||||
: prev.currency,
|
: prev.currency,
|
||||||
vat_rate:
|
vat_rate:
|
||||||
@@ -768,25 +768,19 @@ export default function OfferDetail() {
|
|||||||
|
|
||||||
const handlePdf = async () => {
|
const handlePdf = async () => {
|
||||||
if (!isEdit || pdfLoading) return;
|
if (!isEdit || pdfLoading) return;
|
||||||
const newWindow = window.open("", "_blank");
|
|
||||||
setPdfLoading(true);
|
setPdfLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await apiFetch(`${API_BASE}/offers/${id}/file`);
|
const response = await apiFetch(`${API_BASE}/offers/${id}/file`);
|
||||||
if (response.status === 401) {
|
if (response.status === 401) return;
|
||||||
newWindow?.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
newWindow?.close();
|
|
||||||
alert.error("PDF soubor nenalezen — uložte nabídku pro vygenerování");
|
alert.error("PDF soubor nenalezen — uložte nabídku pro vygenerování");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const blob = await response.blob();
|
const blob = await response.blob();
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
if (newWindow) newWindow.location.href = url;
|
window.open(url, "_blank");
|
||||||
setTimeout(() => URL.revokeObjectURL(url), 60000);
|
setTimeout(() => URL.revokeObjectURL(url), 60000);
|
||||||
} catch {
|
} catch {
|
||||||
newWindow?.close();
|
|
||||||
alert.error("Chyba při generování PDF");
|
alert.error("Chyba při generování PDF");
|
||||||
} finally {
|
} finally {
|
||||||
setPdfLoading(false);
|
setPdfLoading(false);
|
||||||
|
|||||||
@@ -221,28 +221,26 @@ export default function Offers() {
|
|||||||
|
|
||||||
const handlePdf = async (quotation: Quotation) => {
|
const handlePdf = async (quotation: Quotation) => {
|
||||||
if (pdfLoading) return;
|
if (pdfLoading) return;
|
||||||
const newWindow = window.open("", "_blank");
|
|
||||||
setPdfLoading(quotation.id);
|
setPdfLoading(quotation.id);
|
||||||
try {
|
try {
|
||||||
const response = await apiFetch(
|
const response = await apiFetch(`${API_BASE}/offers-pdf/${quotation.id}`);
|
||||||
`${API_BASE}/offers/${quotation.id}/file`,
|
if (response.status === 401) return;
|
||||||
);
|
|
||||||
if (response.status === 401) {
|
|
||||||
newWindow?.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
newWindow?.close();
|
alert.error("Nepodařilo se vygenerovat PDF");
|
||||||
alert.error("PDF soubor nenalezen — otevřete nabídku a uložte ji");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const blob = await response.blob();
|
const html = await response.text();
|
||||||
const url = URL.createObjectURL(blob);
|
const w = window.open("", "_blank");
|
||||||
if (newWindow) newWindow.location.href = url;
|
if (w) {
|
||||||
setTimeout(() => URL.revokeObjectURL(url), 60000);
|
w.document.open();
|
||||||
|
w.document.write(html);
|
||||||
|
w.document.close();
|
||||||
|
w.onload = () => w.print();
|
||||||
|
} else {
|
||||||
|
alert.error("Prohlížeč zablokoval vyskakovací okno");
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
newWindow?.close();
|
alert.error("Chyba při generování PDF");
|
||||||
alert.error("Chyba připojení");
|
|
||||||
} finally {
|
} finally {
|
||||||
setPdfLoading(null);
|
setPdfLoading(null);
|
||||||
}
|
}
|
||||||
@@ -755,7 +753,7 @@ export default function Offers() {
|
|||||||
<button
|
<button
|
||||||
onClick={() => handlePdf(q)}
|
onClick={() => handlePdf(q)}
|
||||||
className="admin-btn-icon"
|
className="admin-btn-icon"
|
||||||
title="Zobrazit nabídku"
|
title="PDF"
|
||||||
disabled={pdfLoading === q.id}
|
disabled={pdfLoading === q.id}
|
||||||
>
|
>
|
||||||
{pdfLoading === q.id ? (
|
{pdfLoading === q.id ? (
|
||||||
|
|||||||
@@ -503,22 +503,19 @@ export default function ReceivedInvoices({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const openFile = async (inv: ReceivedInvoice) => {
|
const openFile = async (inv: ReceivedInvoice) => {
|
||||||
const newWindow = window.open("", "_blank");
|
|
||||||
try {
|
try {
|
||||||
const response = await apiFetch(
|
const response = await apiFetch(
|
||||||
`${API_BASE}/received-invoices/${inv.id}/file`,
|
`${API_BASE}/received-invoices/${inv.id}/file`,
|
||||||
);
|
);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
newWindow?.close();
|
|
||||||
alert.error("Nepodařilo se načíst soubor");
|
alert.error("Nepodařilo se načíst soubor");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const blob = await response.blob();
|
const blob = await response.blob();
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
if (newWindow) newWindow.location.href = url;
|
window.open(url, "_blank");
|
||||||
setTimeout(() => URL.revokeObjectURL(url), 60000);
|
setTimeout(() => URL.revokeObjectURL(url), 60000);
|
||||||
} catch {
|
} catch {
|
||||||
newWindow?.close();
|
|
||||||
alert.error("Chyba připojení");
|
alert.error("Chyba připojení");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ export default async function companySettingsRoutes(
|
|||||||
const settings = await prisma.company_settings.findFirst({
|
const settings = await prisma.company_settings.findFirst({
|
||||||
select: { [column]: true },
|
select: { [column]: true },
|
||||||
});
|
});
|
||||||
const buf = settings?.[column] as unknown as Buffer | null;
|
const buf = settings?.[column] as Buffer | null;
|
||||||
if (!buf) return error(reply, "Logo nenalezeno", 404);
|
if (!buf) return error(reply, "Logo nenalezeno", 404);
|
||||||
|
|
||||||
let mime = "image/png";
|
let mime = "image/png";
|
||||||
@@ -203,15 +203,9 @@ export default async function companySettingsRoutes(
|
|||||||
max_requests_per_minute: true,
|
max_requests_per_minute: true,
|
||||||
available_vat_rates: true,
|
available_vat_rates: true,
|
||||||
available_currencies: true,
|
available_currencies: true,
|
||||||
smtp_from: true,
|
|
||||||
smtp_from_name: true,
|
|
||||||
offer_number_pattern: true,
|
|
||||||
order_number_pattern: true,
|
|
||||||
invoice_number_pattern: true,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!settings) return error(reply, "Nastavení nenalezeno", 500);
|
|
||||||
|
|
||||||
// Check if logo exists
|
// Check if logo exists
|
||||||
const logoCheck = await prisma.company_settings.findFirst({
|
const logoCheck = await prisma.company_settings.findFirst({
|
||||||
@@ -225,8 +219,9 @@ export default async function companySettingsRoutes(
|
|||||||
settings.custom_fields as string | null,
|
settings.custom_fields as string | null,
|
||||||
);
|
);
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
const pkg = await import("../../../package.json", {
|
||||||
const pkg = require("../../../package.json") as { version: string };
|
assert: { type: "json" },
|
||||||
|
});
|
||||||
|
|
||||||
let available_vat_rates: number[] = [0, 10, 12, 15, 21];
|
let available_vat_rates: number[] = [0, 10, 12, 15, 21];
|
||||||
try {
|
try {
|
||||||
@@ -260,7 +255,7 @@ export default async function companySettingsRoutes(
|
|||||||
available_currencies,
|
available_currencies,
|
||||||
has_logo,
|
has_logo,
|
||||||
has_logo_dark,
|
has_logo_dark,
|
||||||
app_version: pkg.version,
|
app_version: pkg.default.version,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -269,8 +264,9 @@ export default async function companySettingsRoutes(
|
|||||||
"/system-info",
|
"/system-info",
|
||||||
{ preHandler: requirePermission("settings.manage") },
|
{ preHandler: requirePermission("settings.manage") },
|
||||||
async (request, reply) => {
|
async (request, reply) => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
const pkg = await import("../../../package.json", {
|
||||||
const pkg = require("../../../package.json") as { version: string };
|
assert: { type: "json" },
|
||||||
|
});
|
||||||
const uptimeSec = process.uptime();
|
const uptimeSec = process.uptime();
|
||||||
const days = Math.floor(uptimeSec / 86400);
|
const days = Math.floor(uptimeSec / 86400);
|
||||||
const hours = Math.floor((uptimeSec % 86400) / 3600);
|
const hours = Math.floor((uptimeSec % 86400) / 3600);
|
||||||
@@ -303,7 +299,7 @@ export default async function companySettingsRoutes(
|
|||||||
const projectNas = new NasFileManager();
|
const projectNas = new NasFileManager();
|
||||||
|
|
||||||
return success(reply, {
|
return success(reply, {
|
||||||
app_version: pkg.version,
|
app_version: pkg.default.version,
|
||||||
node_version: process.version,
|
node_version: process.version,
|
||||||
platform: `${os.type()} ${os.release()}`,
|
platform: `${os.type()} ${os.release()}`,
|
||||||
uptime: uptimeStr,
|
uptime: uptimeStr,
|
||||||
|
|||||||
Reference in New Issue
Block a user