Example-flows + noder: defaults pekar bara på filer som finns

Flöden (flows/example-flows.json):
- Kedjor som skapar det de behöver: png→asset, templates:list→create→
  extract/fill/transform/extractFields, create A+B→compareVersionsPdf
- Defaults /Dokument/Example.md, /Dokument/exempel.odt, dest
  /Dokument/OfficeOut/, mall-id 230 (Invoice.odt via templates:list)
- Ingen referens till /Mallar/avtal.docx, avtal-ny.docx eller logotyp.png
- Debug-noder med tostatus=false (undviker TypeError-length i status)

Noder:
- nc-office templates:create: skickar path+template (richdocuments-
  kontrakt), ärver extension från mallen, MKCOL av mapp, idempotent
  (återanvänd existerande fil i stället för 'namn (2)') — fixar OCS 400
- nc-office document:direct: fileId camelCase (+fileid), 996-fel
  inkluderar nu OCS-body i felmeddelandet
- collabora-wopi discovery: rewrite urlsrc/favIconUrl till
  collaboraPublicUrl så iframe inte går mot CODE bridge-IP
- webdavGet/PROPFIND 404: feltext med föreslagen åtgärd
- resolveDestNcPath: tvingar rätt filändelse (.pdf/.png/…)
- Nytt: listUserExamples (PROPFIND /Dokument+/Documents) +
  bridge-op pickDemoSource; scripts/discover-examples.js

Verifierat mot cloud.domain.name (your-user): capabilities, discovery-
rewrite, pdf/png, asset-länk, mall-skapa+extract/fill/transform,
compare A/B→pdf, document:direct, htmlToOffice — ALL PASS.
This commit is contained in:
dev
2026-08-22 22:50:47 +02:00
parent 5ca7b4d4e0
commit 5ee179539e
11 changed files with 801 additions and 69 deletions
+512 -49
View File
@@ -4,7 +4,7 @@
"type": "tab",
"label": "NC Collabora — examples",
"disabled": false,
"info": "Create nc-collab-config first (gear menu). Set FILL_IN_USER and app password.\n\n1. capabilities — is CODE up?\n2. ncFileToPdf — PDF in OfficeOut\n3. document:direct — editorUrl\n\nSee docs/NODES.md"
"info": "Create/edit nc-collab-config (gear): Nextcloud URL, username + app password,\nCollabora intern https://code:9980 (verifyTls av), publik URL t.ex. https://docs.domain.name.\n\nAlla kedjor utgår från filer som FINNS på denna host:\n /Dokument/Example.md, /Dokument/exempel.odt\nMall-id 230 = Invoice.odt (hämtat via templates:list — kör kedjan\n'templates:list → pick → create' om id:n skiljer).\nDestinationer landar i /Dokument/OfficeOut/ (MKCOL sker tyst).\n\nKedjor:\n 1. capabilities + discovery (urlsrc skrivs om till publik bas)\n 2. ncFileToPdf (/Dokument/Example.md)\n 3. ncFileToPng → createAssetLink (png:n skapas först i kedjan)\n 4. document:direct mot befintlig fil (PROPFIND fileId)\n 5. htmlToOffice\n 6. templates:create explicit (msg.template + msg.path)\n 7. templates:list → pick → create → extract/fill/transform/extractFields\n 8. compareVersionsPdf: två kopior skapade först via templates:create\n\nSe docs/NODES.md"
},
{
"id": "nc_collab_cfg",
@@ -12,21 +12,22 @@
"name": "cloud.domain.name",
"nextcloudUrl": "https://cloud.domain.name",
"collaboraUrl": "https://code:9980",
"collaboraPublicUrl": "https://cloud.domain.name",
"collaboraPublicUrl": "https://docs.domain.name",
"username": "FILL_IN_USER",
"verifyTls": false
},
{
"id": "inj_capabilities",
"type": "inject",
"z": "collab_tab",
"name": "1. CODE capabilities",
"name": "1a. CODE capabilities",
"props": [],
"repeat": "",
"crontab": "",
"once": false,
"topic": "",
"x": 150,
"x": 160,
"y": 80,
"wires": [["wopi_cap"]]
},
@@ -37,7 +38,7 @@
"name": "capabilities",
"config": "nc_collab_cfg",
"operation": "capabilities",
"x": 380,
"x": 400,
"y": 80,
"wires": [["dbg_cap"]]
},
@@ -51,28 +52,66 @@
"console": false,
"tostatus": false,
"complete": "payload",
"x": 590,
"x": 620,
"y": 80,
"wires": []
},
{
"id": "inj_discovery",
"type": "inject",
"z": "collab_tab",
"name": "1b. discovery (publik rewrite)",
"props": [],
"repeat": "",
"crontab": "",
"once": false,
"topic": "",
"x": 170,
"y": 140,
"wires": [["wopi_disc"]]
},
{
"id": "wopi_disc",
"type": "collabora-wopi",
"z": "collab_tab",
"name": "discovery",
"config": "nc_collab_cfg",
"operation": "discovery",
"x": 400,
"y": 140,
"wires": [["dbg_disc"]]
},
{
"id": "dbg_disc",
"type": "debug",
"z": "collab_tab",
"name": "urlsrc ska peka på publik bas",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"x": 640,
"y": 140,
"wires": []
},
{
"id": "inj_pdf",
"type": "inject",
"z": "collab_tab",
"name": "2. NC-fil → PDF",
"name": "2. Example.md → PDF",
"props": [
{
"p": "ncPath",
"v": "/Dokument/test.docx",
"vt": "str"
}
{ "p": "ncPath", "v": "/Dokument/Example.md", "vt": "str" },
{ "p": "destName", "v": "Example.pdf", "vt": "str" }
],
"repeat": "",
"crontab": "",
"once": false,
"topic": "",
"x": 150,
"y": 160,
"x": 160,
"y": 220,
"wires": [["bridge_pdf"]]
},
{
@@ -82,8 +121,8 @@
"name": "ncFileToPdf",
"config": "nc_collab_cfg",
"operation": "ncFileToPdf",
"x": 380,
"y": 160,
"x": 400,
"y": 220,
"wires": [["dbg_pdf"]]
},
{
@@ -96,28 +135,91 @@
"console": false,
"tostatus": false,
"complete": "destNcPath",
"x": 590,
"y": 160,
"x": 620,
"y": 220,
"wires": []
},
{
"id": "inj_editor",
"id": "inj_png_asset",
"type": "inject",
"z": "collab_tab",
"name": "3. Open in Office",
"name": "3. exempel.odt → PNG → asset-länk",
"props": [
{
"p": "ncPath",
"v": "/Dokument/test.docx",
"vt": "str"
}
{ "p": "ncPath", "v": "/Dokument/exempel.odt", "vt": "str" },
{ "p": "destName", "v": "demo-asset.png", "vt": "str" }
],
"repeat": "",
"crontab": "",
"once": false,
"topic": "",
"x": 150,
"y": 240,
"x": 190,
"y": 300,
"wires": [["bridge_png"]]
},
{
"id": "bridge_png",
"type": "collabora-bridge",
"z": "collab_tab",
"name": "ncFileToPng",
"config": "nc_collab_cfg",
"operation": "ncFileToPng",
"x": 410,
"y": 300,
"wires": [["fn_asset_path"]]
},
{
"id": "fn_asset_path",
"type": "function",
"z": "collab_tab",
"name": "peka ncPath på nya png:en",
"func": "if (!msg.destNcPath) { return null; }\nmsg.ncPath = msg.destNcPath;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 630,
"y": 300,
"wires": [["bridge_asset"]]
},
{
"id": "bridge_asset",
"type": "collabora-bridge",
"z": "collab_tab",
"name": "createAssetLink",
"config": "nc_collab_cfg",
"operation": "createAssetLink",
"x": 860,
"y": 300,
"wires": [["dbg_asset"]]
},
{
"id": "dbg_asset",
"type": "debug",
"z": "collab_tab",
"name": "assetUrl",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "assetUrl",
"x": 1080,
"y": 300,
"wires": []
},
{
"id": "inj_direct",
"type": "inject",
"z": "collab_tab",
"name": "4. document:direct (befintlig fil)",
"props": [
{ "p": "ncPath", "v": "/Dokument/exempel.odt", "vt": "str" }
],
"repeat": "",
"crontab": "",
"once": false,
"topic": "",
"x": 190,
"y": 380,
"wires": [["office_direct"]]
},
{
@@ -127,8 +229,8 @@
"name": "document:direct",
"config": "nc_collab_cfg",
"operation": "document:direct",
"x": 380,
"y": 240,
"x": 420,
"y": 380,
"wires": [["dbg_editor"]]
},
{
@@ -141,53 +243,414 @@
"console": false,
"tostatus": false,
"complete": "editorUrl",
"x": 590,
"y": 240,
"x": 640,
"y": 380,
"wires": []
},
{
"id": "inj_extract",
"id": "inj_html",
"type": "inject",
"z": "collab_tab",
"name": "4. Template fields",
"name": "5. HTML → PDF",
"props": [
{
"p": "ncPath",
"v": "/Mallar/avtal.docx",
"vt": "str"
}
{ "p": "payload", "v": "<!doctype html><html><body><h1>Rapport</h1><p>Skapad av Node-RED mot Collabora CODE.</p></body></html>", "vt": "str" },
{ "p": "filename", "v": "rapport.html", "vt": "str" },
{ "p": "format", "v": "pdf", "vt": "str" },
{ "p": "destName", "v": "rapport-demo.pdf", "vt": "str" }
],
"repeat": "",
"crontab": "",
"once": false,
"topic": "",
"x": 150,
"y": 320,
"wires": [["bridge_extract"]]
"y": 460,
"wires": [["bridge_html"]]
},
{
"id": "bridge_html",
"type": "collabora-bridge",
"z": "collab_tab",
"name": "htmlToOffice",
"config": "nc_collab_cfg",
"operation": "htmlToOffice",
"x": 410,
"y": 460,
"wires": [["dbg_html"]]
},
{
"id": "dbg_html",
"type": "debug",
"z": "collab_tab",
"name": "destNcPath",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "destNcPath",
"x": 630,
"y": 460,
"wires": []
},
{
"id": "inj_tpl_explicit",
"type": "inject",
"z": "collab_tab",
"name": "6. skapa från mall 230 (Invoice)",
"props": [
{ "p": "template", "v": 230, "vt": "num" },
{ "p": "path", "v": "/Dokument/OfficeOut/fran-mall", "vt": "str" },
{ "p": "templateExtension", "v": "odt", "vt": "str" }
],
"repeat": "",
"crontab": "",
"once": false,
"topic": "",
"x": 180,
"y": 540,
"wires": [["office_tpl_create1"]]
},
{
"id": "office_tpl_create1",
"type": "nc-office",
"z": "collab_tab",
"name": "templates:create (path+template)",
"config": "nc_collab_cfg",
"operation": "templates:create",
"x": 450,
"y": 540,
"wires": [["fn_created_direct"]]
},
{
"id": "fn_created_direct",
"type": "function",
"z": "collab_tab",
"name": "använd skapad fil",
"func": "if (!msg.createdPath) { return null; }\nmsg.ncPath = msg.createdPath;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 700,
"y": 540,
"wires": [["office_extract_fields"]]
},
{
"id": "office_extract_fields",
"type": "nc-office",
"z": "collab_tab",
"name": "extractFields (fileId via PROPFIND)",
"config": "nc_collab_cfg",
"operation": "template:extractFields",
"x": 950,
"y": 540,
"wires": [["dbg_tpl_fields"]]
},
{
"id": "dbg_tpl_fields",
"type": "debug",
"z": "collab_tab",
"name": "fields (tom lista är OK)",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"x": 1200,
"y": 540,
"wires": []
},
{
"id": "inj_tpl_chain",
"type": "inject",
"z": "collab_tab",
"name": "7a. lista mallar",
"props": [],
"repeat": "",
"crontab": "",
"once": false,
"topic": "",
"x": 150,
"y": 640,
"wires": [["office_tpl_list"]]
},
{
"id": "office_tpl_list",
"type": "nc-office",
"z": "collab_tab",
"name": "templates:list document",
"config": "nc_collab_cfg",
"operation": "templates:list",
"x": 380,
"y": 640,
"wires": [["fn_pick_template"]]
},
{
"id": "fn_pick_template",
"type": "function",
"z": "collab_tab",
"name": "pick Invoice/Letter (inte Empty)",
"func": "const list = Array.isArray(msg.payload) ? msg.payload : (msg.payload && msg.payload.data) || [];\nconst docs = list.filter(t => t && t.type === 'document' && !/^empty/i.test(String(t.name || '')));\nconst pick = docs.find(t => /invoice/i.test(t.name)) || docs.find(t => /letter/i.test(t.name)) || docs[0];\nif (!pick) {\n throw new Error('Ingen document-mall hittad (forvantade Invoice/Letter, inte Empty) - kor templates:list forst');\n}\n// Extension fran mallens NAMN (Invoice.odt -> odt) speglar verkligt innehall;\n// 'extension'-faltet kan avvika nar NC doc_format=ooxml.\nconst nameExt = (String(pick.name || '').match(/\\.([A-Za-z0-9]+)$/) || [])[1];\nconst ext = nameExt || pick.extension || 'odt';\nmsg.templateList = list;\nmsg.template = pick.id;\nmsg.templateName = pick.name;\nmsg.templateExtension = ext;\nmsg.path = '/Dokument/OfficeOut/demo-mall.' + ext;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 610,
"y": 640,
"wires": [["office_tpl_create2"]]
},
{
"id": "office_tpl_create2",
"type": "nc-office",
"z": "collab_tab",
"name": "templates:create demo-mall",
"config": "nc_collab_cfg",
"operation": "templates:create",
"x": 850,
"y": 640,
"wires": [["fn_use_created"]]
},
{
"id": "fn_use_created",
"type": "function",
"z": "collab_tab",
"name": "prep: ncPath/fileId/fields {}",
"func": "if (!msg.createdPath) { return null; }\nmsg.ncPath = msg.createdPath;\nmsg.fileId = undefined;\nmsg.fields = {};\nmsg.transform = {};\nmsg.destNcPath = '/Dokument/OfficeOut/demo-mall-ifylld.' + (msg.templateExtension || 'odt');\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 1090,
"y": 640,
"wires": [
["bridge_extract"],
["office_extract2"],
["bridge_fill"],
["node_transform"]
]
},
{
"id": "bridge_extract",
"type": "collabora-bridge",
"z": "collab_tab",
"name": "extractToPayload",
"name": "extract struktur",
"config": "nc_collab_cfg",
"operation": "extractToPayload",
"x": 390,
"y": 320,
"wires": [["dbg_fields"]]
"x": 1330,
"y": 560,
"wires": [["dbg_structure"]]
},
{
"id": "dbg_fields",
"id": "dbg_structure",
"type": "debug",
"z": "collab_tab",
"name": "fields / structure",
"name": "structure",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "fields",
"x": 610,
"y": 320,
"complete": "structure",
"x": 1550,
"y": 560,
"wires": []
},
{
"id": "office_extract2",
"type": "nc-office",
"z": "collab_tab",
"name": "extractFields (OCS)",
"config": "nc_collab_cfg",
"operation": "template:extractFields",
"x": 1320,
"y": 620,
"wires": [["dbg_ocs_fields"]]
},
{
"id": "dbg_ocs_fields",
"type": "debug",
"z": "collab_tab",
"name": "OCS fields",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"x": 1540,
"y": 620,
"wires": []
},
{
"id": "bridge_fill",
"type": "collabora-bridge",
"z": "collab_tab",
"name": "fillTemplateSave {}",
"config": "nc_collab_cfg",
"operation": "fillTemplateSave",
"x": 1320,
"y": 680,
"wires": [["dbg_fill"]]
},
{
"id": "dbg_fill",
"type": "debug",
"z": "collab_tab",
"name": "ifylld destNcPath",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "destNcPath",
"x": 1550,
"y": 680,
"wires": []
},
{
"id": "node_transform",
"type": "collabora-transform",
"z": "collab_tab",
"name": "transform {}",
"config": "nc_collab_cfg",
"x": 1310,
"y": 740,
"wires": [["dbg_transform"]]
},
{
"id": "dbg_transform",
"type": "debug",
"z": "collab_tab",
"name": "transform buffer",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "contentType",
"x": 1540,
"y": 740,
"wires": []
},
{
"id": "inj_compare_a",
"type": "inject",
"z": "collab_tab",
"name": "8a. skapa kopia A",
"props": [
{ "p": "template", "v": 230, "vt": "num" },
{ "p": "path", "v": "/Dokument/OfficeOut/demo-a.odt", "vt": "str" }
],
"repeat": "",
"crontab": "",
"once": false,
"topic": "",
"x": 160,
"y": 860,
"wires": [["office_cmp_a"]]
},
{
"id": "office_cmp_a",
"type": "nc-office",
"z": "collab_tab",
"name": "templates:create A",
"config": "nc_collab_cfg",
"operation": "templates:create",
"x": 420,
"y": 860,
"wires": [["fn_to_b"]]
},
{
"id": "fn_to_b",
"type": "function",
"z": "collab_tab",
"name": "byt path till B",
"func": "if (!msg.createdPath) { return null; }\nmsg.path = '/Dokument/OfficeOut/demo-b.odt';\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 640,
"y": 860,
"wires": [["office_cmp_b"]]
},
{
"id": "office_cmp_b",
"type": "nc-office",
"z": "collab_tab",
"name": "templates:create B",
"config": "nc_collab_cfg",
"operation": "templates:create",
"x": 880,
"y": 860,
"wires": [["fn_compare_setup"]]
},
{
"id": "fn_compare_setup",
"type": "function",
"z": "collab_tab",
"name": "sätt A/B + dest",
"func": "if (!msg.createdPath) { return null; }\nmsg.ncPath = '/Dokument/OfficeOut/demo-a.odt';\nmsg.compareNcPath = '/Dokument/OfficeOut/demo-b.odt';\nmsg.destNcPath = '/Dokument/OfficeOut/demo-diff.pdf';\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 1110,
"y": 860,
"wires": [["bridge_compare"]]
},
{
"id": "bridge_compare",
"type": "collabora-bridge",
"z": "collab_tab",
"name": "compareVersionsPdf",
"config": "nc_collab_cfg",
"operation": "compareVersionsPdf",
"x": 1350,
"y": 860,
"wires": [["dbg_diff"]]
},
{
"id": "dbg_diff",
"type": "debug",
"z": "collab_tab",
"name": "diff destNcPath",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "destNcPath",
"x": 1570,
"y": 860,
"wires": []
},
{
"id": "inj_pick_demo",
"type": "inject",
"z": "collab_tab",
"name": "9. hitta exempelfil (pickDemoSource)",
"props": [],
"repeat": "",
"crontab": "",
"once": false,
"topic": "",
"x": 190,
"y": 960,
"wires": [["bridge_pick"]]
},
{
"id": "bridge_pick",
"type": "collabora-bridge",
"z": "collab_tab",
"name": "pickDemoSource",
"config": "nc_collab_cfg",
"operation": "pickDemoSource",
"x": 430,
"y": 960,
"wires": [["dbg_pick"]]
},
{
"id": "dbg_pick",
"type": "debug",
"z": "collab_tab",
"name": "kandidater + vald ncPath",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "picked",
"x": 670,
"y": 960,
"wires": []
}
]