feat(word-xml): remove POT/CUT auto-calculation toggle
This commit is contained in:
@@ -1,18 +1,25 @@
|
||||
'use client';
|
||||
"use client";
|
||||
|
||||
import { useXmlConfig } from '../hooks/use-xml-config';
|
||||
import { XmlSettings } from './xml-settings';
|
||||
import { CategoryManager } from './category-manager';
|
||||
import { XmlPreview } from './xml-preview';
|
||||
import { Separator } from '@/shared/components/ui/separator';
|
||||
import { Button } from '@/shared/components/ui/button';
|
||||
import { RotateCcw } from 'lucide-react';
|
||||
import { useXmlConfig } from "../hooks/use-xml-config";
|
||||
import { XmlSettings } from "./xml-settings";
|
||||
import { CategoryManager } from "./category-manager";
|
||||
import { XmlPreview } from "./xml-preview";
|
||||
import { Separator } from "@/shared/components/ui/separator";
|
||||
import { Button } from "@/shared/components/ui/button";
|
||||
import { RotateCcw } from "lucide-react";
|
||||
|
||||
export function WordXmlModule() {
|
||||
const {
|
||||
config, setMode, setBaseNamespace, setComputeMetrics,
|
||||
setCurrentCategory, updateCategoryFields, addCategory,
|
||||
removeCategory, resetCategoryToPreset, clearCategoryFields, resetAll,
|
||||
config,
|
||||
setMode,
|
||||
setBaseNamespace,
|
||||
setCurrentCategory,
|
||||
updateCategoryFields,
|
||||
addCategory,
|
||||
removeCategory,
|
||||
resetCategoryToPreset,
|
||||
clearCategoryFields,
|
||||
resetAll,
|
||||
} = useXmlConfig();
|
||||
|
||||
return (
|
||||
@@ -21,10 +28,8 @@ export function WordXmlModule() {
|
||||
<XmlSettings
|
||||
baseNamespace={config.baseNamespace}
|
||||
mode={config.mode}
|
||||
computeMetrics={config.computeMetrics}
|
||||
onSetBaseNamespace={setBaseNamespace}
|
||||
onSetMode={setMode}
|
||||
onSetComputeMetrics={setComputeMetrics}
|
||||
/>
|
||||
|
||||
<Separator />
|
||||
|
||||
@@ -1,28 +1,37 @@
|
||||
'use client';
|
||||
"use client";
|
||||
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Copy, Download, FileArchive } from 'lucide-react';
|
||||
import { Button } from '@/shared/components/ui/button';
|
||||
import type { XmlGeneratorConfig } from '../types';
|
||||
import { generateAllCategories, downloadXmlFile, downloadZipAll } from '../services/xml-generator';
|
||||
import { useMemo, useState } from "react";
|
||||
import { Copy, Download, FileArchive } from "lucide-react";
|
||||
import { Button } from "@/shared/components/ui/button";
|
||||
import type { XmlGeneratorConfig } from "../types";
|
||||
import {
|
||||
generateAllCategories,
|
||||
downloadXmlFile,
|
||||
downloadZipAll,
|
||||
} from "../services/xml-generator";
|
||||
|
||||
interface XmlPreviewProps {
|
||||
config: XmlGeneratorConfig;
|
||||
}
|
||||
|
||||
export function XmlPreview({ config }: XmlPreviewProps) {
|
||||
const [copied, setCopied] = useState<'xml' | 'xpath' | null>(null);
|
||||
const [copied, setCopied] = useState<"xml" | "xpath" | null>(null);
|
||||
|
||||
const allOutputs = useMemo(
|
||||
() => generateAllCategories(config.categories, config.baseNamespace, config.mode, config.computeMetrics),
|
||||
[config.categories, config.baseNamespace, config.mode, config.computeMetrics],
|
||||
() =>
|
||||
generateAllCategories(
|
||||
config.categories,
|
||||
config.baseNamespace,
|
||||
config.mode,
|
||||
),
|
||||
[config.categories, config.baseNamespace, config.mode],
|
||||
);
|
||||
|
||||
const current = allOutputs[config.currentCategory];
|
||||
const xml = current?.xml || '';
|
||||
const xpaths = current?.xpaths || '';
|
||||
const xml = current?.xml || "";
|
||||
const xpaths = current?.xpaths || "";
|
||||
|
||||
const handleCopy = async (text: string, type: 'xml' | 'xpath') => {
|
||||
const handleCopy = async (text: string, type: "xml" | "xpath") => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
setCopied(type);
|
||||
@@ -32,9 +41,9 @@ export function XmlPreview({ config }: XmlPreviewProps) {
|
||||
}
|
||||
};
|
||||
|
||||
const safeCatName = (config.currentCategory || 'unknown')
|
||||
.replace(/\s+/g, '_')
|
||||
.replace(/[^A-Za-z0-9_.-]/g, '');
|
||||
const safeCatName = (config.currentCategory || "unknown")
|
||||
.replace(/\s+/g, "_")
|
||||
.replace(/[^A-Za-z0-9_.-]/g, "");
|
||||
|
||||
const handleDownloadCurrent = () => {
|
||||
if (!xml) return;
|
||||
@@ -42,7 +51,7 @@ export function XmlPreview({ config }: XmlPreviewProps) {
|
||||
};
|
||||
|
||||
const handleDownloadZip = async () => {
|
||||
await downloadZipAll(config.categories, config.baseNamespace, config.mode, config.computeMetrics);
|
||||
await downloadZipAll(config.categories, config.baseNamespace, config.mode);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -50,7 +59,12 @@ export function XmlPreview({ config }: XmlPreviewProps) {
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<h2 className="text-lg font-semibold">Preview & Export</h2>
|
||||
<div className="ml-auto flex gap-2">
|
||||
<Button variant="outline" size="sm" onClick={handleDownloadCurrent} disabled={!xml}>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleDownloadCurrent}
|
||||
disabled={!xml}
|
||||
>
|
||||
<Download className="mr-1 h-4 w-4" /> XML curent
|
||||
</Button>
|
||||
<Button size="sm" onClick={handleDownloadZip}>
|
||||
@@ -63,28 +77,45 @@ export function XmlPreview({ config }: XmlPreviewProps) {
|
||||
{/* XML preview */}
|
||||
<div>
|
||||
<div className="mb-1.5 flex items-center justify-between">
|
||||
<span className="text-xs font-medium text-muted-foreground">XML — {config.currentCategory}</span>
|
||||
<Button variant="ghost" size="sm" className="h-6 text-xs" onClick={() => handleCopy(xml, 'xml')} disabled={!xml}>
|
||||
<span className="text-xs font-medium text-muted-foreground">
|
||||
XML — {config.currentCategory}
|
||||
</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-6 text-xs"
|
||||
onClick={() => handleCopy(xml, "xml")}
|
||||
disabled={!xml}
|
||||
>
|
||||
<Copy className="mr-1 h-3 w-3" />
|
||||
{copied === 'xml' ? 'Copiat!' : 'Copiază'}
|
||||
{copied === "xml" ? "Copiat!" : "Copiază"}
|
||||
</Button>
|
||||
</div>
|
||||
<pre className="max-h-80 overflow-auto rounded-lg border bg-muted/30 p-3 text-xs">
|
||||
{xml || '<!-- Niciun XML generat. Adaugă câmpuri în categoria curentă. -->'}
|
||||
{xml ||
|
||||
"<!-- Niciun XML generat. Adaugă câmpuri în categoria curentă. -->"}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
{/* XPath preview */}
|
||||
<div>
|
||||
<div className="mb-1.5 flex items-center justify-between">
|
||||
<span className="text-xs font-medium text-muted-foreground">XPaths — {config.currentCategory}</span>
|
||||
<Button variant="ghost" size="sm" className="h-6 text-xs" onClick={() => handleCopy(xpaths, 'xpath')} disabled={!xpaths}>
|
||||
<span className="text-xs font-medium text-muted-foreground">
|
||||
XPaths — {config.currentCategory}
|
||||
</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-6 text-xs"
|
||||
onClick={() => handleCopy(xpaths, "xpath")}
|
||||
disabled={!xpaths}
|
||||
>
|
||||
<Copy className="mr-1 h-3 w-3" />
|
||||
{copied === 'xpath' ? 'Copiat!' : 'Copiază'}
|
||||
{copied === "xpath" ? "Copiat!" : "Copiază"}
|
||||
</Button>
|
||||
</div>
|
||||
<pre className="max-h-80 overflow-auto rounded-lg border bg-muted/30 p-3 text-xs">
|
||||
{xpaths || ''}
|
||||
{xpaths || ""}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
'use client';
|
||||
"use client";
|
||||
|
||||
import type { XmlGeneratorMode } from '../types';
|
||||
import { Input } from '@/shared/components/ui/input';
|
||||
import { Label } from '@/shared/components/ui/label';
|
||||
import { Switch } from '@/shared/components/ui/switch';
|
||||
import { cn } from '@/shared/lib/utils';
|
||||
import type { XmlGeneratorMode } from "../types";
|
||||
import { Input } from "@/shared/components/ui/input";
|
||||
import { Label } from "@/shared/components/ui/label";
|
||||
import { cn } from "@/shared/lib/utils";
|
||||
|
||||
interface XmlSettingsProps {
|
||||
baseNamespace: string;
|
||||
mode: XmlGeneratorMode;
|
||||
computeMetrics: boolean;
|
||||
onSetBaseNamespace: (ns: string) => void;
|
||||
onSetMode: (mode: XmlGeneratorMode) => void;
|
||||
onSetComputeMetrics: (v: boolean) => void;
|
||||
}
|
||||
|
||||
export function XmlSettings({
|
||||
baseNamespace, mode, computeMetrics,
|
||||
onSetBaseNamespace, onSetMode, onSetComputeMetrics,
|
||||
baseNamespace,
|
||||
mode,
|
||||
onSetBaseNamespace,
|
||||
onSetMode,
|
||||
}: XmlSettingsProps) {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
@@ -38,31 +37,28 @@ export function XmlSettings({
|
||||
<div>
|
||||
<Label className="mb-1.5 block">Mod generare</Label>
|
||||
<div className="flex gap-1.5">
|
||||
{(['simple', 'advanced'] as XmlGeneratorMode[]).map((m) => (
|
||||
{(["simple", "advanced"] as XmlGeneratorMode[]).map((m) => (
|
||||
<button
|
||||
key={m}
|
||||
type="button"
|
||||
onClick={() => onSetMode(m)}
|
||||
className={cn(
|
||||
'rounded-full border px-3 py-1 text-xs font-medium transition-colors',
|
||||
"rounded-full border px-3 py-1 text-xs font-medium transition-colors",
|
||||
mode === m
|
||||
? 'border-primary bg-primary text-primary-foreground'
|
||||
: 'border-border hover:bg-accent'
|
||||
? "border-primary bg-primary text-primary-foreground"
|
||||
: "border-border hover:bg-accent",
|
||||
)}
|
||||
>
|
||||
{m === 'simple' ? 'Simple' : 'Advanced'}
|
||||
{m === "simple" ? "Simple" : "Advanced"}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-1 text-xs text-muted-foreground">
|
||||
{mode === 'simple' ? 'Doar câmpurile definite.' : '+ Short / Upper / Lower / Initials / First.'}
|
||||
{mode === "simple"
|
||||
? "Doar câmpurile definite."
|
||||
: "+ Short / Upper / Lower / Initials / First."}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="ml-auto flex items-center gap-2">
|
||||
<Switch checked={computeMetrics} onCheckedChange={onSetComputeMetrics} id="xml-metrics" />
|
||||
<Label htmlFor="xml-metrics" className="cursor-pointer text-sm">POT / CUT automat</Label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
'use client';
|
||||
"use client";
|
||||
|
||||
import { useState, useCallback, useMemo } from 'react';
|
||||
import type { XmlGeneratorConfig, XmlGeneratorMode } from '../types';
|
||||
import { DEFAULT_PRESETS } from '../services/category-presets';
|
||||
import { useState, useCallback, useMemo } from "react";
|
||||
import type { XmlGeneratorConfig, XmlGeneratorMode } from "../types";
|
||||
import { DEFAULT_PRESETS } from "../services/category-presets";
|
||||
|
||||
function createDefaultConfig(): XmlGeneratorConfig {
|
||||
const categories: Record<string, { name: string; fieldsText: string }> = {};
|
||||
for (const [name, fields] of Object.entries(DEFAULT_PRESETS)) {
|
||||
categories[name] = { name, fieldsText: fields.join('\n') };
|
||||
categories[name] = { name, fieldsText: fields.join("\n") };
|
||||
}
|
||||
return {
|
||||
baseNamespace: 'http://schemas.beletage.ro/contract',
|
||||
mode: 'advanced',
|
||||
computeMetrics: true,
|
||||
baseNamespace: "http://schemas.beletage.ro/contract",
|
||||
mode: "advanced",
|
||||
categories,
|
||||
currentCategory: 'Beneficiar',
|
||||
currentCategory: "Beneficiar",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -29,15 +28,12 @@ export function useXmlConfig() {
|
||||
setConfig((prev) => ({ ...prev, baseNamespace }));
|
||||
}, []);
|
||||
|
||||
const setComputeMetrics = useCallback((computeMetrics: boolean) => {
|
||||
setConfig((prev) => ({ ...prev, computeMetrics }));
|
||||
}, []);
|
||||
|
||||
const setCurrentCategory = useCallback((name: string) => {
|
||||
setConfig((prev) => ({ ...prev, currentCategory: name }));
|
||||
}, []);
|
||||
|
||||
const updateCategoryFields = useCallback((categoryName: string, fieldsText: string) => {
|
||||
const updateCategoryFields = useCallback(
|
||||
(categoryName: string, fieldsText: string) => {
|
||||
setConfig((prev) => {
|
||||
const existing = prev.categories[categoryName];
|
||||
if (!existing) return prev;
|
||||
@@ -49,14 +45,16 @@ export function useXmlConfig() {
|
||||
},
|
||||
};
|
||||
});
|
||||
}, []);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const addCategory = useCallback((name: string) => {
|
||||
setConfig((prev) => {
|
||||
if (prev.categories[name]) return prev;
|
||||
return {
|
||||
...prev,
|
||||
categories: { ...prev.categories, [name]: { name, fieldsText: '' } },
|
||||
categories: { ...prev.categories, [name]: { name, fieldsText: "" } },
|
||||
currentCategory: name,
|
||||
};
|
||||
});
|
||||
@@ -70,7 +68,9 @@ export function useXmlConfig() {
|
||||
return {
|
||||
...prev,
|
||||
categories: next,
|
||||
currentCategory: keys.includes(prev.currentCategory) ? prev.currentCategory : keys[0] || '',
|
||||
currentCategory: keys.includes(prev.currentCategory)
|
||||
? prev.currentCategory
|
||||
: keys[0] || "",
|
||||
};
|
||||
});
|
||||
}, []);
|
||||
@@ -82,7 +82,7 @@ export function useXmlConfig() {
|
||||
...prev,
|
||||
categories: {
|
||||
...prev.categories,
|
||||
[name]: { name, fieldsText: preset.join('\n') },
|
||||
[name]: { name, fieldsText: preset.join("\n") },
|
||||
},
|
||||
}));
|
||||
}, []);
|
||||
@@ -95,7 +95,7 @@ export function useXmlConfig() {
|
||||
...prev,
|
||||
categories: {
|
||||
...prev.categories,
|
||||
[name]: { name: existing.name, fieldsText: '' },
|
||||
[name]: { name: existing.name, fieldsText: "" },
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -109,11 +109,11 @@ export function useXmlConfig() {
|
||||
setConfig(loaded);
|
||||
}, []);
|
||||
|
||||
return useMemo(() => ({
|
||||
return useMemo(
|
||||
() => ({
|
||||
config,
|
||||
setMode,
|
||||
setBaseNamespace,
|
||||
setComputeMetrics,
|
||||
setCurrentCategory,
|
||||
updateCategoryFields,
|
||||
addCategory,
|
||||
@@ -122,7 +122,19 @@ export function useXmlConfig() {
|
||||
clearCategoryFields,
|
||||
resetAll,
|
||||
loadConfig,
|
||||
}), [config, setMode, setBaseNamespace, setComputeMetrics, setCurrentCategory,
|
||||
updateCategoryFields, addCategory, removeCategory, resetCategoryToPreset,
|
||||
clearCategoryFields, resetAll, loadConfig]);
|
||||
}),
|
||||
[
|
||||
config,
|
||||
setMode,
|
||||
setBaseNamespace,
|
||||
setCurrentCategory,
|
||||
updateCategoryFields,
|
||||
addCategory,
|
||||
removeCategory,
|
||||
resetCategoryToPreset,
|
||||
clearCategoryFields,
|
||||
resetAll,
|
||||
loadConfig,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import type { XmlGeneratorMode, XmlCategory, GeneratedOutput } from '../types';
|
||||
import type { XmlGeneratorMode, XmlCategory, GeneratedOutput } from "../types";
|
||||
|
||||
function sanitizeName(name: string): string | null {
|
||||
const trimmed = name.trim();
|
||||
if (!trimmed) return null;
|
||||
let n = trimmed.replace(/\s+/g, '_').replace(/[^A-Za-z0-9_.-]/g, '');
|
||||
if (!/^[A-Za-z_]/.test(n)) n = '_' + n;
|
||||
let n = trimmed.replace(/\s+/g, "_").replace(/[^A-Za-z0-9_.-]/g, "");
|
||||
if (!/^[A-Za-z_]/.test(n)) n = "_" + n;
|
||||
return n || null;
|
||||
}
|
||||
|
||||
function getCategoryNamespace(baseNs: string, category: string): string {
|
||||
const safeCat = sanitizeName(category) || category;
|
||||
return baseNs.replace(/\/+$/, '') + '/' + safeCat;
|
||||
return baseNs.replace(/\/+$/, "") + "/" + safeCat;
|
||||
}
|
||||
|
||||
function getCategoryRoot(category: string): string {
|
||||
const safeCat = sanitizeName(category) || category;
|
||||
return safeCat + 'Data';
|
||||
return safeCat + "Data";
|
||||
}
|
||||
|
||||
interface FieldEntry {
|
||||
@@ -29,14 +29,13 @@ export function generateCategoryXml(
|
||||
catData: XmlCategory,
|
||||
baseNamespace: string,
|
||||
mode: XmlGeneratorMode,
|
||||
computeMetrics: boolean,
|
||||
): GeneratedOutput {
|
||||
const raw = catData.fieldsText
|
||||
.split(/\r?\n/)
|
||||
.map((l) => l.trim())
|
||||
.filter((l) => l.length > 0);
|
||||
|
||||
if (raw.length === 0) return { xml: '', xpaths: '' };
|
||||
if (raw.length === 0) return { xml: "", xpaths: "" };
|
||||
|
||||
const ns = getCategoryNamespace(baseNamespace, category);
|
||||
const root = getCategoryRoot(category);
|
||||
@@ -51,19 +50,19 @@ export function generateCategoryXml(
|
||||
let baseName = base;
|
||||
let idx = 2;
|
||||
while (usedNames.has(baseName)) {
|
||||
baseName = base + '_' + idx;
|
||||
baseName = base + "_" + idx;
|
||||
idx++;
|
||||
}
|
||||
usedNames.add(baseName);
|
||||
|
||||
const variants = [baseName];
|
||||
if (mode === 'advanced') {
|
||||
const suffixes = ['Short', 'Upper', 'Lower', 'Initials', 'First'];
|
||||
if (mode === "advanced") {
|
||||
const suffixes = ["Short", "Upper", "Lower", "Initials", "First"];
|
||||
for (const suffix of suffixes) {
|
||||
let vn = baseName + suffix;
|
||||
let k = 2;
|
||||
while (usedNames.has(vn)) {
|
||||
vn = baseName + suffix + '_' + k;
|
||||
vn = baseName + suffix + "_" + k;
|
||||
k++;
|
||||
}
|
||||
usedNames.add(vn);
|
||||
@@ -74,24 +73,7 @@ export function generateCategoryXml(
|
||||
fields.push({ label, baseName, variants });
|
||||
}
|
||||
|
||||
// Auto-add POT/CUT for Suprafete category
|
||||
const extraMetricFields: FieldEntry[] = [];
|
||||
if (computeMetrics && category.toLowerCase().includes('suprafete')) {
|
||||
const hasTeren = fields.some((f) => f.baseName.toLowerCase().includes('suprafatateren'));
|
||||
const hasLaSol = fields.some((f) => f.baseName.toLowerCase().includes('suprafataconstruitalasol'));
|
||||
const hasDesf = fields.some((f) => f.baseName.toLowerCase().includes('suprafatadesfasurata'));
|
||||
|
||||
if (hasTeren && hasLaSol && !usedNames.has('POT')) {
|
||||
usedNames.add('POT');
|
||||
extraMetricFields.push({ label: 'Procent Ocupare Teren', baseName: 'POT', variants: ['POT'] });
|
||||
}
|
||||
if (hasTeren && hasDesf && !usedNames.has('CUT')) {
|
||||
usedNames.add('CUT');
|
||||
extraMetricFields.push({ label: 'Coeficient Utilizare Teren', baseName: 'CUT', variants: ['CUT'] });
|
||||
}
|
||||
}
|
||||
|
||||
const allFields = fields.concat(extraMetricFields);
|
||||
const allFields = fields;
|
||||
|
||||
// Build XML
|
||||
let xml = '<?xml version="1.0" encoding="UTF-8"?>\n';
|
||||
@@ -110,18 +92,8 @@ export function generateCategoryXml(
|
||||
for (const v of f.variants) {
|
||||
xp += `/${root}/${v}\n`;
|
||||
}
|
||||
xp += '\n';
|
||||
xp += "\n";
|
||||
}
|
||||
if (extraMetricFields.length > 0) {
|
||||
xp += '# Metrici auto (POT / CUT)\n';
|
||||
for (const f of extraMetricFields) {
|
||||
for (const v of f.variants) {
|
||||
xp += `/${root}/${v}\n`;
|
||||
}
|
||||
}
|
||||
xp += '\n';
|
||||
}
|
||||
|
||||
return { xml, xpaths: xp };
|
||||
}
|
||||
|
||||
@@ -129,20 +101,19 @@ export function generateAllCategories(
|
||||
categories: Record<string, XmlCategory>,
|
||||
baseNamespace: string,
|
||||
mode: XmlGeneratorMode,
|
||||
computeMetrics: boolean,
|
||||
): Record<string, GeneratedOutput> {
|
||||
const results: Record<string, GeneratedOutput> = {};
|
||||
for (const cat of Object.keys(categories)) {
|
||||
const catData = categories[cat];
|
||||
if (!catData) continue;
|
||||
results[cat] = generateCategoryXml(cat, catData, baseNamespace, mode, computeMetrics);
|
||||
results[cat] = generateCategoryXml(cat, catData, baseNamespace, mode);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
export function downloadXmlFile(xml: string, filename: string): void {
|
||||
const blob = new Blob([xml], { type: 'application/xml' });
|
||||
const a = document.createElement('a');
|
||||
const blob = new Blob([xml], { type: "application/xml" });
|
||||
const a = document.createElement("a");
|
||||
a.href = URL.createObjectURL(blob);
|
||||
a.download = filename;
|
||||
document.body.appendChild(a);
|
||||
@@ -155,13 +126,12 @@ export async function downloadZipAll(
|
||||
categories: Record<string, XmlCategory>,
|
||||
baseNamespace: string,
|
||||
mode: XmlGeneratorMode,
|
||||
computeMetrics: boolean,
|
||||
): Promise<void> {
|
||||
const JSZip = (await import('jszip')).default;
|
||||
const results = generateAllCategories(categories, baseNamespace, mode, computeMetrics);
|
||||
const JSZip = (await import("jszip")).default;
|
||||
const results = generateAllCategories(categories, baseNamespace, mode);
|
||||
|
||||
const zip = new JSZip();
|
||||
const folder = zip.folder('customXmlParts')!;
|
||||
const folder = zip.folder("customXmlParts")!;
|
||||
|
||||
let hasAny = false;
|
||||
for (const cat of Object.keys(results)) {
|
||||
@@ -175,10 +145,10 @@ export async function downloadZipAll(
|
||||
|
||||
if (!hasAny) return;
|
||||
|
||||
const content = await zip.generateAsync({ type: 'blob' });
|
||||
const a = document.createElement('a');
|
||||
const content = await zip.generateAsync({ type: "blob" });
|
||||
const a = document.createElement("a");
|
||||
a.href = URL.createObjectURL(content);
|
||||
a.download = 'beletage_custom_xml_parts.zip';
|
||||
a.download = "beletage_custom_xml_parts.zip";
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export type XmlGeneratorMode = 'simple' | 'advanced';
|
||||
export type XmlGeneratorMode = "simple" | "advanced";
|
||||
|
||||
export interface XmlCategory {
|
||||
name: string;
|
||||
@@ -8,7 +8,6 @@ export interface XmlCategory {
|
||||
export interface XmlGeneratorConfig {
|
||||
baseNamespace: string;
|
||||
mode: XmlGeneratorMode;
|
||||
computeMetrics: boolean;
|
||||
categories: Record<string, XmlCategory>;
|
||||
currentCategory: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user