8
n8n 한국어amn8n.com

회의 등록

고급

이것은Document Extraction, Multimodal AI분야의자동화 워크플로우로, 18개의 노드를 포함합니다.주로 Code, Merge, Webhook, MicrosoftExcel, MicrosoftOutlook 등의 노드를 사용하며. SharePoint, Word, Excel 및 Outlook을 사용한 자동화된 회의 문서 기록

사전 요구사항
  • HTTP Webhook 엔드포인트(n8n이 자동으로 생성)
워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
  "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": "병합",
      "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": "Send a message",
      "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": "Parse Meeting Data",
      "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": "Append data to excel sheet",
      "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": "Download word template",
      "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": "Upload 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": "메모 - Overview",
      "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": "메모 - Send a message",
      "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": "메모 - Upload 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": "메모 - 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": "Sticky Note - 병합",
      "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": "메모 - Append data to excel sheet",
      "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": "메모 - Parse Meeting Data",
      "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": "메모 - Download word template",
      "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": "Sticky Note - 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": "메모",
      "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": {
    "Merge": {
      "main": [
        [
          {
            "node": "7a38e270-ec62-4231-bd31-fee7b8836f74",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "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": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "209ad73a-c876-41e8-a21f-59a000840c7b": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
자주 묻는 질문

이 워크플로우를 어떻게 사용하나요?

위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.

이 워크플로우는 어떤 시나리오에 적합한가요?

고급 - 문서 추출, 멀티모달 AI

유료인가요?

이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.

워크플로우 정보
난이도
고급
노드 수18
카테고리2
노드 유형8
난이도 설명

고급 사용자를 위한 16+개 노드의 복잡한 워크플로우

저자
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.

외부 링크
n8n.io에서 보기

이 워크플로우 공유

카테고리

카테고리: 34