Konferenzanmeldung
Dies ist ein Document Extraction, Multimodal AI-Bereich Automatisierungsworkflow mit 18 Nodes. Hauptsächlich werden Code, Merge, Webhook, MicrosoftExcel, MicrosoftOutlook und andere Nodes verwendet. Automatisierung der Dokumentation von Besprechungen mit SharePoint, Word, Excel und Outlook
- •HTTP Webhook-Endpunkt (wird von n8n automatisch generiert)
Verwendete Nodes (18)
Kategorie
{
"id": "gn82CROXOk8D0PnF",
"meta": {
"instanceId": "89249a8a187ba6e01e16112a0d334a3aa01d510ad8f88d223e12cc0a2a8beb6b"
},
"name": "Meetings registration",
"tags": [],
"nodes": [
{
"id": "cd1f0b4f-94c5-41da-b80f-b83c3c61c8b4",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
-2032,
-16
],
"webhookId": "34aa798e-6c25-4cbd-bc04-10193438ad33",
"parameters": {
"path": "34ff798e-6c25-4cbd-bc04-10103438a111",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "6ba067bd-8be7-4742-9b32-771623780513",
"name": "Zusammenführen",
"type": "n8n-nodes-base.merge",
"position": [
-448,
-64
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineByPosition"
},
"typeVersion": 3.2
},
{
"id": "7a38e270-ec62-4231-bd31-fee7b8836f74",
"name": "DocxTemplater",
"type": "n8n-nodes-docxtemplater.docxTemplater",
"position": [
-64,
-64
],
"parameters": {
"context": "={{ $json }}",
"options": {
"outputFileName": "=meeting_{{$now.format(\"yyyy-MM-dd\")}}.docx"
}
},
"typeVersion": 1
},
{
"id": "e12dfc53-0c38-4261-854f-7561765c4c89",
"name": "Nachricht senden",
"type": "n8n-nodes-base.microsoftOutlook",
"position": [
736,
-208
],
"webhookId": "23406a8b-feb7-4324-8784-d7ba492e12ee",
"parameters": {
"subject": "Meeting summery ",
"additionalFields": {
"attachments": {
"attachments": [
{
"binaryPropertyName": "data"
}
]
}
}
},
"credentials": {},
"typeVersion": 2
},
{
"id": "0909e1b5-3278-491c-abae-db025a81b69f",
"name": "Besprechungsdaten parsen",
"type": "n8n-nodes-base.code",
"position": [
-1248,
64
],
"parameters": {
"jsCode": "// Extract and structure meeting minutes data from webhook\n// Parse the JSON body if it's a string, otherwise use the object directly\nlet inputData;\ntry {\n const rawInput = $input.first().json;\n \n // Check if body exists and is a string that needs parsing\n if (rawInput.body && typeof rawInput.body === 'string') {\n inputData = JSON.parse(rawInput.body);\n } else if (rawInput.body && typeof rawInput.body === 'object') {\n inputData = rawInput.body;\n } else {\n // Fall back to the raw input data\n inputData = rawInput;\n }\n} catch (error) {\n // If parsing fails, use the original data\n inputData = $input.first().json.body || $input.first().json;\n}\n\n// Basic meeting information\nconst meetingInfo = {\n date: inputData.date || '',\n time: inputData.time || '',\n location: inputData.location || '',\n submittedAt: inputData.submitted_at || '',\n userAgent: inputData.user_agent || ''\n};\n\n// Text cleaning function\nconst cleanText = (text) => {\n if (typeof text !== 'string') return text;\n return text\n .replace(/\\r\\n/g, ' ') // Replace Windows line breaks\n .replace(/\\n/g, ' ') // Replace line breaks\n .replace(/\\r/g, ' ') // Replace carriage returns \n .replace(/\\t/g, ' ') // Replace tabs\n .trim();\n};\n\n// Format participants with semicolon separators\nconst attendeesFormatted = inputData.attendees \n ? inputData.attendees.split('\\n')\n .map(name => name.trim())\n .filter(name => name.length > 0)\n .join(';')\n : '';\n\nconst absenteesFormatted = inputData.absentees \n ? inputData.absentees.split('\\n')\n .map(name => name.trim())\n .filter(name => name.length > 0)\n .join(';')\n : '';\n\n// Format discussion points with titles and comma separators\nconst discussionPointsFormatted = (inputData.dps || [])\n .filter(dp => dp.title || dp.decision || dp.notes)\n .map((dp, index) => {\n const parts = [];\n if (dp.title) parts.push(`Title: ${dp.title}`);\n if (dp.decision) parts.push(`Decision: ${dp.decision}`);\n if (dp.notes) parts.push(`Notes: ${dp.notes}`);\n return parts.join(', ');\n })\n .join(';');\n\n// Format action items with titles and comma separators\nconst actionItemsFormatted = (inputData.ais || [])\n .filter(ai => ai.action || ai.owner || ai.deadline)\n .map((ai, index) => {\n const parts = [];\n if (ai.action) parts.push(`Action: ${ai.action}`);\n if (ai.owner) parts.push(`Owner: ${ai.owner}`);\n if (ai.deadline) parts.push(`Deadline: ${ai.deadline}`);\n return parts.join(', ');\n })\n .join(';');\n\n// Statistics\nconst statistics = {\n totalAttendees: inputData.attendees ? inputData.attendees.split('\\n').filter(n => n.trim()).length : 0,\n totalAbsentees: inputData.absentees ? inputData.absentees.split('\\n').filter(n => n.trim()).length : 0,\n totalDiscussionPoints: (inputData.dps || []).filter(dp => dp.title || dp.decision || dp.notes).length,\n totalActionItems: (inputData.ais || []).filter(ai => ai.action || ai.owner || ai.deadline).length\n};\n\n// Add debug logging to help troubleshoot\nconsole.log('Input Data Keys:', Object.keys(inputData || {}));\nconsole.log('Attendees raw:', inputData.attendees);\nconsole.log('Discussion Points:', inputData.dps);\nconsole.log('Action Items:', inputData.ais);\n\n// Return formatted data with cleaned text\nreturn [{\n json: {\n // Basic info\n date: meetingInfo.date,\n time: meetingInfo.time,\n location: cleanText(meetingInfo.location),\n \n // Formatted participants (semicolon separated)\n attendees: attendeesFormatted,\n absentees: absenteesFormatted,\n \n // Meeting content (cleaned)\n opening: cleanText(inputData.opening || ''),\n aob: cleanText(inputData.aob || ''),\n closing: cleanText(inputData.closing || ''),\n \n // Formatted discussion points (semicolon separated, comma within each point)\n discussionPoints: discussionPointsFormatted,\n \n // Formatted action items (semicolon separated, comma within each item)\n actionItems: actionItemsFormatted,\n \n // Statistics\n statistics: statistics,\n \n // Metadata\n submittedAt: meetingInfo.submittedAt,\n userAgent: meetingInfo.userAgent,\n \n // Debug info (remove in production)\n _debug: {\n inputType: typeof inputData,\n hasBody: !!$input.first().json.body,\n bodyType: typeof $input.first().json.body,\n inputKeys: Object.keys(inputData || {})\n }\n }\n}];"
},
"typeVersion": 2
},
{
"id": "fdcd059e-b167-43d5-84ca-5a06652bff83",
"name": "Daten zu Excel-Tabelle hinzufügen",
"type": "n8n-nodes-base.microsoftExcel",
"position": [
-848,
176
],
"parameters": {
"options": {},
"fieldsUi": {
"values": [
{
"column": "Date",
"fieldValue": "={{ $json.date }}"
},
{
"column": "Time",
"fieldValue": "={{ $json.time }}"
},
{
"column": "Attendees",
"fieldValue": "={{ $json.attendees }}"
},
{
"column": "Absentees",
"fieldValue": "={{ $json.absentees }}"
},
{
"column": "Opening & Agenda Approval",
"fieldValue": "={{ $json.opening }}"
},
{
"column": "Discussion Points",
"fieldValue": "={{ $json.discussionPoints }}"
},
{
"column": " Action Items",
"fieldValue": "={{ $json.actionItems }}"
},
{
"column": "Any Other Business",
"fieldValue": "={{ $json.aob }}"
},
{
"column": " Closing",
"fieldValue": "={{ $json.closing }}"
},
{
"column": "Location",
"fieldValue": "={{ $json.location }}"
}
]
},
"resource": "worksheet",
"workbook": {
"__rl": true,
"mode": "list",
"value": "01VJX45VW77SMOI764LVBJPDS4VXR4SEMM",
"cachedResultName": "meeting"
},
"operation": "append",
"worksheet": {
"__rl": true,
"mode": "list",
"value": "{00000000-0001-0000-0000-000000000000}",
"cachedResultName": "Sheet1"
}
},
"credentials": {},
"typeVersion": 2.1
},
{
"id": "209ad73a-c876-41e8-a21f-59a000840c7b",
"name": "Word-Vorlage herunterladen",
"type": "n8n-nodes-base.microsoftSharePoint",
"position": [
-1648,
-128
],
"parameters": {
"file": {
"__rl": true,
"mode": "list",
"value": "01MT5H3G2HACJOUV2AV5B2HPMSUE5IEH73",
"cachedResultName": "meeting_minutes_template.docx"
},
"site": {
"__rl": true,
"mode": "list"
},
"folder": {
"__rl": true,
"mode": "list",
"value": "01MT5H3G7JU7CVVI34RFAJ56ZW5GCBKBGI",
"cachedResultName": "General"
},
"requestOptions": {}
},
"credentials": {},
"typeVersion": 1
},
{
"id": "39e407c6-0dec-4176-9669-42a95df24cec",
"name": "DOCX hochladen",
"type": "n8n-nodes-base.microsoftSharePoint",
"position": [
352,
48
],
"parameters": {
"site": {
"__rl": true,
"mode": "list"
},
"folder": {
"__rl": true,
"mode": "list",
"value": "01MT5H3G65QP3YC64BOVD37VQBTHMJQWHT",
"cachedResultName": "Meetings"
},
"fileName": "=meeting_{{$now.format(\"yyyy-MM-dd\")}}.docx",
"operation": "upload",
"fileContents": "data",
"requestOptions": {}
},
"credentials": {},
"typeVersion": 1
},
{
"id": "a903b4dc-7321-4fba-99f0-50d16604007d",
"name": "Haftnotiz - Übersicht",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2784,
-224
],
"parameters": {
"color": 3,
"width": 600,
"height": 812,
"content": "## The workflow will generate a well-structured documentation file based on your meeting data and send it via email while also logging the details in an Excel sheet for future reference.\n\n\n### How it works:\n- 🌐 **Webhook**: Triggers the workflow to start upon receiving data (e.g., meeting details).\n- 🔗 **Merge**: Combines data streams to create a comprehensive output.\n- 🖋️ **Parse Meeting Data**: Processes and structures the incoming meeting information.\n- 📄 **Download Word Template**: Retrieves a predefined DOCX template from SharePoint.\n- ✍️ **DocxTemplater**: Fills the template with parsed meeting data for final document creation.\n- 📤 **Upload DOCX**: Saves the generated document back to SharePoint.\n- 📊 **Append Data to Excel Sheet**: Records meeting details into an Excel file for tracking.\n- 📧 **Send a Message**: Sends the generated document via Microsoft Outlook to specified recipients.\n\n### Parameters to configure:\n- **Webhook URL**: Specify the endpoint that triggers the workflow.\n- **Template location**: Define SharePoint URL for the DOCX template.\n- **Email recipients**: List of email addresses to send the generated documentation.\n\n### Limitations / Gotchas:\n- Ensure that the webhook can handle the incoming format correctly; structure may vary.\n- The template must exist in the specified SharePoint location; otherwise, the workflow fails.\n- Excel updates may need permission adjustments for proper integration.\n- A very basic HTML form is include, dont forgert to change the webhook URL"
},
"typeVersion": 1
},
{
"id": "ea8ae3b8-8568-4e97-bccd-56ad4b360052",
"name": "Haftnotiz - Nachricht senden",
"type": "n8n-nodes-base.stickyNote",
"position": [
704,
336
],
"parameters": {
"color": 7,
"width": 380,
"height": 1020,
"content": "## 📩 Send a Message \n\n### 🎯 Purpose\nSend an email message via Microsoft Outlook with an optional attachment, effectively communicating meeting summaries or any other relevant information.\n\n### 🔄 Inputs / Outputs\n- **Inputs:** \n - Email subject: Defines the subject line of the email.\n - Attachments (optional): Files can be attached to the email using the specified binary property.\n- **Outputs:** \n - Confirmation of the sent message or error details if the sending fails.\n\n### ⚙️ Key Fields to Configure\n- **Subject:** \n - Define the subject of the email, e.g., \"Meeting summary\".\n- **Attachments:** \n - Include any files to be sent along with the message by specifying the binary property name (in this case, \"data\").\n\n### 📝 Tip / Validation\n- Ensure that the Microsoft Outlook credentials are properly configured to grant n8n the necessary permissions to send an email.\n- Verify that the attachment paths and properties are correctly defined and accessible to avoid errors during the email sending process."
},
"typeVersion": 1
},
{
"id": "92343917-0f4b-4f41-bfaf-14da21606e6a",
"name": "Haftnotiz - DOCX hochladen",
"type": "n8n-nodes-base.stickyNote",
"position": [
304,
336
],
"parameters": {
"color": 7,
"width": 380,
"height": 1020,
"content": "## 📁 Upload DOCX \n\n### 🎯 Purpose\nUpload a DOCX file to a specified SharePoint folder, automating the process of document storage for meetings.\n\n### 🔄 Inputs / Outputs\n- **Inputs:**\n - Site: SharePoint site where the document will be uploaded.\n - Folder: Target folder within the SharePoint site for the DOCX file.\n - File Name: Automatically generates a name for the file based on the current date.\n - File Contents: The content of the DOCX file to be uploaded.\n\n- **Outputs:**\n - Confirmation of the uploaded file along with metadata (e.g., file ID, upload status).\n\n### ⚙️ Key Fields to Configure\n- **Site:**\n - Set the SharePoint site value using the site URL and relevant identifiers.\n- **Folder:**\n - Define the specific folder ID within the site where the DOCX should be saved.\n- **File Name:**\n - Format as `=meeting_{{$now.format(\"yyyy-MM-dd\")}}.docx` to create a date-stamped meeting document.\n- **File Contents:**\n - Specify the data to be included in the DOCX file, currently referenced as `\"data\"`.\n\n### 📝 Tip / Validation\n- Ensure that the SharePoint credentials are correctly configured for authentication to avoid access issues.\n- Verify that the folder ID exists within the specified site to prevent upload errors.\n- Consider adding error handling in your workflow to capture any issues during the upload process."
},
"typeVersion": 1
},
{
"id": "0788528f-8bbf-453d-b05e-69a91838d859",
"name": "Haftnotiz - DocxTemplater",
"type": "n8n-nodes-base.stickyNote",
"position": [
-96,
336
],
"parameters": {
"color": 7,
"width": 380,
"height": 1020,
"content": "## 📄 DocxTemplater \n\n### 🎯 Purpose\nGenerate a DOCX file using a template and provided context data, streamlining documentation creation for workflows.\n\n### 🔄 Inputs / Outputs\n- **Inputs:** \n - Context data populated from the workflow JSON.\n- **Outputs:** \n - A generated DOCX file named `meeting_YYYY-MM-DD.docx`, where `YYYY-MM-DD` reflects the current date.\n\n### ⚙️ Key Fields to Configure\n- **Context:** \n - Set to `={{ $json }}` to utilize the current workflow data as the context for the template.\n- **Output File Name:** \n - Defined as `=meeting_{{$now.format(\"yyyy-MM-dd\")}}.docx` to automatically include today's date in the filename.\n\n### 📝 Tip / Validation\n- Ensure that the template used for the DOCX file is correctly structured to match the context data provided.\n- Confirm that the necessary permissions are in place for writing files to the desired output location."
},
"typeVersion": 1
},
{
"id": "811bc994-614d-43e6-85df-f81be08a6a2a",
"name": "Haftnotiz - Zusammenführen",
"type": "n8n-nodes-base.stickyNote",
"position": [
-496,
336
],
"parameters": {
"color": 7,
"width": 380,
"height": 1020,
"content": "## Merge \n\n### 🎯 Purpose\nCombine multiple data sets into a single output stream based on their positions.\n\n### 🔄 Inputs / Outputs\n- **Inputs:** \n - Multiple data sets to be merged.\n- **Outputs:** \n - A single unified data set containing all combined input data.\n\n### ⚙️ Key Fields to Configure\n- **Mode:** \n - Set to \"combine\" for merging data sets.\n- **Combine By:** \n - Select \"combineByPosition\" to merge based on the order of items in the input data sets.\n\n### 📝 Tip / Validation\n- Ensure that input data sets are structured consistently for effective merging; mismatched structures could lead to unpredictable results.\n- Utilize logging to monitor the output data after merging to verify that the process is working as intended."
},
"typeVersion": 1
},
{
"id": "8dde6bc4-a444-47e7-aaed-162e45321bbf",
"name": "Haftnotiz - Daten zu Excel-Tabelle hinzufügen",
"type": "n8n-nodes-base.stickyNote",
"position": [
-896,
336
],
"parameters": {
"color": 7,
"width": 380,
"height": 1020,
"content": "## 📁 Append Data to Excel Sheet \n\n### 🎯 Purpose\nAppend meeting data to a specified worksheet in an Excel workbook, facilitating organized documentation of workflow activities.\n\n### 🔄 Inputs / Outputs\n- **Inputs:** \n - Meeting details such as date, time, attendees, absentees, discussion points, and more.\n- **Outputs:** \n - Updated Excel sheet with new data appended to the designated worksheet.\n\n### ⚙️ Key Fields to Configure\n- **Resource:** \n - Select \"worksheet\" to specify the resource type.\n- **Operation:**\n - Set to \"append\" to add new data.\n- **Workbook:**\n - Provide the workbook ID\n- **Worksheet:**\n - Specify the worksheet ID.\n- **Fields Configuration:**\n - Map the following fields with their respective values:\n - **Date**: `={{ $json.date }}`\n - **Time**: `={{ $json.time }}`\n - **Attendees**: `={{ $json.attendees }}`\n - **Absentees**: `={{ $json.absentees }}`\n - **Opening & Agenda Approval**: `={{ $json.opening }}`\n - **Discussion Points**: `={{ $json.discussionPoints }}`\n - **Action Items**: `={{ $json.actionItems }}`\n - **Any Other Business**: `={{ $json.aob }}`\n - **Closing**: `={{ $json.closing }}`\n - **Location**: `={{ $json.location }}`\n\n### 📝 Tip / Validation\n- Ensure that the values for all fields are correctly populated from the preceding nodes in your workflow.\n- Validate that the specified workbook and worksheet are accessible and that you have permission to edit them.\n- Keep track of the Excel sheet's structure to avoid mismatches during data input (e.g., correct column headings)."
},
"typeVersion": 1
},
{
"id": "2c41fa1a-f564-4543-87ed-31107684336e",
"name": "Haftnotiz - Besprechungsdaten parsen",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1280,
336
],
"parameters": {
"color": 7,
"width": 380,
"height": 1020,
"content": "## 📁 Parse Meeting Data \n\n### 🎯 Purpose\nExtract, structure, and format meeting minutes data from webhook inputs for improved documentation and accessibility.\n\n### 🔄 Inputs / Outputs\n- **Inputs:** \n - Webhook data containing meeting details, attendees, absentees, discussion points, and action items.\n- **Outputs:** \n - Structured JSON object with cleaned and formatted meeting data ready for further processing or storing.\n\n### ⚙️ Key Fields to Configure\n- **Webhook Data:** \n - Ensure that the input JSON provides all necessary fields: `date`, `time`, `location`, `attendees`, `absentees`, `dps` (discussion points), `ais` (action items), `opening`, `aob`, and `closing`.\n\n### 📝 Tip / Gotchas\n- **Input Type Handling:** \n - The node checks if the incoming `body` is a string or object, and parses accordingly. Ensure the body format is consistent to avoid parsing errors.\n- **Text Cleaning:** \n - The node includes a text cleaning function that removes unwanted line breaks and tabs. Make sure your text format adheres to expected standards to get the best results.\n- **Debugging Information:** \n - The debug log outputs information about the input data structure; remove or comment out these log statements in production for cleaner execution.\n- **Empty Values:** \n - If any expected field is missing, fallback mechanisms will provide defaults (e.g., empty strings) to avoid errors in the output structure."
},
"typeVersion": 1
},
{
"id": "c60f3c7f-5721-4247-b94b-be219c26c6bf",
"name": "Haftnotiz - Word-Vorlage herunterladen",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1680,
336
],
"parameters": {
"color": 7,
"width": 380,
"height": 1020,
"content": "## 📄 Download Word Template \n\n### 🎯 Purpose\nDownload a specific Word template file from SharePoint to facilitate documentation tasks.\n\n### 🔄 Inputs / Outputs\n- **Inputs:** \n - SharePoint site, folder, and file identifiers for the Word template.\n- **Outputs:** \n - The downloaded Word template file, ready for use in your documentation workflow.\n\n### ⚙️ Key Fields to Configure\n- **Site:** \n - Enter the SharePoint site information \n \n- **Folder:** \n - Specify the folder ID where the template is located.\n \n- **File:** \n - Provide the ID of the Word template you wish to download.\n\n### 📝 Tip / Validation\n- Verify your SharePoint credentials and access permissions to ensure a successful download.\n- Double-check the provided IDs for site, folder, and file to avoid errors during the download process."
},
"typeVersion": 1
},
{
"id": "ccfef0b5-4ebf-4eb9-a973-fd0721c40375",
"name": "Haftnotiz - Webhook",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2080,
336
],
"parameters": {
"color": 7,
"width": 380,
"height": 1020,
"content": "## 🌐 Webhook \n\n### 🎯 Purpose\nFacilitates real-time interactions by receiving HTTP POST requests at a specified endpoint, allowing for seamless integration with external systems.\n\n### 🔄 Inputs / Outputs\n- **Inputs:** \n - Data sent via POST requests to the defined webhook.\n- **Outputs:** \n - Data received from the external system, which can be utilized in subsequent nodes in the workflow.\n\n### ⚙️ Key Fields to Configure\n- **HTTP Method:** \n - Set to `POST` to accept incoming requests.\n- **Path:** \n - Unique identifier that defines the endpoint for the webhook.\n\n### 📝 Tip / Validation\n- Ensure the webhook URL is properly exposed and accessible from external sources.\n- Test the webhook with tools like Postman to verify that it receives and processes incoming requests correctly."
},
"typeVersion": 1
},
{
"id": "7417b3a7-ccab-446d-b875-343fd2e76036",
"name": "Haftnotiz",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2784,
608
],
"parameters": {
"width": 640,
"height": 768,
"content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>Meetings (Minimal, n8n-compatible)</title>\n</head>\n<body>\n <h1>Meetings</h1>\n\n <form id=\"minutesForm\">\n <div>\n <label for=\"date\">Date:</label><br>\n <input id=\"date\" name=\"date\" type=\"date\">\n </div><br>\n\n <div>\n <label for=\"time\">Time:</label><br>\n <input id=\"time\" name=\"time\" type=\"time\">\n </div><br>\n\n <div>\n <label for=\"location\">Location:</label><br>\n <input id=\"location\" name=\"location\" type=\"text\">\n </div><br>\n\n <div>\n <label for=\"attendees\">Attendees (one per line):</label><br>\n <textarea id=\"attendees\" name=\"attendees\" rows=\"4\" cols=\"60\"></textarea>\n </div><br>\n\n <div>\n <label for=\"absentees\">Absentees (optional):</label><br>\n <textarea id=\"absentees\" name=\"absentees\" rows=\"3\" cols=\"60\"></textarea>\n </div><br>\n\n <div>\n <label for=\"opening\">1) Opening & Agenda Approval:</label><br>\n <textarea id=\"opening\" name=\"opening\" rows=\"3\" cols=\"60\"></textarea>\n </div><br>\n\n <fieldset id=\"discussionList\">\n <legend>2) Discussion Points</legend>\n <!-- One starter discussion point -->\n <div class=\"dp\">\n <label>Title<br><input type=\"text\" class=\"dp-title\"></label><br>\n <label>Decision(s)<br><input type=\"text\" class=\"dp-decision\"></label><br>\n <label>Summary / Arguments<br><textarea class=\"dp-notes\" rows=\"3\" cols=\"60\"></textarea></label><br>\n <button type=\"button\" class=\"dp-remove\">Remove</button>\n </div>\n </fieldset>\n <button type=\"button\" id=\"addDiscussion\">+ Add discussion point</button>\n <br><br>\n\n <fieldset>\n <legend>3) Action Items</legend>\n <table id=\"actionTable\" border=\"1\" cellpadding=\"6\">\n <thead>\n <tr><th>Action</th><th>Responsible</th><th>Deadline</th><th>Remove</th></tr>\n </thead>\n <tbody>\n <tr>\n <td><input type=\"text\" class=\"ai-action\"></td>\n <td><input type=\"text\" class=\"ai-owner\"></td>\n <td><input type=\"date\" class=\"ai-date\"></td>\n <td><button type=\"button\" class=\"ai-remove\">×</button></td>\n </tr>\n </tbody>\n </table>\n <button type=\"button\" id=\"addAction\">+ Add action</button>\n </fieldset>\n <br>\n\n <div>\n <label for=\"aob\">4) Any Other Business:</label><br>\n <textarea id=\"aob\" name=\"aob\" rows=\"3\" cols=\"60\"></textarea>\n </div><br>\n\n <div>\n <label for=\"closing\">5) Closing:</label><br>\n <textarea id=\"closing\" name=\"closing\" rows=\"3\" cols=\"60\"></textarea>\n </div><br>\n\n <button type=\"button\" id=\"sendN8N\">Send to n8n</button>\n <span id=\"sendStatus\"></span>\n </form>\n\n <template id=\"dpTpl\">\n <div class=\"dp\">\n <label>Title<br><input type=\"text\" class=\"dp-title\"></label><br>\n <label>Decision(s)<br><input type=\"text\" class=\"dp-decision\"></label><br>\n <label>Summary / Arguments<br><textarea class=\"dp-notes\" rows=\"3\" cols=\"60\"></textarea></label><br>\n <button type=\"button\" class=\"dp-remove\">Remove</button>\n </div>\n </template>\n\n <script>\n // Minimal helpers\n const $ = (q, el=document) => el.querySelector(q);\n const $$ = (q, el=document) => Array.from(el.querySelectorAll(q));\n\n const discussionList = $('#discussionList');\n const actionTableBody = $('#actionTable tbody');\n const statusEl = $('#sendStatus');\n\n // Add/remove discussion blocks\n $('#addDiscussion').addEventListener('click', () => {\n const tpl = document.importNode($('#dpTpl').content, true);\n tpl.querySelector('.dp-remove').addEventListener('click', (e) => {\n e.target.closest('.dp').remove();\n });\n discussionList.appendChild(tpl);\n });\n // Wire starter remove button\n $('.dp-remove').addEventListener('click', (e) => e.target.closest('.dp').remove());\n\n // Add/remove action rows\n $('#addAction').addEventListener('click', () => {\n const tr = document.createElement('tr');\n tr.innerHTML = `\n <td><input type=\"text\" class=\"ai-action\"></td>\n <td><input type=\"text\" class=\"ai-owner\"></td>\n <td><input type=\"date\" class=\"ai-date\"></td>\n <td><button type=\"button\" class=\"ai-remove\">×</button></td>\n `;\n tr.querySelector('.ai-remove').addEventListener('click', () => tr.remove());\n actionTableBody.appendChild(tr);\n });\n // Wire starter remove button\n $('.ai-remove').addEventListener('click', (e) => e.target.closest('tr').remove());\n\n // Serialize to the SAME structure as the original working version\n function serialize() {\n return {\n date: $('#date').value || '',\n time: $('#time').value || '',\n location: $('#location').value || '',\n attendees: $('#attendees').value || '',\n absentees: $('#absentees').value || '',\n opening: $('#opening').value || '',\n aob: $('#aob').value || '',\n closing: $('#closing').value || '',\n dps: $$('#discussionList .dp').map(d => ({\n title: $('.dp-title', d).value || '',\n decision: $('.dp-decision', d).value || '',\n notes: $('.dp-notes', d).value || '',\n })),\n ais: $$('#actionTable tbody tr').map(tr => ({\n action: $('.ai-action', tr).value || '',\n owner: $('.ai-owner', tr).value || '',\n deadline: $('.ai-date', tr).value || '',\n })),\n };\n }\n\n // N8N Settings\n const WEBHOOK_URL = 'https://n8n.webhook_replace with youre own';\n async function sendToN8N() {\n statusEl.textContent = 'Sending…';\n try {\n const payload = serialize();\n payload.user_agent = navigator.userAgent;\n payload.submitted_at = new Date().toISOString();\n\n const res = await fetch(WEBHOOK_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'text/plain' },\n body: JSON.stringify(payload)\n });\n const text = await res.text().catch(() => '');\n if (!res.ok) throw new Error('HTTP ' + res.status + ': ' + text.slice(0,200));\n statusEl.textContent = 'Sent ✓';\n } catch (err) {\n statusEl.textContent = 'Failed: ' + (err && err.message ? err.message : err);\n }\n }\n\n $('#sendN8N').addEventListener('click', sendToN8N);\n </script>\n</body>\n</html>\n\n"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "c9f9d45c-cc23-4bab-879e-15192721d783",
"connections": {
"6ba067bd-8be7-4742-9b32-771623780513": {
"main": [
[
{
"node": "7a38e270-ec62-4231-bd31-fee7b8836f74",
"type": "main",
"index": 0
}
]
]
},
"cd1f0b4f-94c5-41da-b80f-b83c3c61c8b4": {
"main": [
[
{
"node": "0909e1b5-3278-491c-abae-db025a81b69f",
"type": "main",
"index": 0
},
{
"node": "209ad73a-c876-41e8-a21f-59a000840c7b",
"type": "main",
"index": 0
}
]
]
},
"7a38e270-ec62-4231-bd31-fee7b8836f74": {
"main": [
[
{
"node": "39e407c6-0dec-4176-9669-42a95df24cec",
"type": "main",
"index": 0
},
{
"node": "e12dfc53-0c38-4261-854f-7561765c4c89",
"type": "main",
"index": 0
}
]
]
},
"0909e1b5-3278-491c-abae-db025a81b69f": {
"main": [
[
{
"node": "fdcd059e-b167-43d5-84ca-5a06652bff83",
"type": "main",
"index": 0
},
{
"node": "6ba067bd-8be7-4742-9b32-771623780513",
"type": "main",
"index": 1
}
]
]
},
"209ad73a-c876-41e8-a21f-59a000840c7b": {
"main": [
[
{
"node": "6ba067bd-8be7-4742-9b32-771623780513",
"type": "main",
"index": 0
}
]
]
}
}
}Wie verwende ich diesen Workflow?
Kopieren Sie den obigen JSON-Code, erstellen Sie einen neuen Workflow in Ihrer n8n-Instanz und wählen Sie "Aus JSON importieren". Fügen Sie die Konfiguration ein und passen Sie die Anmeldedaten nach Bedarf an.
Für welche Szenarien ist dieser Workflow geeignet?
Experte - Dokumentenextraktion, Multimodales KI
Ist es kostenpflichtig?
Dieser Workflow ist völlig kostenlos. Beachten Sie jedoch, dass Drittanbieterdienste (wie OpenAI API), die im Workflow verwendet werden, möglicherweise kostenpflichtig sind.
Verwandte Workflows
Wessel Bulte
@uuesselCybersecurity and automation consultant specializing in n8n workflows for GDPR compliance, process optimization, and business integration. Helping teams streamline operations with secure, scalable automation solutions.
Diesen Workflow teilen