Registro de reuniones

Avanzado

Este es unDocument Extraction, Multimodal AIflujo de automatización del dominio deautomatización que contiene 18 nodos.Utiliza principalmente nodos como Code, Merge, Webhook, MicrosoftExcel, MicrosoftOutlook. Automatización de la documentación de reuniones con SharePoint, Word, Excel y Outlook

Requisitos previos
  • Punto final de HTTP Webhook (n8n generará automáticamente)
Vista previa del flujo de trabajo
Visualización de las conexiones entre nodos, con soporte para zoom y panorámica
Exportar flujo de trabajo
Copie la siguiente configuración JSON en n8n para importar y usar este flujo de trabajo
{
  "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": "Combinar",
      "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": "Enviar un mensaje",
      "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": "Analizar Datos de la Reunión",
      "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": "Añadir datos a la hoja de Excel",
      "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": "Descargar plantilla de Word",
      "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": "Subir DOCX",
      "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": "Nota Adhesiva - Descripción General",
      "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": "Nota Adhesiva - Enviar un mensaje",
      "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": "Nota Adhesiva - Subir DOCX",
      "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": "Nota Adhesiva - 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": "Nota Adhesiva - Combinar",
      "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": "Nota Adhesiva - Añadir datos a la hoja de Excel",
      "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": "Nota Adhesiva - Analizar Datos de la Reunión",
      "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": "Nota Adhesiva - Descargar plantilla de Word",
      "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": "Nota Adhesiva - 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": "Nota Adhesiva",
      "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 &amp; 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
          }
        ]
      ]
    }
  }
}
Preguntas frecuentes

¿Cómo usar este flujo de trabajo?

Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.

¿En qué escenarios es adecuado este flujo de trabajo?

Avanzado - Extracción de documentos, IA Multimodal

¿Es de pago?

Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.

Información del flujo de trabajo
Nivel de dificultad
Avanzado
Número de nodos18
Categoría2
Tipos de nodos8
Descripción de la dificultad

Adecuado para usuarios avanzados, flujos de trabajo complejos con 16+ nodos

Autor
Wessel Bulte

Wessel Bulte

@uuessel

Cybersecurity and automation consultant specializing in n8n workflows for GDPR compliance, process optimization, and business integration. Helping teams streamline operations with secure, scalable automation solutions.

Enlaces externos
Ver en n8n.io

Compartir este flujo de trabajo

Categorías

Categorías: 34