diff --git a/_reference/commission-based-cut-manual-test-plan.md b/_reference/commission-based-cut-manual-test-plan.md new file mode 100644 index 000000000..df94cc3f4 --- /dev/null +++ b/_reference/commission-based-cut-manual-test-plan.md @@ -0,0 +1,424 @@ +# Commission-Based Cut Feature Manual Test Plan + +## Purpose +Use this guide to manually test the commission-based cut feature from an end-user point of view. + +This plan is written for a non-technical tester. Follow the steps exactly as written and mark each scenario as Pass or Fail. + +## What You Need Before You Start +- A login that can open `Manage my Shop`, `Jobs`, and `Time Tickets`. +- At least 2 active employees in the shop. +- At least 1 converted repair order that already has labor lines on it. +- If possible, use a simple test job where the labor sale rates are easy to calculate. +- A notebook, spreadsheet, or screenshot folder to record what happened. + +## Recommended Easy-Math Test Data +If you can choose your own test job, use something simple like this: + +- Body sale rate: `$100.00` +- Refinish sale rate: `$120.00` +- Mechanical sale rate: `$80.00` +- 1 Body labor line with `10.0` hours +- 1 Refinish labor line with `4.0` hours + +This makes the expected payout easy to check: + +- `40%` of `$100.00` = `$40.00` +- `30%` of `$120.00` = `$36.00` + +## Important Navigation Notes +- Team setup is under `Manage my Shop` > `Employee Teams`. +- Team assignment happens on the job line grid in the `Team` column. +- Automatic payout happens from the job's `Labor Allocations` card using the `Pay All` button. +- If your shop uses task presets, the `Flag Hours` button can preview the payout method before committing tickets. + +--- + +## Scenario 1: Create a Simple Commission Team +### Goal +Confirm a team member can be set to commission and saved successfully. + +### Steps +1. Sign in. +2. Click `Manage my Shop`. +3. Click the `Employee Teams` tab. +4. Click `New Team`. +5. In `Team Name`, type `Commission Team Test`. +6. Make sure `Active` is turned on. +7. In `Max Load`, enter `10`. +8. Click `New Team Member`. +9. In `Employee`, choose an active employee. +10. In `Allocation %`, enter `100`. +11. In `Payout Method`, choose `Commission %`. +12. In each commission field that appears, enter a value. +13. For the main labor types you plan to test, use these values: +14. Enter `40` for Body. +15. Enter `30` for Refinish. +16. Enter `25` for Mechanical. +17. Enter `20` for Frame. +18. Enter `15` for Glass. +19. Fill in the remaining commission boxes with any valid number from `0` to `100`. +20. Click `Save`. + +### Expected Result +- The team saves successfully. +- The team stays visible in the Employee Teams list. +- The team member card shows a `Commission` tag. +- The `Allocation Total` shows `100%`. + +### Record +- [ ] Pass +- [ ] Fail +- Notes: + +--- + +## Scenario 2: Allocation Total Must Equal 100% +### Goal +Confirm the system blocks a team that does not total exactly 100%. + +### Steps +1. Stay on the same team. +2. Change `Allocation %` from `100` to `90`. +3. Click `Save`. +4. Change `Allocation %` from `90` to `110`. +5. Click `Save`. +6. Change `Allocation %` back to `100`. +7. Click `Save` again. + +### Expected Result +- When the total is `90%`, the system should not save. +- When the total is `110%`, the system should not save. +- The page should show that the allocation total is not correct. +- When the total is set back to `100%`, the save should succeed. + +### Record +- [ ] Pass +- [ ] Fail +- Notes: + +--- + +## Scenario 3: The Same Employee Cannot Be Added Twice +### Goal +Confirm the same employee cannot appear twice on one team. + +### Steps +1. Open the same team again. +2. Click `New Team Member`. +3. Choose the same employee already used on the team. +4. Enter any valid allocation amount. +5. Choose `Commission %`. +6. Fill in all required commission fields. +7. Click `Save`. + +### Expected Result +- The system should block the save. +- The team should not save with the same employee listed twice. + +### Record +- [ ] Pass +- [ ] Fail +- Notes: + +--- + +## Scenario 4: Switching Between Hourly and Commission Changes the Input Style +### Goal +Confirm the rate section changes correctly when the payout method changes. + +### Steps +1. Open the same team again. +2. On the team member row, change `Payout Method` from `Commission %` to `Hourly`. +3. Look at the rate fields that appear. +4. Change `Payout Method` back to `Commission %`. +5. Look at the rate fields again. + +### Expected Result +- In `Hourly` mode, the rate boxes should behave like money/rate fields. +- In `Commission %` mode, the rate boxes should behave like percentage fields. +- The screen should clearly show you are editing the correct type of value. + +### Record +- [ ] Pass +- [ ] Fail +- Notes: + +--- + +## Scenario 5: Boundary Values for Commission % +### Goal +Confirm the feature accepts valid boundary values and blocks invalid ones. + +### Steps +1. Open the team again. +2. In one commission box, enter `0`. +3. In another commission box, enter `100`. +4. Click `Save`. +5. Try to type a value above `100` in one of the commission boxes. +6. Try to type a negative value in one of the commission boxes. + +### Expected Result +- `0` should be accepted. +- `100` should be accepted. +- Values above `100` should not be allowed or should fail validation. +- Negative values should not be allowed or should fail validation. + +### Record +- [ ] Pass +- [ ] Fail +- Notes: + +--- + +## Scenario 6: Inactive Teams Should Not Be Offered for New Assignment +### Goal +Confirm inactive teams do not appear as normal team choices. + +### Steps +1. Open the team again. +2. Turn `Active` off. +3. Click `Save`. +4. Open a converted repair order. +5. Go to the job lines area where the `Team` column is visible. +6. Click inside the `Team` field on any labor line. +7. Open the team drop-down list. +8. Look for `Commission Team Test`. +9. Go back to `Manage my Shop` > `Employee Teams`. +10. Turn `Active` back on. +11. Click `Save`. +12. Return to the same job line and open the `Team` drop-down again. + +### Expected Result +- When the team is inactive, it should not appear as a normal assignment choice. +- After turning it back on, it should appear again. + +### Record +- [ ] Pass +- [ ] Fail +- Notes: + +--- + +## Scenario 7: Assign the Commission Team to a Labor Line +### Goal +Confirm the team can be assigned to a job line from the job screen. + +### Steps +1. Open a converted repair order that has labor lines. +2. Find a labor line in the job line grid. +3. In the `Team` column, click the blank area or the current team name. +4. From the drop-down list, choose `Commission Team Test`. +5. Click outside the field so it saves. +6. Repeat for at least 1 Body line and 1 Refinish line if both exist. + +### Expected Result +- The selected team name should appear in the `Team` column. +- The assignment should stay in place after the screen refreshes. + +### Record +- [ ] Pass +- [ ] Fail +- Notes: + +--- + +## Scenario 8: Pay All Creates Commission-Based Tickets +### Goal +Confirm `Pay All` creates time tickets using the commission rate, not a flat hourly rate. + +### Steps +1. Use a converted repair order that has: +2. At least 1 labor line assigned to `Commission Team Test`. +3. Known labor sale rates on the job. +4. No existing time tickets for the same employee and labor type. +5. Open that repair order. +6. Go to the labor/payroll area where the `Labor Allocations` card is visible. +7. Write down the following before you click anything: +8. The labor type on the line. +9. The sold labor rate for that labor type. +10. The hours on that line. +11. The commission % you entered for that labor type on the team. +12. Click `Pay All`. +13. Wait for the success message. +14. Look at the `Time Tickets` list on the same screen. +15. Find the new ticket created for that employee. + +### Expected Result +- The system should show `All hours paid out successfully.` +- A new time ticket should appear. +- The ticket rate should equal: +- `sale rate x commission %` +- Example: if Body sale rate is `$100.00` and commission is `40%`, the ticket rate should be `$40.00`. +- The productive hours should match the assigned labor hours for that employee. + +### Record +- [ ] Pass +- [ ] Fail +- Notes: + +--- + +## Scenario 9: Different Labor Types Use Different Commission Rates +### Goal +Confirm the feature uses the correct commission % for each labor type. + +### Steps +1. Use a job that has at least: +2. One Body labor line. +3. One Refinish labor line. +4. Make sure both lines are assigned to `Commission Team Test`. +5. Confirm your team is set up like this: +6. Body = `40%` +7. Refinish = `30%` +8. Open the job's `Labor Allocations` area. +9. Click `Pay All`. +10. Review the new time tickets that are created. + +### Expected Result +- The Body ticket should use the Body commission %. +- The Refinish ticket should use the Refinish commission %. +- Example: +- If Body sale rate is `$100.00`, Body payout rate should be `$40.00`. +- If Refinish sale rate is `$120.00`, Refinish payout rate should be `$36.00`. + +### Record +- [ ] Pass +- [ ] Fail +- Notes: + +--- + +## Scenario 10: Mixed Team With Commission and Hourly Members +### Goal +Confirm one team can contain both commission and hourly members, and each person is paid correctly. + +### Steps +1. Open `Manage my Shop` > `Employee Teams`. +2. Open `Commission Team Test`. +3. Edit the first team member: +4. Keep Employee 1 as `Commission %`. +5. Change `Allocation %` to `60`. +6. Make sure Body commission is still `40`. +7. Add a second team member. +8. Choose a different active employee. +9. Set `Allocation %` to `40`. +10. Set `Payout Method` to `Hourly`. +11. Enter an hourly rate for each required labor type. +12. For Body, use `$25.00`. +13. Fill in the other required hourly boxes with valid values. +14. Make sure the total allocation shows `100%`. +15. Click `Save`. +16. Assign this team to a Body line with `10.0` hours. +17. Click `Pay All`. +18. Review the new time tickets. + +### Expected Result +- Employee 1 should receive `60%` of the hours at the commission-derived rate. +- Employee 2 should receive `40%` of the hours at the hourly rate you entered. +- Example with a 10-hour Body line and `$100.00` sale rate: +- Employee 1 should get `6.0` hours at `$40.00`. +- Employee 2 should get `4.0` hours at `$25.00`. + +### Record +- [ ] Pass +- [ ] Fail +- Notes: + +--- + +## Scenario 11: Pay All Only Adds the Remaining Hours +### Goal +Confirm `Pay All` does not duplicate hours that were already paid. + +### Steps +1. Use a job with one Body line assigned to `Commission Team Test`. +2. Make sure the line has `10.0` hours. +3. In the `Time Tickets` card, click `Enter New Time Ticket`. +4. Create a manual time ticket for the same employee and the same labor type. +5. Enter `4.0` productive hours. +6. Save the manual time ticket. +7. Go back to the `Labor Allocations` card. +8. Click `Pay All`. +9. Review the new ticket that is created. + +### Expected Result +- The system should only create the remaining unpaid hours. +- In this example, it should add `6.0` hours, not `10.0`. +- The payout rate should still use the current commission-based rate. + +### Record +- [ ] Pass +- [ ] Fail +- Notes: + +--- + +## Scenario 12: Unassigned Labor Lines Should Block Automatic Payout +### Goal +Confirm `Pay All` does not silently pay lines that do not have a team assigned. + +### Steps +1. Open a converted repair order with at least 2 labor lines. +2. Assign `Commission Team Test` to one line. +3. Leave the second labor line with no team assigned. +4. Go to the `Labor Allocations` card. +5. Click `Pay All`. + +### Expected Result +- The system should not quietly pay everything. +- You should see an error telling you that not all hours have been assigned. +- The unassigned line should still need manual attention. + +### Record +- [ ] Pass +- [ ] Fail +- Notes: + +--- + +## Scenario 13: Flag Hours Preview Shows the Correct Payout Method +### Goal +If your shop uses task presets, confirm the preview shows `Commission` for commission-based tickets. + +### Steps +1. Open a converted repair order. +2. Go to the `Time Tickets` card. +3. Click `Flag Hours`. +4. Choose a task preset. +5. Wait for the preview table to load. +6. Review the `Payout Method` column in the preview. +7. If the preview includes more than one employee, review each row. + +### Expected Result +- The preview table should load without error. +- Rows for commission-based employees should show `Commission`. +- Rows for hourly employees should show `Hourly`. +- If there are unassigned hours, a warning should appear. + +### Record +- [ ] Pass +- [ ] Fail +- Notes: + +--- + +## Quick Regression Checklist +- [ ] I can create a commission-based team. +- [ ] Allocation must total exactly 100%. +- [ ] The same employee cannot be added twice to one team. +- [ ] Inactive teams do not appear for normal assignment. +- [ ] A team can be assigned to job lines from the `Team` column. +- [ ] `Pay All` creates commission-based tickets correctly. +- [ ] Different labor types use different commission percentages. +- [ ] Mixed commission and hourly teams calculate correctly. +- [ ] `Pay All` only creates the remaining unpaid hours. +- [ ] Unassigned labor lines stop automatic payout. +- [ ] `Flag Hours` preview shows the correct payout method. + +## Tester Sign-Off +- Tester name: +- Test date: +- Environment: +- Overall result: +- Follow-up issues found: diff --git a/_reference/localEmailViewer/README.md b/_reference/localEmailViewer/README.md index 3f8a6fc71..6054686fd 100644 --- a/_reference/localEmailViewer/README.md +++ b/_reference/localEmailViewer/README.md @@ -1,7 +1,33 @@ -This will connect to your dockers local stack session and render the email in HTML. +This app connects to your Docker LocalStack SES endpoint and gives you a local inbox-style viewer +for generated emails. + +```shell +npm start +``` + +Or: ```shell node index.js ``` -http://localhost:3334 +Open: http://localhost:3334 + +Features: + +- Manual refresh +- Live refresh with adjustable polling interval +- Search across subject, addresses, preview text, and attachment names +- Expand/collapse all messages +- Rendered HTML, plain-text, and raw MIME views +- Copy raw MIME source +- New-message highlighting plus fetch timing and parse-error stats + +Optional environment variables: + +```shell +PORT=3334 +SES_VIEWER_ENDPOINT=http://localhost:4566/_aws/ses +SES_VIEWER_REFRESH_MS=10000 +SES_VIEWER_FETCH_TIMEOUT_MS=5000 +``` diff --git a/_reference/localEmailViewer/index.js b/_reference/localEmailViewer/index.js index 1dd17f779..15b7736a9 100644 --- a/_reference/localEmailViewer/index.js +++ b/_reference/localEmailViewer/index.js @@ -1,96 +1,1011 @@ -// index.js - import express from "express"; import fetch from "node-fetch"; import { simpleParser } from "mailparser"; const app = express(); -const PORT = 3334; -app.get("/", async (req, res) => { +const PORT = Number(process.env.PORT || 3334); +const SES_ENDPOINT = process.env.SES_VIEWER_ENDPOINT || "http://localhost:4566/_aws/ses"; +const FETCH_TIMEOUT_MS = Number(process.env.SES_VIEWER_FETCH_TIMEOUT_MS || 5000); +const DEFAULT_REFRESH_MS = Number(process.env.SES_VIEWER_REFRESH_MS || 10000); + +app.use((req, res, next) => { + res.set("Cache-Control", "no-store"); + next(); +}); + +app.get("/", (req, res) => { + res.type("html").send(renderHtml()); +}); + +app.get("/app.js", (req, res) => { + res.type("application/javascript").send(`(${clientApp.toString()})(${JSON.stringify(getClientConfig())});`); +}); + +app.get("/health", (req, res) => { + res.json({ + ok: true, + endpoint: SES_ENDPOINT, + port: PORT, + defaultRefreshMs: DEFAULT_REFRESH_MS + }); +}); + +app.get("/api/messages", async (req, res) => { try { - const response = await fetch("http://localhost:4566/_aws/ses"); - if (!response.ok) { - throw new Error("Network response was not ok"); - } - const data = await response.json(); - const messagesHtml = await parseMessages(data.messages); - res.send(renderHtml(messagesHtml)); + res.json(await loadMessages()); } catch (error) { console.error("Error fetching messages:", error); - res.status(500).send("Error fetching messages"); + res.status(502).json({ + error: "Unable to fetch messages from LocalStack SES", + details: error.message, + endpoint: SES_ENDPOINT + }); } }); -async function parseMessages(messages) { - const parsedMessages = await Promise.all( - messages.map(async (message, index) => { - try { - const parsed = await simpleParser(message.RawData); - return ` -
-
-
Message ${index + 1}
-
From: ${message.Source}
-
To: ${parsed.to.text || "No To Address"}
-
Subject: ${parsed.subject || "No Subject"}
-
Region: ${message.Region}
-
Timestamp: ${message.Timestamp}
-
-
${parsed.html || parsed.textAsHtml || "No HTML content available"}
-
- `; - } catch (error) { - console.error("Error parsing email:", error); - return ` -
-
Message ${index + 1}
-
From: ${message.Source}
-
Region: ${message.Region}
-
Timestamp: ${message.Timestamp}
-
Error parsing email content
-
- `; - } - }) - ); - return parsedMessages.join(""); +app.get("/api/messages/:id/raw", async (req, res) => { + try { + const messages = await fetchSesMessages(); + const message = messages.find((candidate) => resolveMessageId(candidate) === req.params.id); + + if (!message) { + res.status(404).type("text/plain").send("Message not found"); + return; + } + + res.type("text/plain").send(message.RawData || ""); + } catch (error) { + console.error("Error fetching raw message:", error); + res.status(502).type("text/plain").send(`Unable to fetch raw message: ${error.message}`); + } +}); + +async function loadMessages() { + const startedAt = Date.now(); + const sesMessages = await fetchSesMessages(); + const messages = await Promise.all(sesMessages.map((message, index) => toMessageViewModel(message, index))); + + messages.sort((left, right) => { + if ((right.timestampMs || 0) !== (left.timestampMs || 0)) { + return (right.timestampMs || 0) - (left.timestampMs || 0); + } + + return right.index - left.index; + }); + + return { + endpoint: SES_ENDPOINT, + fetchedAt: new Date().toISOString(), + fetchDurationMs: Date.now() - startedAt, + totalMessages: messages.length, + parseErrors: messages.filter((message) => Boolean(message.parseError)).length, + latestMessageTimestamp: messages[0]?.timestamp || "", + messages + }; } -function renderHtml(messagesHtml) { - return ` - - - - - - Email Messages Viewer - - - - -
-

Email Messages Viewer

-
${messagesHtml}
+async function fetchSesMessages() { + const response = await fetch(SES_ENDPOINT, { + signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) + }); + + if (!response.ok) { + throw new Error(`SES endpoint responded with ${response.status}`); + } + + const data = await response.json(); + return Array.isArray(data.messages) ? data.messages : []; +} + +async function toMessageViewModel(message, index) { + const id = resolveMessageId(message, index); + + try { + const parsed = await simpleParser(message.RawData || ""); + const textContent = normalizeText(parsed.text || ""); + const renderedHtml = buildRenderedHtml(parsed.html || parsed.textAsHtml || ""); + const timestamp = normalizeTimestamp(message.Timestamp || parsed.date); + + return { + id, + index, + from: formatAddressList(parsed.from) || message.Source || "Unknown sender", + to: formatAddressList(parsed.to) || "No To Address", + replyTo: formatAddressList(parsed.replyTo), + subject: parsed.subject || "No Subject", + region: message.Region || "", + timestamp, + timestampMs: timestamp ? Date.parse(timestamp) : 0, + messageId: parsed.messageId || "", + rawSizeBytes: Buffer.byteLength(message.RawData || "", "utf8"), + attachmentCount: parsed.attachments.length, + attachments: parsed.attachments.map((attachment) => ({ + filename: attachment.filename || "Unnamed attachment", + contentType: attachment.contentType || "application/octet-stream", + size: attachment.size || 0 + })), + preview: buildPreview(textContent, renderedHtml), + textContent, + renderedHtml, + hasHtml: Boolean(renderedHtml), + parseError: "" + }; + } catch (error) { + return { + id, + index, + from: message.Source || "Unknown sender", + to: "Unknown recipient", + replyTo: "", + subject: "Unable to parse message", + region: message.Region || "", + timestamp: normalizeTimestamp(message.Timestamp), + timestampMs: message.Timestamp ? Date.parse(message.Timestamp) : 0, + messageId: "", + rawSizeBytes: Buffer.byteLength(message.RawData || "", "utf8"), + attachmentCount: 0, + attachments: [], + preview: "This message could not be parsed. Open the raw view to inspect the MIME source.", + textContent: "", + renderedHtml: "", + hasHtml: false, + parseError: error.message + }; + } +} + +function resolveMessageId(message, index = 0) { + return message.Id || `${message.Timestamp || "unknown"}-${message.Source || "unknown"}-${index}`; +} + +function normalizeTimestamp(value) { + if (!value) { + return ""; + } + + const date = value instanceof Date ? value : new Date(value); + return Number.isNaN(date.getTime()) ? "" : date.toISOString(); +} + +function normalizeText(value) { + return String(value || "") + .replace(/\r\n/g, "\n") + .trim(); +} + +function buildPreview(textContent, renderedHtml) { + const source = (textContent || stripTags(renderedHtml)).replace(/\s+/g, " ").trim(); + + if (!source) { + return "No message preview available."; + } + + return source.length > 220 ? `${source.slice(0, 217)}...` : source; +} + +function buildRenderedHtml(html) { + if (!html) { + return ""; + } + + const value = String(html); + const hasDocument = /]/i.test(value) || / + + + + + + + + ${value} +`; +} + +function stripTags(value) { + return String(value || "") + .replace(//gi, " ") + .replace(//gi, " ") + .replace(/<[^>]+>/g, " "); +} + +function formatAddressList(addresses) { + if (!addresses?.value?.length) { + return ""; + } + + return addresses.value + .map(({ name, address }) => { + if (name && address) { + return `${name} <${address}>`; + } + + return address || name || ""; + }) + .filter(Boolean) + .join(", "); +} + +function getClientConfig() { + return { + defaultRefreshMs: DEFAULT_REFRESH_MS, + endpoint: SES_ENDPOINT + }; +} + +function renderHtml() { + return ` + + + + + LocalStack Email Viewer + + + +
+
+
+

LocalStack SES

+

Email Viewer

+

A faster local inbox for generated emails with live refresh, manual refresh, search, and raw MIME inspection.

- - +
+
+ + + +
+
+ + +
+
+ + + Waiting for first refresh... +
+
+
+ +
+
Total00 visible
+
New0New since last refresh
+
NewestNo messagesNot refreshed yet
+
FetchIdleEndpoint: ${escapeHtml(SES_ENDPOINT)}
+
+ + + +
+
+ + + +`; +} + +function renderStyles() { + return ` + :root{--panel:rgba(255,255,255,.86);--panel-strong:#fff;--ink:#1f2933;--muted:#607080;--line:rgba(31,41,51,.12);--accent:#cf6d3c;--ok:#1f8f65;--warn:#9d5f00;--bad:#b33a3a;--shadow:0 18px 48px rgba(35,43,53,.12);} + *{box-sizing:border-box} + html,body{margin:0;min-height:100%} + body{background:radial-gradient(circle at top left,rgba(207,109,60,.18),transparent 28%),radial-gradient(circle at top right,rgba(31,143,101,.14),transparent 24%),linear-gradient(180deg,#f8f5ef,#efe7da);color:var(--ink);font:16px/1.5 "Aptos","Segoe UI Variable Display","Segoe UI",system-ui,sans-serif} + button,input,select,textarea{font:inherit} + button{cursor:pointer} + .page{max-width:1440px;margin:0 auto;padding:24px} + .hero{display:grid;grid-template-columns:minmax(0,1.1fr) minmax(320px,.9fr);gap:24px;margin-bottom:24px} + .hero-copy,.hero-controls,.stat,.card{background:var(--panel);backdrop-filter:blur(16px);border:1px solid var(--line);box-shadow:var(--shadow)} + .hero-copy,.hero-controls{border-radius:24px;padding:24px} + .eyebrow{margin:0 0 8px;color:var(--accent);font-size:.8rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase} + h1{margin:0;font-size:clamp(2.2rem,5vw,4rem);line-height:.95;letter-spacing:-.05em} + .lede{margin:16px 0 0;max-width:60ch;color:var(--muted)} + .hero-controls{display:grid;gap:12px} + .row{display:flex;flex-wrap:wrap;gap:12px;align-items:center} + .primary,.ghost,.mini,.tab{border-radius:999px;border:1px solid transparent;transition:transform .12s ease,background-color .12s ease,border-color .12s ease} + .primary,.ghost{min-height:44px;padding:0 18px;font-weight:700} + .mini,.tab{min-height:34px;padding:0 12px;font-weight:600} + .primary{background:var(--accent);color:#fff7f2} + .ghost,.mini{background:rgba(255,255,255,.76);border-color:var(--line);color:var(--ink)} + .tab{background:transparent;color:var(--muted)} + .tab.active{background:#fff;border-color:var(--line);color:var(--ink)} + .primary:hover,.ghost:hover,.mini:hover,.tab:hover{transform:translateY(-1px)} + .chip{display:inline-flex;align-items:center;gap:10px;min-height:44px;padding:0 16px;border-radius:999px;background:rgba(255,255,255,.76);border:1px solid var(--line);font-weight:600} + .chip input{margin:0;accent-color:var(--accent)} + .chip select{border:none;background:transparent;outline:none;color:var(--ink)} + .search{flex:1 1 320px;min-height:48px;padding:0 16px;border-radius:16px;border:1px solid var(--line);background:rgba(255,255,255,.82);color:var(--ink);outline:none} + .status{display:inline-flex;align-items:center;min-height:40px;padding:0 14px;border-radius:999px;background:rgba(255,255,255,.76);border:1px solid var(--line);color:var(--muted);font-weight:600} + .status.ok{color:var(--ok);border-color:rgba(31,143,101,.22);background:rgba(31,143,101,.08)} + .status.warn{color:var(--warn);border-color:rgba(157,95,0,.22);background:rgba(157,95,0,.08)} + .status.bad{color:var(--bad);border-color:rgba(179,58,58,.22);background:rgba(179,58,58,.08)} + .stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px;margin-bottom:18px} + .stat{border-radius:18px;padding:18px} + .stat span{display:block;margin-bottom:10px;color:var(--muted);font-size:.82rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase} + .stat strong{display:block;font-size:clamp(2rem,4vw,2.6rem);line-height:1;letter-spacing:-.05em} + .stat strong.small{font-size:1.1rem;line-height:1.3;letter-spacing:-.02em} + .stat small{display:block;margin-top:10px;color:var(--muted);font-size:.95rem} + .banner,.empty{margin:0 0 18px;padding:16px 18px;border-radius:16px;border:1px solid var(--line);background:rgba(255,255,255,.82)} + .banner{color:var(--bad);border-color:rgba(179,58,58,.24);background:rgba(179,58,58,.08)} + .list{display:grid;gap:18px} + .card{overflow:hidden;border-radius:18px} + .card.new{border-color:rgba(31,143,101,.28);box-shadow:var(--shadow),0 0 0 1px rgba(31,143,101,.12)} + .summary{list-style:none;display:grid;gap:12px;padding:20px;cursor:pointer} + .summary::-webkit-details-marker{display:none} + .top,.tags,.toolbar,.actions,.attachments{display:flex;flex-wrap:wrap;gap:10px;align-items:center} + .top{justify-content:space-between} + .head{min-width:0;flex:1 1 320px} + .head h2{margin:0;font-size:clamp(1.1rem,2vw,1.45rem);line-height:1.2;letter-spacing:-.03em;word-break:break-word} + .meta{margin:6px 0 0;color:var(--muted);font-size:.95rem;word-break:break-word} + .time,.tag{display:inline-flex;align-items:center;min-height:28px;padding:0 12px;border-radius:999px;font-size:.84rem;font-weight:700} + .time{background:rgba(31,41,51,.06)} + .tag{background:rgba(31,41,51,.06);color:var(--muted)} + .tag.new{background:rgba(31,143,101,.1);color:var(--ok)} + .tag.bad{background:rgba(179,58,58,.1);color:var(--bad)} + .preview{margin:0} + .body{display:grid;gap:16px;padding:18px 20px 20px;border-top:1px solid var(--line);background:var(--panel-strong)} + .toolbar{justify-content:space-between;align-items:flex-start} + .tabs{display:inline-flex;gap:6px;padding:6px;border-radius:999px;background:rgba(31,41,51,.05)} + .grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px} + .metaCard{padding:14px 16px;border-radius:14px;background:rgba(31,41,51,.035);border:1px solid rgba(31,41,51,.08)} + .metaCard dt{margin:0 0 6px;color:var(--muted);font-size:.8rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase} + .metaCard dd{margin:0;word-break:break-word} + .attachments{gap:8px} + .attachment{padding:9px 12px;border-radius:12px;background:rgba(255,255,255,.72);border:1px solid var(--line);font-size:.92rem} + .panel{overflow:hidden;border-radius:14px;border:1px solid var(--line);background:#fff} + iframe{width:100%;min-height:720px;border:none;background:#fff} + pre{margin:0;padding:16px;white-space:pre-wrap;word-break:break-word;overflow:auto;font:13px/1.55 "Cascadia Code","Consolas",monospace;color:#102030;background:linear-gradient(180deg,rgba(207,109,60,.04),transparent 140px),#fff} + .placeholder,.inlineError{padding:16px} + .inlineError{color:var(--bad)} + @media (max-width:1080px){.hero{grid-template-columns:1fr}.stats{grid-template-columns:repeat(2,minmax(0,1fr))}} + @media (max-width:720px){.page{padding:16px}.stats{grid-template-columns:1fr}.primary,.ghost,.chip{width:100%;justify-content:center}.toolbar,.row{align-items:stretch}iframe{min-height:560px}} `; } +function escapeHtml(value) { + return String(value ?? "") + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); +} + +function clientApp(config) { + const state = { + messages: [], + filtered: [], + search: "", + auto: true, + interval: config.defaultRefreshMs, + loading: false, + error: "", + updatedAt: 0, + source: "initial", + duration: 0, + parseErrors: 0, + newest: "", + newIds: new Set(), + knownIds: new Set(), + openIds: new Set(), + views: {}, + raw: {} + }; + + const el = { + refreshButton: document.getElementById("refreshButton"), + autoToggle: document.getElementById("autoToggle"), + intervalSelect: document.getElementById("intervalSelect"), + searchInput: document.getElementById("searchInput"), + clearSearchButton: document.getElementById("clearSearchButton"), + expandAllButton: document.getElementById("expandAllButton"), + collapseAllButton: document.getElementById("collapseAllButton"), + statusChip: document.getElementById("statusChip"), + totalStat: document.getElementById("totalStat"), + visibleStat: document.getElementById("visibleStat"), + newStat: document.getElementById("newStat"), + newestStat: document.getElementById("newestStat"), + updatedStat: document.getElementById("updatedStat"), + fetchStat: document.getElementById("fetchStat"), + fetchDetail: document.getElementById("fetchDetail"), + banner: document.getElementById("banner"), + empty: document.getElementById("empty"), + list: document.getElementById("list") + }; + + el.intervalSelect.value = String(config.defaultRefreshMs); + wire(); + renderAll(); + refreshMessages("initial"); + window.setInterval(renderLiveClock, 1000); + + function wire() { + el.refreshButton.addEventListener("click", () => refreshMessages("manual")); + + el.autoToggle.addEventListener("change", () => { + state.auto = el.autoToggle.checked; + scheduleRefresh(); + renderStatus(); + }); + + el.intervalSelect.addEventListener("change", () => { + state.interval = Number(el.intervalSelect.value) || config.defaultRefreshMs; + scheduleRefresh(); + renderStatus(); + }); + + el.searchInput.addEventListener("input", (event) => { + state.search = event.target.value; + applyFilter(); + }); + + el.clearSearchButton.addEventListener("click", () => { + state.search = ""; + el.searchInput.value = ""; + applyFilter(); + }); + + el.expandAllButton.addEventListener("click", () => { + state.filtered.forEach((message) => state.openIds.add(message.id)); + renderList(); + }); + + el.collapseAllButton.addEventListener("click", () => { + state.openIds.clear(); + renderList(); + }); + + el.list.addEventListener("click", async (event) => { + const button = event.target.closest("button[data-action]"); + + if (!button) { + return; + } + + const id = button.dataset.id; + const message = getMessage(id); + + if (!message) { + return; + } + + if (button.dataset.action === "view") { + state.views[id] = button.dataset.view; + renderList(); + return; + } + + if (button.dataset.action === "load-raw") { + await loadRaw(id); + renderList(); + return; + } + + if (button.dataset.action === "copy-raw") { + const raw = await loadRaw(id); + + if (raw) { + await copyText(raw); + setStatus("Raw message copied to the clipboard.", "ok"); + } + } + }); + + document.addEventListener("visibilitychange", () => { + window.clearTimeout(state.timer); + + if (!document.hidden && state.auto) { + refreshMessages("visibility"); + } else { + renderStatus(); + } + }); + + window.addEventListener("keydown", (event) => { + const isField = + event.target instanceof HTMLElement && + (event.target.matches("input,textarea,select") || event.target.isContentEditable); + + if (!isField && event.key.toLowerCase() === "r") { + event.preventDefault(); + refreshMessages("keyboard"); + } + }); + } + + async function refreshMessages(source) { + if (state.loading) { + return; + } + + state.loading = true; + state.source = source; + state.error = ""; + renderStatus(); + renderFetch(); + + try { + const response = await fetch("/api/messages", { cache: "no-store" }); + + if (!response.ok) { + const payload = await safeJson(response); + throw new Error(payload?.details || payload?.error || `Request failed with ${response.status}`); + } + + const payload = await response.json(); + const messages = Array.isArray(payload.messages) ? payload.messages : []; + const nextIds = new Set(messages.map((message) => message.id)); + + state.newIds = state.updatedAt + ? new Set(messages.filter((message) => !state.knownIds.has(message.id)).map((message) => message.id)) + : new Set(); + state.knownIds = nextIds; + state.messages = messages; + state.duration = payload.fetchDurationMs || 0; + state.parseErrors = payload.parseErrors || 0; + state.newest = payload.latestMessageTimestamp || ""; + state.updatedAt = Date.now(); + + pruneState(); + applyFilter(); + setStatus(`Updated ${messages.length} message${messages.length === 1 ? "" : "s"}.`, "ok"); + } catch (error) { + state.error = error.message || "Unknown refresh error"; + setStatus(`Refresh failed: ${state.error}`, "bad"); + } finally { + state.loading = false; + scheduleRefresh(); + renderAll(); + } + } + + function pruneState() { + const ids = new Set(state.messages.map((message) => message.id)); + state.openIds = new Set([...state.openIds].filter((id) => ids.has(id))); + state.newIds = new Set([...state.newIds].filter((id) => ids.has(id))); + + Object.keys(state.views).forEach((id) => { + if (!ids.has(id)) { + delete state.views[id]; + } + }); + + Object.keys(state.raw).forEach((id) => { + if (!ids.has(id)) { + delete state.raw[id]; + } + }); + } + + function applyFilter() { + const search = state.search.trim().toLowerCase(); + state.filtered = !search + ? [...state.messages] + : state.messages.filter((message) => haystack(message).includes(search)); + renderAll(); + } + + function haystack(message) { + return [ + message.subject, + message.from, + message.to, + message.replyTo, + message.preview, + message.textContent, + message.region, + ...(message.attachments || []).flatMap((attachment) => [attachment.filename, attachment.contentType]) + ] + .filter(Boolean) + .join(" ") + .toLowerCase(); + } + + function scheduleRefresh() { + window.clearTimeout(state.timer); + + if (!state.auto || document.hidden || state.loading) { + return; + } + + state.timer = window.setTimeout(() => refreshMessages("auto"), state.interval); + } + + function renderAll() { + renderStats(); + renderFetch(); + renderStatus(); + renderList(); + renderLiveClock(); + } + + function renderStats() { + el.totalStat.textContent = String(state.messages.length); + el.visibleStat.textContent = `${state.filtered.length} visible${state.search ? " after search" : ""}`; + el.newStat.textContent = String(state.newIds.size); + el.newestStat.textContent = state.newest ? formatDateTime(state.newest) : "No messages"; + } + + function renderFetch() { + if (state.loading) { + el.fetchStat.textContent = "Refreshing..."; + el.fetchDetail.textContent = `Endpoint: ${config.endpoint}`; + return; + } + + if (state.error) { + el.fetchStat.textContent = "Needs attention"; + el.fetchDetail.textContent = state.error; + return; + } + + if (!state.updatedAt) { + el.fetchStat.textContent = "Idle"; + el.fetchDetail.textContent = `Endpoint: ${config.endpoint}`; + return; + } + + el.fetchStat.textContent = `${state.duration}ms`; + el.fetchDetail.textContent = `${state.parseErrors} parse error${state.parseErrors === 1 ? "" : "s"}. Endpoint: ${config.endpoint}`; + } + + function renderStatus() { + el.statusChip.className = "status"; + + if (state.loading) { + el.statusChip.classList.add("warn"); + el.statusChip.textContent = "Refreshing messages..."; + return; + } + + if (state.error) { + el.statusChip.classList.add("bad"); + el.statusChip.textContent = `Refresh failed: ${state.error}`; + return; + } + + if (!state.auto) { + el.statusChip.textContent = "Live refresh paused"; + return; + } + + if (document.hidden) { + el.statusChip.classList.add("warn"); + el.statusChip.textContent = "Tab hidden, live refresh paused"; + return; + } + + if (!state.updatedAt) { + el.statusChip.textContent = "Waiting for first refresh..."; + return; + } + + const seconds = Math.max(0, Math.ceil((state.updatedAt + state.interval - Date.now()) / 1000)); + el.statusChip.classList.add("ok"); + el.statusChip.textContent = `Live refresh on, next check in ${seconds}s`; + } + + function renderLiveClock() { + if (!state.updatedAt) { + el.updatedStat.textContent = "Not refreshed yet"; + return; + } + + el.updatedStat.textContent = `Updated ${formatRelative(state.updatedAt)} via ${state.source}`; + renderStatus(); + } + + function renderList() { + el.banner.hidden = !state.error; + el.banner.textContent = state.error ? `Refresh failed: ${state.error}` : ""; + + if (!state.filtered.length) { + el.list.innerHTML = ""; + el.empty.hidden = false; + el.empty.textContent = state.messages.length + ? "No messages match the current search." + : "No emails yet. Send one through LocalStack SES and refresh."; + return; + } + + el.empty.hidden = true; + el.list.innerHTML = state.filtered.map(renderCard).join(""); + bindCardToggles(); + el.list.querySelectorAll(".card[open]").forEach((details) => hydrate(details, getMessage(details.dataset.id))); + } + + function bindCardToggles() { + el.list.querySelectorAll(".card").forEach((details) => { + details.addEventListener("toggle", () => { + const id = details.dataset.id; + + if (!id) { + return; + } + + if (details.open) { + state.openIds.add(id); + } else { + state.openIds.delete(id); + } + + hydrate(details, getMessage(id)); + }); + }); + } + + function renderCard(message) { + const open = state.openIds.has(message.id); + const view = state.views[message.id] || (message.hasHtml ? "rendered" : "text"); + const tags = []; + + if (state.newIds.has(message.id)) { + tags.push('New'); + } + + if (message.attachmentCount) { + tags.push( + `${message.attachmentCount} attachment${message.attachmentCount === 1 ? "" : "s"}` + ); + } + + tags.push(`${message.hasHtml ? "HTML" : "Text only"}`); + + if (message.parseError) { + tags.push('Parse issue'); + } + + return ` +
+ +
+
+

${escapeHtml(message.subject)}

+

${escapeHtml(message.from)} to ${escapeHtml(message.to)}

+
+ ${escapeHtml(formatDateTime(message.timestamp))} +
+
${tags.join("")}
+

${escapeHtml(message.preview)}

+
+
+
+
+ ${ + message.hasHtml + ? `` + : "" + } + + +
+
+ +
+
+ +
+ ${metaCard("From", message.from)} + ${metaCard("To", message.to)} + ${metaCard("Reply-To", message.replyTo || "None")} + ${metaCard("Sent", formatDateTime(message.timestamp))} + ${metaCard("Region", message.region || "Unknown region")} + ${metaCard("LocalStack Id", message.id)} + ${metaCard("Message-Id", message.messageId || "Not available")} + ${metaCard("Raw size", formatBytes(message.rawSizeBytes))} + ${message.parseError ? metaCard("Parse error", message.parseError) : ""} +
+ + ${ + message.attachments?.length + ? `
${message.attachments + .map((attachment) => { + const size = attachment.size ? `, ${formatBytes(attachment.size)}` : ""; + return `${escapeHtml(attachment.filename)} (${escapeHtml(attachment.contentType)}${escapeHtml(size)})`; + }) + .join("")}
` + : "" + } + +
${renderPanel(message, view)}
+
+
+ `; + } + + function renderPanel(message, view) { + if (view === "rendered" && message.hasHtml) { + return ``; + } + + if (view === "raw") { + const raw = state.raw[message.id]; + + if (!raw) { + return `
Raw MIME source is loaded on demand.
`; + } + + if (raw.status === "loading") { + return '
Loading raw source...
'; + } + + if (raw.status === "error") { + return `
Unable to load raw source: ${escapeHtml(raw.error)}
`; + } + + return `
${escapeHtml(raw.value)}
`; + } + + return `
${escapeHtml(message.textContent || "No plain-text content available for this message.")}
`; + } + + function metaCard(label, value) { + return `
${escapeHtml(label)}
${escapeHtml(value)}
`; + } + + function hydrate(details, message) { + if (!details || !details.open || !message) { + return; + } + + const view = state.views[message.id] || (message.hasHtml ? "rendered" : "text"); + + if (view !== "rendered" || !message.hasHtml) { + return; + } + + const iframe = details.querySelector("[data-frame]"); + + if (iframe) { + iframe.referrerPolicy = "no-referrer"; + iframe.sandbox = ""; + iframe.srcdoc = message.renderedHtml || ""; + } + } + + function getMessage(id) { + return state.messages.find((message) => message.id === id); + } + + async function loadRaw(id) { + if (state.raw[id]?.status === "loaded") { + return state.raw[id].value; + } + + if (state.raw[id]?.status === "loading") { + return null; + } + + state.raw[id] = { status: "loading" }; + renderList(); + + try { + const response = await fetch(`/api/messages/${encodeURIComponent(id)}/raw`, { cache: "no-store" }); + + if (!response.ok) { + throw new Error((await response.text()) || `Request failed with ${response.status}`); + } + + const value = await response.text(); + state.raw[id] = { status: "loaded", value }; + return value; + } catch (error) { + state.raw[id] = { status: "error", error: error.message || "Unknown raw load error" }; + setStatus("Could not load the raw message source.", "bad"); + return null; + } finally { + renderList(); + } + } + + async function copyText(value) { + try { + await navigator.clipboard.writeText(value); + } catch { + const input = document.createElement("textarea"); + input.value = value; + input.setAttribute("readonly", ""); + input.style.position = "fixed"; + input.style.opacity = "0"; + document.body.appendChild(input); + input.select(); + document.execCommand("copy"); + document.body.removeChild(input); + } + } + + function setStatus(message, tone) { + el.statusChip.className = "status"; + + if (tone) { + el.statusChip.classList.add(tone); + } + + el.statusChip.textContent = message; + } + + function formatDateTime(value) { + if (!value) { + return "Unknown time"; + } + + const date = new Date(value); + return Number.isNaN(date.getTime()) + ? "Unknown time" + : new Intl.DateTimeFormat(undefined, { dateStyle: "medium", timeStyle: "short" }).format(date); + } + + function formatRelative(timestampMs) { + const seconds = Math.max(1, Math.round((Date.now() - timestampMs) / 1000)); + + if (seconds < 60) { + return `${seconds}s ago`; + } + + const minutes = Math.round(seconds / 60); + + if (minutes < 60) { + return `${minutes}m ago`; + } + + const hours = Math.round(minutes / 60); + + if (hours < 24) { + return `${hours}h ago`; + } + + return `${Math.round(hours / 24)}d ago`; + } + + function formatBytes(value) { + if (!value) { + return "0 B"; + } + + const units = ["B", "KB", "MB", "GB"]; + let size = value; + let index = 0; + + while (size >= 1024 && index < units.length - 1) { + size /= 1024; + index += 1; + } + + return `${index === 0 ? size : size.toFixed(1)} ${units[index]}`; + } + + function escapeHtml(value) { + return String(value ?? "") + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); + } + + async function safeJson(response) { + try { + return await response.json(); + } catch { + return null; + } + } +} + app.listen(PORT, () => { - console.log(`Server is running on http://localhost:${PORT}`); + console.log(`Local email viewer is running on http://localhost:${PORT}`); + console.log(`Watching LocalStack SES endpoint at ${SES_ENDPOINT}`); }); diff --git a/_reference/localEmailViewer/package.json b/_reference/localEmailViewer/package.json index 5f553cf17..a6b522e0e 100644 --- a/_reference/localEmailViewer/package.json +++ b/_reference/localEmailViewer/package.json @@ -4,12 +4,13 @@ "main": "index.js", "type": "module", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "start": "node index.js", + "check": "node --check index.js" }, "keywords": [], "author": "", "license": "ISC", - "description": "", + "description": "LocalStack SES email viewer for inspecting local outbound mail", "dependencies": { "express": "^5.1.0", "mailparser": "^3.7.4", diff --git a/client/package-lock.json b/client/package-lock.json index 02a8f6229..c61164bdc 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -9,7 +9,7 @@ "version": "0.2.1", "hasInstallScript": true, "dependencies": { - "@amplitude/analytics-browser": "^2.35.3", + "@amplitude/analytics-browser": "^2.36.6", "@ant-design/pro-layout": "^7.22.6", "@apollo/client": "^4.1.6", "@dnd-kit/core": "^6.3.1", @@ -17,45 +17,45 @@ "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", "@emotion/is-prop-valid": "^1.4.0", - "@fingerprintjs/fingerprintjs": "^5.0.1", - "@firebase/analytics": "^0.10.19", - "@firebase/app": "^0.14.8", - "@firebase/auth": "^1.12.0", - "@firebase/firestore": "^4.11.0", - "@firebase/messaging": "^0.12.22", + "@fingerprintjs/fingerprintjs": "^5.1.0", + "@firebase/analytics": "^0.10.20", + "@firebase/app": "^0.14.9", + "@firebase/auth": "^1.12.1", + "@firebase/firestore": "^4.12.0", + "@firebase/messaging": "^0.12.24", "@jsreport/browser-client": "^3.1.0", "@reduxjs/toolkit": "^2.11.2", - "@sentry/cli": "^3.2.2", - "@sentry/react": "^10.40.0", + "@sentry/cli": "^3.3.3", + "@sentry/react": "^10.43.0", "@sentry/vite-plugin": "^4.9.1", "@splitsoftware/splitio-react": "^2.6.1", "@tanem/react-nprogress": "^5.0.63", - "antd": "^6.3.1", + "antd": "^6.3.3", "apollo-link-logger": "^3.0.0", "autosize": "^6.0.1", - "axios": "^1.13.5", + "axios": "^1.13.6", "classnames": "^2.5.1", "css-box-model": "^1.2.1", - "dayjs": "^1.11.19", + "dayjs": "^1.11.20", "dayjs-business-days2": "^1.3.2", "dinero.js": "^1.9.1", "dotenv": "^17.3.1", "env-cmd": "^11.0.0", "exifr": "^7.1.3", - "graphql": "^16.13.0", + "graphql": "^16.13.1", "graphql-ws": "^6.0.7", - "i18next": "^25.8.13", + "i18next": "^25.8.18", "i18next-browser-languagedetector": "^8.2.1", "immutability-helper": "^3.1.1", - "libphonenumber-js": "^1.12.38", - "lightningcss": "^1.31.1", - "logrocket": "^12.0.0", + "libphonenumber-js": "^1.12.40", + "lightningcss": "^1.32.0", + "logrocket": "^12.1.0", "markerjs2": "^2.32.7", "memoize-one": "^6.0.0", "normalize-url": "^8.1.1", "object-hash": "^3.0.0", "phone": "^3.1.71", - "posthog-js": "^1.355.0", + "posthog-js": "^1.360.2", "prop-types": "^15.8.1", "query-string": "^9.3.1", "raf-schd": "^4.0.3", @@ -66,8 +66,8 @@ "react-dom": "^19.2.4", "react-grid-gallery": "^1.0.1", "react-grid-layout": "^2.2.2", - "react-i18next": "^16.5.4", - "react-icons": "^5.5.0", + "react-i18next": "^16.5.8", + "react-icons": "^5.6.0", "react-image-lightbox": "^5.1.4", "react-markdown": "^10.1.0", "react-number-format": "^5.4.3", @@ -77,8 +77,8 @@ "react-resizable": "^3.1.3", "react-router-dom": "^7.13.1", "react-sticky": "^6.0.3", - "react-virtuoso": "^4.18.1", - "recharts": "^3.7.0", + "react-virtuoso": "^4.18.3", + "recharts": "^3.8.0", "redux": "^5.0.1", "redux-actions": "^3.0.3", "redux-persist": "^6.0.0", @@ -86,7 +86,7 @@ "redux-state-sync": "^3.1.4", "reselect": "^5.1.1", "rxjs": "^7.8.2", - "sass": "^1.97.3", + "sass": "^1.98.0", "socket.io-client": "^4.8.3", "styled-components": "^6.3.11", "vite-plugin-ejs": "^1.7.0", @@ -96,7 +96,7 @@ "@ant-design/icons": "^6.1.0", "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/preset-react": "^7.28.5", - "@dotenvx/dotenvx": "^1.52.0", + "@dotenvx/dotenvx": "^1.55.1", "@emotion/babel-plugin": "^11.13.5", "@emotion/react": "^11.14.0", "@eslint/js": "^9.39.2", @@ -112,9 +112,9 @@ "eslint": "^9.39.2", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-compiler": "^19.1.0-rc.2", - "globals": "^17.3.0", + "globals": "^17.4.0", "jsdom": "^28.1.0", - "memfs": "^4.56.10", + "memfs": "^4.56.11", "os-browserify": "^0.3.0", "playwright": "^1.58.2", "react-error-overlay": "^6.1.0", @@ -126,7 +126,7 @@ "vite-plugin-node-polyfills": "^0.25.0", "vite-plugin-pwa": "^1.2.0", "vite-plugin-style-import": "^2.0.0", - "vitest": "^4.0.18", + "vitest": "^4.1.0", "workbox-window": "^7.4.0" }, "engines": { @@ -151,17 +151,17 @@ "license": "MIT" }, "node_modules/@amplitude/analytics-browser": { - "version": "2.35.3", - "resolved": "https://registry.npmjs.org/@amplitude/analytics-browser/-/analytics-browser-2.35.3.tgz", - "integrity": "sha512-JHUtoDX+iKlpcUDw4A4EEi39sIWXB2q5M9Xb/vNVwNGmIAkPa8XwUYcM22872dvc2aaYo7Y1HHljcj2ETzOCJw==", + "version": "2.36.6", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-browser/-/analytics-browser-2.36.6.tgz", + "integrity": "sha512-tnIObYiC/YtVAxn83lPEhsVCmGjKe3tzWQ4IwufDR6RIsaopqW3qgCOYLeCyWFAwUtwrIwoYWAOBi9bn1KkI6A==", "license": "MIT", "dependencies": { - "@amplitude/analytics-core": "2.40.1", - "@amplitude/plugin-autocapture-browser": "1.22.2", - "@amplitude/plugin-network-capture-browser": "1.8.2", - "@amplitude/plugin-page-url-enrichment-browser": "0.6.2", - "@amplitude/plugin-page-view-tracking-browser": "2.7.2", - "@amplitude/plugin-web-vitals-browser": "1.1.13", + "@amplitude/analytics-core": "2.41.6", + "@amplitude/plugin-autocapture-browser": "1.23.6", + "@amplitude/plugin-network-capture-browser": "1.9.6", + "@amplitude/plugin-page-url-enrichment-browser": "0.6.10", + "@amplitude/plugin-page-view-tracking-browser": "2.8.6", + "@amplitude/plugin-web-vitals-browser": "1.1.21", "tslib": "^2.4.1" } }, @@ -172,64 +172,65 @@ "license": "MIT" }, "node_modules/@amplitude/analytics-core": { - "version": "2.40.1", - "resolved": "https://registry.npmjs.org/@amplitude/analytics-core/-/analytics-core-2.40.1.tgz", - "integrity": "sha512-7nX+QDsx29rbuNkRyvsqqhgtIAs9qTaKq4svrKv2sR+D8vEPFGuWW2Shb4/S3J5N03n3HSGkkPWWUNuqqEtrog==", + "version": "2.41.6", + "resolved": "https://registry.npmjs.org/@amplitude/analytics-core/-/analytics-core-2.41.6.tgz", + "integrity": "sha512-l8orw7J+fTDvPLtPUMIp3R+O7OHtHiSXFSPivi+YOpsxyZhm65Rs1EUVpWeHAavuTmzRR7VnVKxERVQqaZ2y/A==", "license": "MIT", "dependencies": { "@amplitude/analytics-connector": "^1.6.4", + "@types/zen-observable": "0.8.3", "safe-json-stringify": "1.2.0", "tslib": "^2.4.1", - "zen-observable-ts": "^1.1.0" + "zen-observable": "0.10.0" } }, "node_modules/@amplitude/plugin-autocapture-browser": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/@amplitude/plugin-autocapture-browser/-/plugin-autocapture-browser-1.22.2.tgz", - "integrity": "sha512-FvFLsbLNdHYhhFWUYtHHj5LlVYldoDa4musJpqcftqBtWmcRXujrgJeuTU9bbF39JSOeJZrKIxzYaFqbMXgpYQ==", + "version": "1.23.6", + "resolved": "https://registry.npmjs.org/@amplitude/plugin-autocapture-browser/-/plugin-autocapture-browser-1.23.6.tgz", + "integrity": "sha512-8WulIIySVfUEO9rhTfY8R/RQ6Ds8t2CTv4dBx0GXSiZrbncg7zbIXt3RBowCM53ZKu0q7raC0IHhD+XaaykqQA==", "license": "MIT", "dependencies": { - "@amplitude/analytics-core": "2.40.1", + "@amplitude/analytics-core": "2.41.6", "tslib": "^2.4.1" } }, "node_modules/@amplitude/plugin-network-capture-browser": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@amplitude/plugin-network-capture-browser/-/plugin-network-capture-browser-1.8.2.tgz", - "integrity": "sha512-+8OqmhZ5Gy3ldTIT9AWNHwby2YW0+0TSNhbXtlDEphluPPOpDqAAzt1WNgIh8piOHxXhalkF8VM9Ub2sdwZ9VQ==", + "version": "1.9.6", + "resolved": "https://registry.npmjs.org/@amplitude/plugin-network-capture-browser/-/plugin-network-capture-browser-1.9.6.tgz", + "integrity": "sha512-9eLYTSJE+ORu76Wh0ECZpLldmI/F38h+x0SZCtoc2IaILZ0RQENRqQK6HW9Jv2CCj3K1/+hKWwSYOpew+rF9RQ==", "license": "MIT", "dependencies": { - "@amplitude/analytics-core": "2.40.1", + "@amplitude/analytics-core": "2.41.6", "tslib": "^2.4.1" } }, "node_modules/@amplitude/plugin-page-url-enrichment-browser": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@amplitude/plugin-page-url-enrichment-browser/-/plugin-page-url-enrichment-browser-0.6.2.tgz", - "integrity": "sha512-E/QsgyHg/uOB6GloifGc/LA+iexWTWG6YGwnmD8RQUpdmk8V7Nl5MHJxl9dlC3H5N1tQ2gqJwv+RqRCqu6uW8Q==", + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/@amplitude/plugin-page-url-enrichment-browser/-/plugin-page-url-enrichment-browser-0.6.10.tgz", + "integrity": "sha512-jgp//bCJ93B6vz6AYAMg2vroHzK4rYpHxYVgmZwipD4fRD+18Y/GJebWcl6DYfQB4tvEzHQk2mxYBeZQG0d1Ug==", "license": "MIT", "dependencies": { - "@amplitude/analytics-core": "2.40.1", + "@amplitude/analytics-core": "2.41.6", "tslib": "^2.4.1" } }, "node_modules/@amplitude/plugin-page-view-tracking-browser": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@amplitude/plugin-page-view-tracking-browser/-/plugin-page-view-tracking-browser-2.7.2.tgz", - "integrity": "sha512-3QIJqoV5jN8QfbUecaD0PQDJ21851+idpINAEqvDFp4fF2E/Ki4KlEFSvcuq3jx85ICqq82Efqh6JlAYj0jsSA==", + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/@amplitude/plugin-page-view-tracking-browser/-/plugin-page-view-tracking-browser-2.8.6.tgz", + "integrity": "sha512-P7hyBg4/d4Mdbgzx5nkciy+yHWxPtoclJyVOf++AOgYLSzAeGw9J5mJl0vUitBG50tIvdRxoVk7kTHImfzD4dQ==", "license": "MIT", "dependencies": { - "@amplitude/analytics-core": "2.40.1", + "@amplitude/analytics-core": "2.41.6", "tslib": "^2.4.1" } }, "node_modules/@amplitude/plugin-web-vitals-browser": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@amplitude/plugin-web-vitals-browser/-/plugin-web-vitals-browser-1.1.13.tgz", - "integrity": "sha512-cNCUyJCXUjq8qNV1uzTyAbX/pKHSrfQ00n+FqNCcUgmizsjBPZh+RQzAKA227DvM6GG3LJ+ze173Fx8SB5u2gg==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/@amplitude/plugin-web-vitals-browser/-/plugin-web-vitals-browser-1.1.21.tgz", + "integrity": "sha512-ZivQlkkMIed0E0nrUuAbYTAZErYbvXTaBPMkQ+yPzixoBnMww/RF9q63WaH7mq83HMEVN66ISOmsUcmM0J/FVQ==", "license": "MIT", "dependencies": { - "@amplitude/analytics-core": "2.40.1", + "@amplitude/analytics-core": "2.41.6", "tslib": "^2.4.1", "web-vitals": "5.1.0" } @@ -263,12 +264,12 @@ } }, "node_modules/@ant-design/cssinjs-utils": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-2.1.1.tgz", - "integrity": "sha512-RKxkj5pGFB+FkPJ5NGhoX3DK3xsv0pMltha7Ei1AnY3tILeq38L7tuhaWDPQI/5nlPxOog44wvqpNyyGcUsNMg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-2.1.2.tgz", + "integrity": "sha512-5fTHQ158jJJ5dC/ECeyIdZUzKxE/mpEMRZxthyG1sw/AKRHKgJBg00Yi6ACVXgycdje7KahRNvNET/uBccwCnA==", "license": "MIT", "dependencies": { - "@ant-design/cssinjs": "^2.1.0", + "@ant-design/cssinjs": "^2.1.2", "@babel/runtime": "^7.23.2", "@rc-component/util": "^1.4.0" }, @@ -278,9 +279,9 @@ } }, "node_modules/@ant-design/cssinjs-utils/node_modules/@ant-design/cssinjs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-2.1.0.tgz", - "integrity": "sha512-eZFrPCnrYrF3XtL7qA4L75P0qA3TtZta8H3Yggy7UYFh8gZgu5bSMNF+v4UVCzGxzYmx8ZvPdgOce0BJ6PsW9g==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-2.1.2.tgz", + "integrity": "sha512-2Hy8BnCEH31xPeSLbhhB2ctCPXE2ZnASdi+KbSeS79BNbUhL9hAEe20SkUk+BR8aKTmqb6+FKFruk7w8z0VoRQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.11.1", @@ -2576,9 +2577,9 @@ } }, "node_modules/@dotenvx/dotenvx": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.52.0.tgz", - "integrity": "sha512-CaQcc8JvtzQhUSm9877b6V4Tb7HCotkcyud9X2YwdqtQKwgljkMRwU96fVYKnzN3V0Hj74oP7Es+vZ0mS+Aa1w==", + "version": "1.55.1", + "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.55.1.tgz", + "integrity": "sha512-WEuKyoe9CA7dfcFBnNbL0ndbCNcptaEYBygfFo9X1qEG+HD7xku4CYIplw6sbAHJavesZWbVBHeRSpvri0eKqw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -3418,21 +3419,21 @@ } }, "node_modules/@fingerprintjs/fingerprintjs": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@fingerprintjs/fingerprintjs/-/fingerprintjs-5.0.1.tgz", - "integrity": "sha512-KbaeE/rk2WL8MfpRP6jTI4lSr42SJPjvkyrjP3QU6uUDkOMWWYC2Ts1sNSYcegHC8avzOoYTHBj+2fTqvZWQBA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@fingerprintjs/fingerprintjs/-/fingerprintjs-5.1.0.tgz", + "integrity": "sha512-8h/CscV3xQ4KSLyXbSK8YFpZ5AaezzHfkl82mn8NJIEWNi1zLfbZSIu7MGGtx4pqa10oejhEk4u0MNutuE63Fw==", "license": "MIT" }, "node_modules/@firebase/analytics": { - "version": "0.10.19", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.19.tgz", - "integrity": "sha512-3wU676fh60gaiVYQEEXsbGS4HbF2XsiBphyvvqDbtC1U4/dO4coshbYktcCHq+HFaGIK07iHOh4pME0hEq1fcg==", + "version": "0.10.20", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.20.tgz", + "integrity": "sha512-adGTNVUWH5q66tI/OQuKLSN6mamPpfYhj0radlH2xt+3eL6NFPtXoOs+ulvs+UsmK27vNFx5FjRDfWk+TyduHg==", "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.7.0", - "@firebase/installations": "0.6.19", + "@firebase/component": "0.7.1", + "@firebase/installations": "0.6.20", "@firebase/logger": "0.5.0", - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -3440,14 +3441,14 @@ } }, "node_modules/@firebase/app": { - "version": "0.14.8", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.8.tgz", - "integrity": "sha512-WiE9uCGRLUnShdjb9iP20sA3ToWrBbNXr14/N5mow7Nls9dmKgfGaGX5cynLvrltxq2OrDLh1VDNaUgsnS/k/g==", + "version": "0.14.9", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.9.tgz", + "integrity": "sha512-3gtUX0e584MYkKBQMgSECMvE1Dwzg+eONefDQ0wxVSe5YMBsZwdN5pL7UapwWBlV8+i8QCztF9TP947tEjZAGA==", "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.7.0", + "@firebase/component": "0.7.1", "@firebase/logger": "0.5.0", - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "idb": "7.1.1", "tslib": "^2.1.0" }, @@ -3456,14 +3457,14 @@ } }, "node_modules/@firebase/auth": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.12.0.tgz", - "integrity": "sha512-zkvLpsrxynWHk07qGrUDfCSqKf4AvfZGEqJ7mVCtYGjNNDbGE71k0Yn84rg8QEZu4hQw1BC0qDEHzpNVBcSVmA==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.12.1.tgz", + "integrity": "sha512-nXKj7d5bMBlnq6XpcQQpmnSVwEeHBkoVbY/+Wk0P1ebLSICoH4XPtvKOFlXKfIHmcS84mLQ99fk3njlDGKSDtw==", "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.7.0", + "@firebase/component": "0.7.1", "@firebase/logger": "0.5.0", - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "tslib": "^2.1.0" }, "engines": { @@ -3480,12 +3481,12 @@ } }, "node_modules/@firebase/component": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", - "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.1.tgz", + "integrity": "sha512-mFzsm7CLHR60o08S23iLUY8m/i6kLpOK87wdEFPLhdlCahaxKmWOwSVGiWoENYSmFJJoDhrR3gKSCxz7ENdIww==", "license": "Apache-2.0", "dependencies": { - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "tslib": "^2.1.0" }, "engines": { @@ -3493,14 +3494,14 @@ } }, "node_modules/@firebase/firestore": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.11.0.tgz", - "integrity": "sha512-Zb88s8rssBd0J2Tt+NUXMPt2sf+Dq7meatKiJf5t9oto1kZ8w9gK59Koe1uPVbaKfdgBp++N/z0I4G/HamyEhg==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.12.0.tgz", + "integrity": "sha512-PM47OyiiAAoAMB8kkq4Je14mTciaRoAPDd3ng3Ckqz9i2TX9D9LfxIRcNzP/OxzNV4uBKRq6lXoOggkJBQR3Gw==", "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.7.0", + "@firebase/component": "0.7.1", "@firebase/logger": "0.5.0", - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "@firebase/webchannel-wrapper": "1.0.5", "@grpc/grpc-js": "~1.9.0", "@grpc/proto-loader": "^0.7.8", @@ -3514,13 +3515,13 @@ } }, "node_modules/@firebase/installations": { - "version": "0.6.19", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.19.tgz", - "integrity": "sha512-nGDmiwKLI1lerhwfwSHvMR9RZuIH5/8E3kgUWnVRqqL7kGVSktjLTWEMva7oh5yxQ3zXfIlIwJwMcaM5bK5j8Q==", + "version": "0.6.20", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.20.tgz", + "integrity": "sha512-LOzvR7XHPbhS0YB5ANXhqXB5qZlntPpwU/4KFwhSNpXNsGk/sBQ9g5hepi0y0/MfenJLe2v7t644iGOOElQaHQ==", "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.7.0", - "@firebase/util": "1.13.0", + "@firebase/component": "0.7.1", + "@firebase/util": "1.14.0", "idb": "7.1.1", "tslib": "^2.1.0" }, @@ -3541,15 +3542,15 @@ } }, "node_modules/@firebase/messaging": { - "version": "0.12.23", - "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.23.tgz", - "integrity": "sha512-cfuzv47XxqW4HH/OcR5rM+AlQd1xL/VhuaeW/wzMW1LFrsFcTn0GND/hak1vkQc2th8UisBcrkVcQAnOnKwYxg==", + "version": "0.12.24", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.24.tgz", + "integrity": "sha512-UtKoubegAhHyehcB7iQjvQ8OVITThPbbWk3g2/2ze42PrQr6oe6OmCElYQkBrE5RDCeMTNucXejbdulrQ2XwVg==", "license": "Apache-2.0", "dependencies": { - "@firebase/component": "0.7.0", - "@firebase/installations": "0.6.19", + "@firebase/component": "0.7.1", + "@firebase/installations": "0.6.20", "@firebase/messaging-interop-types": "0.2.3", - "@firebase/util": "1.13.0", + "@firebase/util": "1.14.0", "idb": "7.1.1", "tslib": "^2.1.0" }, @@ -3564,9 +3565,9 @@ "license": "Apache-2.0" }, "node_modules/@firebase/util": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", - "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.14.0.tgz", + "integrity": "sha512-/gnejm7MKkVIXnSJGpc9L2CvvvzJvtDPeAEq5jAwgVlf/PeNxot+THx/bpD20wQ8uL5sz0xqgXy1nisOYMU+mw==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -3930,14 +3931,14 @@ } }, "node_modules/@jsonjoy.com/fs-core": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.56.10.tgz", - "integrity": "sha512-PyAEA/3cnHhsGcdY+AmIU+ZPqTuZkDhCXQ2wkXypdLitSpd6d5Ivxhnq4wa2ETRWFVJGabYynBWxIijOswSmOw==", + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.56.11.tgz", + "integrity": "sha512-wThHjzUp01ImIjfCwhs+UnFkeGPFAymwLEkOtenHewaKe2pTP12p6r1UuwikA9NEvNf9Vlck92r8fb8n/MWM5w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-node-builtins": "4.56.10", - "@jsonjoy.com/fs-node-utils": "4.56.10", + "@jsonjoy.com/fs-node-builtins": "4.56.11", + "@jsonjoy.com/fs-node-utils": "4.56.11", "thingies": "^2.5.0" }, "engines": { @@ -3952,15 +3953,15 @@ } }, "node_modules/@jsonjoy.com/fs-fsa": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.56.10.tgz", - "integrity": "sha512-/FVK63ysNzTPOnCCcPoPHt77TOmachdMS422txM4KhxddLdbW1fIbFMYH0AM0ow/YchCyS5gqEjKLNyv71j/5Q==", + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.56.11.tgz", + "integrity": "sha512-ZYlF3XbMayyp97xEN8ZvYutU99PCHjM64mMZvnCseXkCJXJDVLAwlF8Q/7q/xiWQRsv3pQBj1WXHd9eEyYcaCQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-core": "4.56.10", - "@jsonjoy.com/fs-node-builtins": "4.56.10", - "@jsonjoy.com/fs-node-utils": "4.56.10", + "@jsonjoy.com/fs-core": "4.56.11", + "@jsonjoy.com/fs-node-builtins": "4.56.11", + "@jsonjoy.com/fs-node-utils": "4.56.11", "thingies": "^2.5.0" }, "engines": { @@ -3975,17 +3976,17 @@ } }, "node_modules/@jsonjoy.com/fs-node": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.56.10.tgz", - "integrity": "sha512-7R4Gv3tkUdW3dXfXiOkqxkElxKNVdd8BDOWC0/dbERd0pXpPY+s2s1Mino+aTvkGrFPiY+mmVxA7zhskm4Ue4Q==", + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.56.11.tgz", + "integrity": "sha512-D65YrnP6wRuZyEWoSFnBJSr5zARVpVBGctnhie4rCsMuGXNzX7IHKaOt85/Aj7SSoG1N2+/xlNjWmkLvZ2H3Tg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-core": "4.56.10", - "@jsonjoy.com/fs-node-builtins": "4.56.10", - "@jsonjoy.com/fs-node-utils": "4.56.10", - "@jsonjoy.com/fs-print": "4.56.10", - "@jsonjoy.com/fs-snapshot": "4.56.10", + "@jsonjoy.com/fs-core": "4.56.11", + "@jsonjoy.com/fs-node-builtins": "4.56.11", + "@jsonjoy.com/fs-node-utils": "4.56.11", + "@jsonjoy.com/fs-print": "4.56.11", + "@jsonjoy.com/fs-snapshot": "4.56.11", "glob-to-regex.js": "^1.0.0", "thingies": "^2.5.0" }, @@ -4001,9 +4002,9 @@ } }, "node_modules/@jsonjoy.com/fs-node-builtins": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.56.10.tgz", - "integrity": "sha512-uUnKz8R0YJyKq5jXpZtkGV9U0pJDt8hmYcLRrPjROheIfjMXsz82kXMgAA/qNg0wrZ1Kv+hrg7azqEZx6XZCVw==", + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.56.11.tgz", + "integrity": "sha512-CNmt3a0zMCIhniFLXtzPWuUxXFU+U+2VyQiIrgt/rRVeEJNrMQUABaRbVxR0Ouw1LyR9RjaEkPM6nYpED+y43A==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4018,15 +4019,15 @@ } }, "node_modules/@jsonjoy.com/fs-node-to-fsa": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.56.10.tgz", - "integrity": "sha512-oH+O6Y4lhn9NyG6aEoFwIBNKZeYy66toP5LJcDOMBgL99BKQMUf/zWJspdRhMdn/3hbzQsZ8EHHsuekbFLGUWw==", + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.56.11.tgz", + "integrity": "sha512-5OzGdvJDgZVo+xXWEYo72u81zpOWlxlbG4d4nL+hSiW+LKlua/dldNgPrpWxtvhgyntmdFQad2UTxFyGjJAGhA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-fsa": "4.56.10", - "@jsonjoy.com/fs-node-builtins": "4.56.10", - "@jsonjoy.com/fs-node-utils": "4.56.10" + "@jsonjoy.com/fs-fsa": "4.56.11", + "@jsonjoy.com/fs-node-builtins": "4.56.11", + "@jsonjoy.com/fs-node-utils": "4.56.11" }, "engines": { "node": ">=10.0" @@ -4040,13 +4041,13 @@ } }, "node_modules/@jsonjoy.com/fs-node-utils": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.56.10.tgz", - "integrity": "sha512-8EuPBgVI2aDPwFdaNQeNpHsyqPi3rr+85tMNG/lHvQLiVjzoZsvxA//Xd8aB567LUhy4QS03ptT+unkD/DIsNg==", + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.56.11.tgz", + "integrity": "sha512-JADOZFDA3wRfsuxkT0+MYc4F9hJO2PYDaY66kRTG6NqGX3+bqmKu66YFYAbII/tEmQWPZeHoClUB23rtQM9UPg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-node-builtins": "4.56.10" + "@jsonjoy.com/fs-node-builtins": "4.56.11" }, "engines": { "node": ">=10.0" @@ -4060,13 +4061,13 @@ } }, "node_modules/@jsonjoy.com/fs-print": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.56.10.tgz", - "integrity": "sha512-JW4fp5mAYepzFsSGrQ48ep8FXxpg4niFWHdF78wDrFGof7F3tKDJln72QFDEn/27M1yHd4v7sKHHVPh78aWcEw==", + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.56.11.tgz", + "integrity": "sha512-rnaKRgCRIn8JGTjxhS0JPE38YM3Pj/H7SW4/tglhIPbfKEkky7dpPayNKV2qy25SZSL15oFVgH/62dMZ/z7cyA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-node-utils": "4.56.10", + "@jsonjoy.com/fs-node-utils": "4.56.11", "tree-dump": "^1.1.0" }, "engines": { @@ -4081,14 +4082,14 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.56.10.tgz", - "integrity": "sha512-DkR6l5fj7+qj0+fVKm/OOXMGfDFCGXLfyHkORH3DF8hxkpDgIHbhf/DwncBMs2igu/ST7OEkexn1gIqoU6Y+9g==", + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.56.11.tgz", + "integrity": "sha512-IIldPX+cIRQuUol9fQzSS3hqyECxVpYMJQMqdU3dCKZFRzEl1rkIkw4P6y7Oh493sI7YdxZlKr/yWdzEWZ1wGQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@jsonjoy.com/buffers": "^17.65.0", - "@jsonjoy.com/fs-node-utils": "4.56.10", + "@jsonjoy.com/fs-node-utils": "4.56.11", "@jsonjoy.com/json-pack": "^17.65.0", "@jsonjoy.com/util": "^17.65.0" }, @@ -4104,9 +4105,9 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/base64": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-17.65.0.tgz", - "integrity": "sha512-Xrh7Fm/M0QAYpekSgmskdZYnFdSGnsxJ/tHaolA4bNwWdG9i65S8m83Meh7FOxyJyQAdo4d4J97NOomBLEfkDQ==", + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-17.67.0.tgz", + "integrity": "sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4121,9 +4122,9 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/buffers": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-17.65.0.tgz", - "integrity": "sha512-eBrIXd0/Ld3p9lpDDlMaMn6IEfWqtHMD+z61u0JrIiPzsV1r7m6xDZFRxJyvIFTEO+SWdYF9EiQbXZGd8BzPfA==", + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-17.67.0.tgz", + "integrity": "sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4138,9 +4139,9 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/codegen": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-17.65.0.tgz", - "integrity": "sha512-7MXcRYe7n3BG+fo3jicvjB0+6ypl2Y/bQp79Sp7KeSiiCgLqw4Oled6chVv07/xLVTdo3qa1CD0VCCnPaw+RGA==", + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-17.67.0.tgz", + "integrity": "sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4155,17 +4156,17 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pack": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-17.65.0.tgz", - "integrity": "sha512-e0SG/6qUCnVhHa0rjDJHgnXnbsacooHVqQHxspjvlYQSkHm+66wkHw6Gql+3u/WxI/b1VsOdUi0M+fOtkgKGdQ==", + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-17.67.0.tgz", + "integrity": "sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/base64": "17.65.0", - "@jsonjoy.com/buffers": "17.65.0", - "@jsonjoy.com/codegen": "17.65.0", - "@jsonjoy.com/json-pointer": "17.65.0", - "@jsonjoy.com/util": "17.65.0", + "@jsonjoy.com/base64": "17.67.0", + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0", + "@jsonjoy.com/json-pointer": "17.67.0", + "@jsonjoy.com/util": "17.67.0", "hyperdyperid": "^1.2.0", "thingies": "^2.5.0", "tree-dump": "^1.1.0" @@ -4182,13 +4183,13 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pointer": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-17.65.0.tgz", - "integrity": "sha512-uhTe+XhlIZpWOxgPcnO+iSCDgKKBpwkDVTyYiXX9VayGV8HSFVJM67M6pUE71zdnXF1W0Da21AvnhlmdwYPpow==", + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-17.67.0.tgz", + "integrity": "sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/util": "17.65.0" + "@jsonjoy.com/util": "17.67.0" }, "engines": { "node": ">=10.0" @@ -4202,14 +4203,14 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/util": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-17.65.0.tgz", - "integrity": "sha512-cWiEHZccQORf96q2y6zU3wDeIVPeidmGqd9cNKJRYoVHTV0S1eHPy5JTbHpMnGfDvtvujQwQozOqgO9ABu6h0w==", + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-17.67.0.tgz", + "integrity": "sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/buffers": "17.65.0", - "@jsonjoy.com/codegen": "17.65.0" + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0" }, "engines": { "node": ">=10.0" @@ -4852,18 +4853,18 @@ } }, "node_modules/@posthog/core": { - "version": "1.23.1", - "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.23.1.tgz", - "integrity": "sha512-GViD5mOv/mcbZcyzz3z9CS0R79JzxVaqEz4sP5Dsea178M/j3ZWe6gaHDZB9yuyGfcmIMQ/8K14yv+7QrK4sQQ==", + "version": "1.23.4", + "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.23.4.tgz", + "integrity": "sha512-gSM1gnIuw5UOBUOTz0IhCTH8jOHoFr5rzSDb5m7fn9ofLHvz3boZT1L1f+bcuk+mvzNJfrJ3ByVQGKmUQnKQ8g==", "license": "MIT", "dependencies": { "cross-spawn": "^7.0.6" } }, "node_modules/@posthog/types": { - "version": "1.355.0", - "resolved": "https://registry.npmjs.org/@posthog/types/-/types-1.355.0.tgz", - "integrity": "sha512-g9YNcIzSe+BJFKjuea7Hr0DiN83XlmqBXRpIyEJ7t9jVAK2Srf67Y2rI0ZjeNXe2LasOyOvoy7RgnSPBXbNZGw==", + "version": "1.360.2", + "resolved": "https://registry.npmjs.org/@posthog/types/-/types-1.360.2.tgz", + "integrity": "sha512-U48CbtmX5kETZvWjaJVlublSA1aLV99m71TQtgxWksBMXINS/3C7j+KqlMO6wH7SuaEZQnjaxh1KYGH4nRCaaA==", "license": "MIT" }, "node_modules/@protobufjs/aspromise": { @@ -5016,12 +5017,12 @@ } }, "node_modules/@rc-component/color-picker": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-3.1.0.tgz", - "integrity": "sha512-o7Vavj7yyfVxFmeynXf0fCHVlC0UTE9al74c6nYuLck+gjuVdQNWSVXR8Efq/mmWFy7891SCOsfaPq6Eqe1s/g==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-3.1.1.tgz", + "integrity": "sha512-OHaCHLHszCegdXmIq2ZRIZBN/EtpT6Wm8SG/gpzLATHbVKc/avvuKi+zlOuk05FTWvgaMmpxAko44uRJ3M+2pg==", "license": "MIT", "dependencies": { - "@ant-design/fast-color": "^3.0.0", + "@ant-design/fast-color": "^3.0.1", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, @@ -5127,9 +5128,9 @@ } }, "node_modules/@rc-component/form": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@rc-component/form/-/form-1.6.2.tgz", - "integrity": "sha512-OgIn2RAoaSBqaIgzJf/X6iflIa9LpTozci1lagLBdURDFhGA370v0+T0tXxOi8YShMjTha531sFhwtnrv+EJaQ==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@rc-component/form/-/form-1.7.2.tgz", + "integrity": "sha512-5C90rXH7aZvvvxB4M5ew+QxROvimdL/lqhSshR8NsyiR7HKOoGQYSitxdfENnH6/0KNFxEy2ranVe2LrTnHZIw==", "license": "MIT", "dependencies": { "@rc-component/async-validator": "^5.1.0", @@ -5405,9 +5406,9 @@ } }, "node_modules/@rc-component/picker": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@rc-component/picker/-/picker-1.9.0.tgz", - "integrity": "sha512-OLisdk8AWVCG9goBU1dWzuH5QlBQk8jktmQ6p0/IyBFwdKGwyIZOSjnBYo8hooHiTdl0lU+wGf/OfMtVBw02KQ==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@rc-component/picker/-/picker-1.9.1.tgz", + "integrity": "sha512-9FBYYsvH3HMLICaPDA/1Th5FLaDkFa7qAtangIdlhKb3ZALaR745e9PsOhheJb6asS4QXc12ffiAcjdkZ4C5/g==", "license": "MIT", "dependencies": { "@rc-component/overflow": "^1.0.0", @@ -5581,9 +5582,9 @@ } }, "node_modules/@rc-component/select": { - "version": "1.6.12", - "resolved": "https://registry.npmjs.org/@rc-component/select/-/select-1.6.12.tgz", - "integrity": "sha512-jYXAglYdOb54BrpWAcjjhdBP16NyCv/HbEaWFMbEHZQAJVmGHPAtmBqbFuPPuvInAVsIwLbCj4Agag9udOamiQ==", + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/@rc-component/select/-/select-1.6.15.tgz", + "integrity": "sha512-SyVCWnqxCQZZcQvQJ/CxSjx2bGma6ds/HtnpkIfZVnt6RoEgbqUmHgD6vrzNarNXwbLXerwVzWwq8F3d1sst7g==", "license": "MIT", "dependencies": { "@rc-component/overflow": "^1.0.0", @@ -5821,9 +5822,9 @@ } }, "node_modules/@rc-component/tree": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@rc-component/tree/-/tree-1.2.3.tgz", - "integrity": "sha512-mG8hF2ogQcKaEpfyxzPvMWqqkptofd7Sf+YiXOpPzuXLTLwNKfLDJtysc1/oybopbnzxNqWh2Vgwi+GYwNIb7w==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@rc-component/tree/-/tree-1.2.4.tgz", + "integrity": "sha512-5Gli43+m4R7NhpYYz3Z61I6LOw9yI6CNChxgVtvrO6xB1qML7iE6QMLVMB3+FTjo2yF6uFdAHtqWPECz/zbX5w==", "license": "MIT", "dependencies": { "@rc-component/motion": "^1.0.0", @@ -6700,50 +6701,50 @@ ] }, "node_modules/@sentry-internal/browser-utils": { - "version": "10.40.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.40.0.tgz", - "integrity": "sha512-3CDeVNBXYOIvBVdT0SOdMZx5LzYDLuhGK/z7A14sYZz4Cd2+f4mSeFDaEOoH/g2SaY2CKR5KGkAADy8IyjZ21w==", + "version": "10.43.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.43.0.tgz", + "integrity": "sha512-8zYTnzhAPvNkVH1Irs62wl0J/c+0QcJ62TonKnzpSFUUD3V5qz8YDZbjIDGfxy+1EB9fO0sxtddKCzwTHF/MbQ==", "license": "MIT", "dependencies": { - "@sentry/core": "10.40.0" + "@sentry/core": "10.43.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/feedback": { - "version": "10.40.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.40.0.tgz", - "integrity": "sha512-V/ixkcdCNMo04KgsCEeNEu966xUUTD6czKT2LOAO5siZACqFjT/Rp9VR1n7QQrVo3sL7P3QNiTHtX0jaeWbwzg==", + "version": "10.43.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.43.0.tgz", + "integrity": "sha512-YoXuwluP6eOcQxTeTtaWb090++MrLyWOVsUTejzUQQ6LFL13Jwt+bDPF1kvBugMq4a7OHw/UNKQfd6//rZMn2g==", "license": "MIT", "dependencies": { - "@sentry/core": "10.40.0" + "@sentry/core": "10.43.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/replay": { - "version": "10.40.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.40.0.tgz", - "integrity": "sha512-vsH2Ut0KIIQIHNdS3zzEGLJ2C9btbpvJIWAVk7l7oft66JzlUNC89qNaQ5SAypjLQx4Ln2V/ZTqfEoNzXOAsoQ==", + "version": "10.43.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.43.0.tgz", + "integrity": "sha512-khCXlGrlH1IU7P5zCEAJFestMeH97zDVCekj8OsNNDtN/1BmCJ46k6Xi0EqAUzdJgrOLJeLdoYdgtiIjovZ8Sg==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "10.40.0", - "@sentry/core": "10.40.0" + "@sentry-internal/browser-utils": "10.43.0", + "@sentry/core": "10.43.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "10.40.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.40.0.tgz", - "integrity": "sha512-wzQwilFHO2baeCt0dTMf0eW+rgK8O+mkisf9sQzPXzG3Krr/iVtFg1T5T1Th3YsCsEdn6yQ3hcBPLEXjMSvccg==", + "version": "10.43.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.43.0.tgz", + "integrity": "sha512-ZIw1UNKOFXo1LbPCJPMAx9xv7D8TMZQusLDUgb6BsPQJj0igAuwd7KRGTkjjgnrwBp2O/sxcQFRhQhknWk7QPg==", "license": "MIT", "dependencies": { - "@sentry-internal/replay": "10.40.0", - "@sentry/core": "10.40.0" + "@sentry-internal/replay": "10.43.0", + "@sentry/core": "10.43.0" }, "engines": { "node": ">=18" @@ -6759,16 +6760,16 @@ } }, "node_modules/@sentry/browser": { - "version": "10.40.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.40.0.tgz", - "integrity": "sha512-nCt3FKUMFad0C6xl5wCK0Jz+qT4Vev4fv6HJRn0YoNRRDQCfsUVxAz7pNyyiPNGM/WCDp9wJpGJsRvbBRd2anw==", + "version": "10.43.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.43.0.tgz", + "integrity": "sha512-2V3I3sXi3SMeiZpKixd9ztokSgK27cmvsD9J5oyOyjhGLTW/6QKCwHbKnluMgQMXq20nixQk5zN4wRjRUma3sg==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "10.40.0", - "@sentry-internal/feedback": "10.40.0", - "@sentry-internal/replay": "10.40.0", - "@sentry-internal/replay-canvas": "10.40.0", - "@sentry/core": "10.40.0" + "@sentry-internal/browser-utils": "10.43.0", + "@sentry-internal/feedback": "10.43.0", + "@sentry-internal/replay": "10.43.0", + "@sentry-internal/replay-canvas": "10.43.0", + "@sentry/core": "10.43.0" }, "engines": { "node": ">=18" @@ -6992,9 +6993,9 @@ } }, "node_modules/@sentry/cli": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-3.2.2.tgz", - "integrity": "sha512-qmjsm9+Bq/3QGTnIfOsJdhq+8LI3imxAPbGNBpRj4R0YFk+b1ry9huRHCLgkMcRFWtPkJmGZwEq2Z7e+02QPLA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-3.3.3.tgz", + "integrity": "sha512-4CZtfgiOraX+BntMjYQhfLDArXwpqt3sEo5Zdj2pqWSZSd4yI3ncfQ21CsxLcI/sUQrjmD5Vzidu4/1OShyxtA==", "hasInstallScript": true, "license": "FSL-1.1-MIT", "dependencies": { @@ -7010,20 +7011,20 @@ "node": ">= 18" }, "optionalDependencies": { - "@sentry/cli-darwin": "3.2.2", - "@sentry/cli-linux-arm": "3.2.2", - "@sentry/cli-linux-arm64": "3.2.2", - "@sentry/cli-linux-i686": "3.2.2", - "@sentry/cli-linux-x64": "3.2.2", - "@sentry/cli-win32-arm64": "3.2.2", - "@sentry/cli-win32-i686": "3.2.2", - "@sentry/cli-win32-x64": "3.2.2" + "@sentry/cli-darwin": "3.3.3", + "@sentry/cli-linux-arm": "3.3.3", + "@sentry/cli-linux-arm64": "3.3.3", + "@sentry/cli-linux-i686": "3.3.3", + "@sentry/cli-linux-x64": "3.3.3", + "@sentry/cli-win32-arm64": "3.3.3", + "@sentry/cli-win32-i686": "3.3.3", + "@sentry/cli-win32-x64": "3.3.3" } }, "node_modules/@sentry/cli-darwin": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-3.2.2.tgz", - "integrity": "sha512-y1uglMBbo9dYqC92hTQBkuGk7SegLPo1cVwJzX0dhplJoBMuanLMhOMYd1J20qhkDdBhguflCHGf0tOzNTGWhg==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-3.3.3.tgz", + "integrity": "sha512-P8DoL79eX5fhKCfBHHl7xwwTShDPOb2drJC8lizZ3v1iS1JLPrNweM1KEzDefR30zH1wghbLSwsYv/svWdM3wA==", "license": "FSL-1.1-MIT", "optional": true, "os": [ @@ -7034,9 +7035,9 @@ } }, "node_modules/@sentry/cli-linux-arm": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-3.2.2.tgz", - "integrity": "sha512-CC7N3hjOgs3cwrW0T9hqirFVUpKO6ASjdd0JT4DQHaAn34pruv8J+OoSnj1jkrT2DHxDkNNZPOFSK05AnHr8wA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-3.3.3.tgz", + "integrity": "sha512-a7o/huozveLIImXHe0HDwEMVhvDopOP2tLcopvV7sQsVE8f/QOShR5FudKjmiaZz2opdLzPJO9pv5WuF9jAZPg==", "cpu": [ "arm" ], @@ -7052,9 +7053,9 @@ } }, "node_modules/@sentry/cli-linux-arm64": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-3.2.2.tgz", - "integrity": "sha512-SIGJknEQNDw9S/8QPTl8QLVe2IEiTKH3NeeHQ/Q2XWXig1ZebJfm4iTrdu47ypszIfxHeLvQkkVrr8mRKq16xA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-3.3.3.tgz", + "integrity": "sha512-9jaX9RGyTpjo9u2urNi5ciBDpRdTt107YJpFXev+BFHJ6Lwz/owgRuYzPRfAen8hKkOOFheZ3iy07kl576eZzw==", "cpu": [ "arm64" ], @@ -7070,9 +7071,9 @@ } }, "node_modules/@sentry/cli-linux-i686": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-3.2.2.tgz", - "integrity": "sha512-W2hQ2DvIlZI05j2JN/87lfeo51F24zmQOJU6Uz+fZz/mkSvpnjeWxjAvfDNVGlLxp7XSoDbhHfrLBxdIh6jMeg==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-3.3.3.tgz", + "integrity": "sha512-VngQYzR2kDm2oojCuYF20ebLTK8HKvEwxe785J6gxob8Ef9JvZkERyUqENYppBa9aVgN0pandqPAqOECWykTMA==", "cpu": [ "x86", "ia32" @@ -7089,9 +7090,9 @@ } }, "node_modules/@sentry/cli-linux-x64": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-3.2.2.tgz", - "integrity": "sha512-4mh3yvOUxO63lq3teexRvalD1mWaRVjpgL2cCMKA2wkB69lcL5nK2gkdzDUKx2y/elluVdvGPPZaqOr1bfNI0w==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-3.3.3.tgz", + "integrity": "sha512-rBxXQeIYGefUNI2cXHxEr0y3bhxDQjOD4G6j/gqLz/Dj+l8gJ/iKP64kTudnoViNIpn0pdYccG69th7zmzM/Fg==", "cpu": [ "x64" ], @@ -7107,9 +7108,9 @@ } }, "node_modules/@sentry/cli-win32-arm64": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-3.2.2.tgz", - "integrity": "sha512-TQgfkdJgd8Y/lPzDibqc5Hamg8Hl5rN1sZwX80n4r9Ly46Yzu8Bv6KUhoNL/ktAvw9Aeko6Bx54rwZnzxFZHwg==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-3.3.3.tgz", + "integrity": "sha512-c52g+YS6BO0rzH8AEHqQPmpqZrw0GJjMWqy0tQ5jcqaGdaLVnxk0mMEubv8R6Dv5MR2LShoKjiNsaeVfrWIMUg==", "cpu": [ "arm64" ], @@ -7123,9 +7124,9 @@ } }, "node_modules/@sentry/cli-win32-i686": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-3.2.2.tgz", - "integrity": "sha512-vAcnq0SdYuvwIdREgF5APocjW3d9Z17xLwugpaAz8wpOjCeC1iMEFWqbz5k49i4iDkDVNFRMENiVvWVSu1kEnA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-3.3.3.tgz", + "integrity": "sha512-DygYzSY/+tS7oFj/mfeg/yzYxsQx3fO8cI+IWc2pns/at+JcJ9O5xyM/x/q55wOxpnwla7RL1D3rsqK2mqkYfg==", "cpu": [ "x86", "ia32" @@ -7140,9 +7141,9 @@ } }, "node_modules/@sentry/cli-win32-x64": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-3.2.2.tgz", - "integrity": "sha512-xWPTXjSSdmoyG/0ee7A9KSfsScGHCdaXMP6ASt4bMx3yYJO7ziEoZzfJE2M6oglz+woAm0LV9+O/n7g80tixlQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-3.3.3.tgz", + "integrity": "sha512-i0glPcHwkqbVA2Y+0Yz7CD/l8TSkfft1a+lTU9yk/+DDU8WGkyArEAxAji9bGo4p+k5HIFC8OC2MwpKdcdFM4Q==", "cpu": [ "x64" ], @@ -7177,22 +7178,22 @@ } }, "node_modules/@sentry/core": { - "version": "10.40.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.40.0.tgz", - "integrity": "sha512-/wrcHPp9Avmgl6WBimPjS4gj810a1wU5oX9fF1bzJfeIIbF3jTsAbv0oMbgDp0cSDnkwv2+NvcPnn3+c5J6pBA==", + "version": "10.43.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.43.0.tgz", + "integrity": "sha512-l0SszQAPiQGWl/ferw8GP3ALyHXiGiRKJaOvNmhGO+PrTQyZTZ6OYyPnGijAFRg58dE1V3RCH/zw5d2xSUIiNg==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@sentry/react": { - "version": "10.40.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.40.0.tgz", - "integrity": "sha512-3T5W/e3QJMimXRIOx8xMEZbxeIuFiKlXvHLcMTLGygGBYnxQGeb8Oz/8heov+3zF1JoCIxeVQNFW0woySApfyA==", + "version": "10.43.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.43.0.tgz", + "integrity": "sha512-shvErEpJ41i0Q3lIZl0CDWYQ7m8yHLi7ECG0gFvN8zf8pEdl5grQIOoe3t/GIUzcpCcor16F148ATmKJJypc/Q==", "license": "MIT", "dependencies": { - "@sentry/browser": "10.40.0", - "@sentry/core": "10.40.0" + "@sentry/browser": "10.43.0", + "@sentry/core": "10.43.0" }, "engines": { "node": ">=18" @@ -7278,9 +7279,9 @@ "license": "MIT" }, "node_modules/@standard-schema/spec": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "license": "MIT" }, "node_modules/@standard-schema/utils": { @@ -7739,17 +7740,17 @@ } }, "node_modules/@vitest/expect": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", - "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.0.tgz", + "integrity": "sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA==", "dev": true, "license": "MIT", "dependencies": { - "@standard-schema/spec": "^1.0.0", + "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "chai": "^6.2.1", + "@vitest/spy": "4.1.0", + "@vitest/utils": "4.1.0", + "chai": "^6.2.2", "tinyrainbow": "^3.0.3" }, "funding": { @@ -7757,13 +7758,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", - "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.0.tgz", + "integrity": "sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.0.18", + "@vitest/spy": "4.1.0", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -7772,7 +7773,7 @@ }, "peerDependencies": { "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0-0" + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" }, "peerDependenciesMeta": { "msw": { @@ -7804,9 +7805,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", - "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.0.tgz", + "integrity": "sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A==", "dev": true, "license": "MIT", "dependencies": { @@ -7817,13 +7818,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", - "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.0.tgz", + "integrity": "sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.0.18", + "@vitest/utils": "4.1.0", "pathe": "^2.0.3" }, "funding": { @@ -7838,13 +7839,14 @@ "license": "MIT" }, "node_modules/@vitest/snapshot": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", - "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.0.tgz", + "integrity": "sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.18", + "@vitest/pretty-format": "4.1.0", + "@vitest/utils": "4.1.0", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -7870,9 +7872,9 @@ "license": "MIT" }, "node_modules/@vitest/spy": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", - "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.0.tgz", + "integrity": "sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw==", "dev": true, "license": "MIT", "funding": { @@ -7880,19 +7882,27 @@ } }, "node_modules/@vitest/utils": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", - "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.0.tgz", + "integrity": "sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.18", + "@vitest/pretty-format": "4.1.0", + "convert-source-map": "^2.0.0", "tinyrainbow": "^3.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/utils/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, "node_modules/@wry/caches": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@wry/caches/-/caches-1.0.1.tgz", @@ -8015,14 +8025,14 @@ } }, "node_modules/antd": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/antd/-/antd-6.3.1.tgz", - "integrity": "sha512-8pRjvxitZFyrYAtgwml93Km7fCXjw9IeqlmzpIsusRsmO3eWFVrOMum6+0TsGCtR/WrXVnPwfsgrFg3ChzGCeA==", + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/antd/-/antd-6.3.3.tgz", + "integrity": "sha512-T8FAQelw36zS96cZw2U/qEjpYny5yFc7hg+1W7DvVr8xMoSXWvyB8WvmiDVH0nS0LPYV4y2sxetsJoGZt7rhhw==", "license": "MIT", "dependencies": { "@ant-design/colors": "^8.0.1", - "@ant-design/cssinjs": "^2.1.0", - "@ant-design/cssinjs-utils": "^2.1.1", + "@ant-design/cssinjs": "^2.1.2", + "@ant-design/cssinjs-utils": "^2.1.2", "@ant-design/fast-color": "^3.0.1", "@ant-design/icons": "^6.1.0", "@ant-design/react-slick": "~2.0.0", @@ -8030,11 +8040,11 @@ "@rc-component/cascader": "~1.14.0", "@rc-component/checkbox": "~2.0.0", "@rc-component/collapse": "~1.2.0", - "@rc-component/color-picker": "~3.1.0", + "@rc-component/color-picker": "~3.1.1", "@rc-component/dialog": "~1.8.4", "@rc-component/drawer": "~1.4.2", "@rc-component/dropdown": "~1.0.2", - "@rc-component/form": "~1.6.2", + "@rc-component/form": "~1.7.2", "@rc-component/image": "~1.6.0", "@rc-component/input": "~1.1.2", "@rc-component/input-number": "~1.6.2", @@ -8044,13 +8054,13 @@ "@rc-component/mutate-observer": "^2.0.1", "@rc-component/notification": "~1.2.0", "@rc-component/pagination": "~1.2.0", - "@rc-component/picker": "~1.9.0", + "@rc-component/picker": "~1.9.1", "@rc-component/progress": "~1.0.2", "@rc-component/qrcode": "~1.1.1", "@rc-component/rate": "~1.0.1", "@rc-component/resize-observer": "^1.1.1", "@rc-component/segmented": "~1.3.0", - "@rc-component/select": "~1.6.12", + "@rc-component/select": "~1.6.14", "@rc-component/slider": "~1.0.1", "@rc-component/steps": "~1.2.2", "@rc-component/switch": "~1.0.3", @@ -8059,7 +8069,7 @@ "@rc-component/textarea": "~1.1.2", "@rc-component/tooltip": "~1.4.0", "@rc-component/tour": "~2.3.0", - "@rc-component/tree": "~1.2.3", + "@rc-component/tree": "~1.2.4", "@rc-component/tree-select": "~1.8.0", "@rc-component/trigger": "^3.9.0", "@rc-component/upload": "~1.1.0", @@ -8079,9 +8089,9 @@ } }, "node_modules/antd/node_modules/@ant-design/cssinjs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-2.1.0.tgz", - "integrity": "sha512-eZFrPCnrYrF3XtL7qA4L75P0qA3TtZta8H3Yggy7UYFh8gZgu5bSMNF+v4UVCzGxzYmx8ZvPdgOce0BJ6PsW9g==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-2.1.2.tgz", + "integrity": "sha512-2Hy8BnCEH31xPeSLbhhB2ctCPXE2ZnASdi+KbSeS79BNbUhL9hAEe20SkUk+BR8aKTmqb6+FKFruk7w8z0VoRQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.11.1", @@ -8399,9 +8409,9 @@ } }, "node_modules/axios": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", - "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz", + "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.11", @@ -9711,9 +9721,9 @@ "license": "MIT" }, "node_modules/dayjs": { - "version": "1.11.19", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", - "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", + "version": "1.11.20", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz", + "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==", "license": "MIT" }, "node_modules/dayjs-business-days2": { @@ -9975,9 +9985,9 @@ } }, "node_modules/dompurify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", - "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.3.tgz", + "integrity": "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -10824,9 +10834,9 @@ "license": "MIT" }, "node_modules/expect-type": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", - "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -11341,9 +11351,9 @@ "integrity": "sha512-5e01v8eLGfuQSOvx2MsDMOWS0GFtCx1wPzQSmcHw4hkxFzrQDBO3Xwg/m8Hr/7qXMrHeOIE29qWVzyv06u1TZA==" }, "node_modules/globals": { - "version": "17.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-17.3.0.tgz", - "integrity": "sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw==", + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz", + "integrity": "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==", "dev": true, "license": "MIT", "engines": { @@ -11390,9 +11400,9 @@ "license": "ISC" }, "node_modules/graphql": { - "version": "16.13.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.13.0.tgz", - "integrity": "sha512-uSisMYERbaB9bkA9M4/4dnqyktaEkf1kMHNKq/7DHyxVeWqHQ2mBmVqm5u6/FVHwF3iCNalKcg82Zfl+tffWoA==", + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.13.1.tgz", + "integrity": "sha512-gGgrVCoDKlIZ8fIqXBBb0pPKqDgki0Z/FSKNiQzSGj2uEYHr1tq5wmBegGwJx6QB5S5cM0khSBpi/JFHMCvsmQ==", "license": "MIT", "engines": { "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" @@ -11763,9 +11773,9 @@ } }, "node_modules/i18next": { - "version": "25.8.13", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.13.tgz", - "integrity": "sha512-E0vzjBY1yM+nsFrtgkjLhST2NBkirkvOVoQa0MSldhsuZ3jUge7ZNpuwG0Cfc74zwo5ZwRzg3uOgT+McBn32iA==", + "version": "25.8.18", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.18.tgz", + "integrity": "sha512-lzY5X83BiL5AP77+9DydbrqkQHFN9hUzWGjqjLpPcp5ZOzuu1aSoKaU3xbBLSjWx9dAzW431y+d+aogxOZaKRA==", "funding": [ { "type": "individual", @@ -11782,7 +11792,7 @@ ], "license": "MIT", "dependencies": { - "@babel/runtime": "^7.28.4" + "@babel/runtime": "^7.28.6" }, "peerDependencies": { "typescript": "^5" @@ -11856,9 +11866,9 @@ "license": "MIT" }, "node_modules/immutable": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz", - "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", + "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", "license": "MIT" }, "node_modules/import-fresh": { @@ -12906,15 +12916,15 @@ } }, "node_modules/libphonenumber-js": { - "version": "1.12.38", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.38.tgz", - "integrity": "sha512-vwzxmasAy9hZigxtqTbFEwp8ZdZ975TiqVDwj5bKx5sR+zi5ucUQy9mbVTkKM9GzqdLdxux/hTw2nmN5J7POMA==", + "version": "1.12.40", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.40.tgz", + "integrity": "sha512-HKGs7GowShNls3Zh+7DTr6wYpPk5jC78l508yQQY3e8ZgJChM3A9JZghmMJZuK+5bogSfuTafpjksGSR3aMIEg==", "license": "MIT" }, "node_modules/lightningcss": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", - "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" @@ -12927,23 +12937,23 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-android-arm64": "1.31.1", - "lightningcss-darwin-arm64": "1.31.1", - "lightningcss-darwin-x64": "1.31.1", - "lightningcss-freebsd-x64": "1.31.1", - "lightningcss-linux-arm-gnueabihf": "1.31.1", - "lightningcss-linux-arm64-gnu": "1.31.1", - "lightningcss-linux-arm64-musl": "1.31.1", - "lightningcss-linux-x64-gnu": "1.31.1", - "lightningcss-linux-x64-musl": "1.31.1", - "lightningcss-win32-arm64-msvc": "1.31.1", - "lightningcss-win32-x64-msvc": "1.31.1" + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" } }, "node_modules/lightningcss-android-arm64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz", - "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", "cpu": [ "arm64" ], @@ -12961,9 +12971,9 @@ } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz", - "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", "cpu": [ "arm64" ], @@ -12981,9 +12991,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz", - "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", "cpu": [ "x64" ], @@ -13001,9 +13011,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz", - "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", "cpu": [ "x64" ], @@ -13021,9 +13031,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz", - "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", "cpu": [ "arm" ], @@ -13041,9 +13051,9 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz", - "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", "cpu": [ "arm64" ], @@ -13061,9 +13071,9 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz", - "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", "cpu": [ "arm64" ], @@ -13081,9 +13091,9 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz", - "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", "cpu": [ "x64" ], @@ -13101,9 +13111,9 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz", - "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", "cpu": [ "x64" ], @@ -13121,9 +13131,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz", - "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", "cpu": [ "arm64" ], @@ -13141,9 +13151,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz", - "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==", + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", "cpu": [ "x64" ], @@ -13240,9 +13250,9 @@ "license": "MIT" }, "node_modules/logrocket": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/logrocket/-/logrocket-12.0.0.tgz", - "integrity": "sha512-7VUI2gi3XxACLqJGZJ/8hRx3KT7z2joNXcBqbefkfWI6rLqMJOq0LUmfLbw3qRPPZTjOBiwpKKVecusL3V5K7Q==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/logrocket/-/logrocket-12.1.0.tgz", + "integrity": "sha512-WZXCwtPam15ktseKzP2SAd2PgHXmr41++8Lgg30VyW/mpAbHaJAZm5//C+l9Yt5x6HLfwH76PuY47RXpKUvTuA==", "license": "MIT" }, "node_modules/long": { @@ -13517,20 +13527,20 @@ "license": "CC0-1.0" }, "node_modules/memfs": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.56.10.tgz", - "integrity": "sha512-eLvzyrwqLHnLYalJP7YZ3wBe79MXktMdfQbvMrVD80K+NhrIukCVBvgP30zTJYEEDh9hZ/ep9z0KOdD7FSHo7w==", + "version": "4.56.11", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.56.11.tgz", + "integrity": "sha512-/GodtwVeKVIHZKLUSr2ZdOxKBC5hHki4JNCU22DoCGPEHr5o2PD5U721zvESKyWwCfTfavFl9WZYgA13OAYK0g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-core": "4.56.10", - "@jsonjoy.com/fs-fsa": "4.56.10", - "@jsonjoy.com/fs-node": "4.56.10", - "@jsonjoy.com/fs-node-builtins": "4.56.10", - "@jsonjoy.com/fs-node-to-fsa": "4.56.10", - "@jsonjoy.com/fs-node-utils": "4.56.10", - "@jsonjoy.com/fs-print": "4.56.10", - "@jsonjoy.com/fs-snapshot": "4.56.10", + "@jsonjoy.com/fs-core": "4.56.11", + "@jsonjoy.com/fs-fsa": "4.56.11", + "@jsonjoy.com/fs-node": "4.56.11", + "@jsonjoy.com/fs-node-builtins": "4.56.11", + "@jsonjoy.com/fs-node-to-fsa": "4.56.11", + "@jsonjoy.com/fs-node-utils": "4.56.11", + "@jsonjoy.com/fs-print": "4.56.11", + "@jsonjoy.com/fs-snapshot": "4.56.11", "@jsonjoy.com/json-pack": "^1.11.0", "@jsonjoy.com/util": "^1.9.0", "glob-to-regex.js": "^1.0.1", @@ -15049,9 +15059,9 @@ "license": "MIT" }, "node_modules/posthog-js": { - "version": "1.355.0", - "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.355.0.tgz", - "integrity": "sha512-RpxHyodlr9wuqoZOct8DDg50SGq3SQmUWxYu+G1eOO+PvWsr5N2ZZdhE/rpv2zZccPdbXdgIy3M1pa574Nps7w==", + "version": "1.360.2", + "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.360.2.tgz", + "integrity": "sha512-/Wed0mOuRUfyEGT/BRQaokCqBlxrEceE7MDT9A00lU5tXo443/2Pg9ZiqN5sucUluZF47hwGORpYPoVUt32UFw==", "license": "SEE LICENSE IN LICENSE", "dependencies": { "@opentelemetry/api": "^1.9.0", @@ -15059,10 +15069,10 @@ "@opentelemetry/exporter-logs-otlp-http": "^0.208.0", "@opentelemetry/resources": "^2.2.0", "@opentelemetry/sdk-logs": "^0.208.0", - "@posthog/core": "1.23.1", - "@posthog/types": "1.355.0", + "@posthog/core": "1.23.4", + "@posthog/types": "1.360.2", "core-js": "^3.38.1", - "dompurify": "^3.3.1", + "dompurify": "^3.3.2", "fflate": "^0.4.8", "preact": "^10.28.2", "query-selector-shadow-dom": "^1.0.1", @@ -15524,9 +15534,9 @@ "license": "MIT" }, "node_modules/react-i18next": { - "version": "16.5.4", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.5.4.tgz", - "integrity": "sha512-6yj+dcfMncEC21QPhOTsW8mOSO+pzFmT6uvU7XXdvM/Cp38zJkmTeMeKmTrmCMD5ToT79FmiE/mRWiYWcJYW4g==", + "version": "16.5.8", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.5.8.tgz", + "integrity": "sha512-2ABeHHlakxVY+LSirD+OiERxFL6+zip0PaHo979bgwzeHg27Sqc82xxXWIrSFmfWX0ZkrvXMHwhsi/NGUf5VQg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", @@ -15551,9 +15561,9 @@ } }, "node_modules/react-icons": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", - "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.6.0.tgz", + "integrity": "sha512-RH93p5ki6LfOiIt0UtDyNg/cee+HLVR6cHHtW3wALfo+eOHTp8RnU2kRkI6E+H19zMIs03DyxUG/GfZMOGvmiA==", "license": "MIT", "peerDependencies": { "react": "*" @@ -15790,9 +15800,9 @@ } }, "node_modules/react-virtuoso": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.18.1.tgz", - "integrity": "sha512-KF474cDwaSb9+SJ380xruBB4P+yGWcVkcu26HtMqYNMTYlYbrNy8vqMkE+GpAApPPufJqgOLMoWMFG/3pJMXUA==", + "version": "4.18.3", + "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.18.3.tgz", + "integrity": "sha512-fLz/peHAx4Eu0DLHurFEEI7Y6n5CqEoxBh04rgJM9yMuOJah2a9zWg/MUOmZLcp7zuWYorXq5+5bf3IRgkNvWg==", "license": "MIT", "peerDependencies": { "react": ">=16 || >=17 || >= 18 || >= 19", @@ -15837,15 +15847,15 @@ } }, "node_modules/recharts": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.7.0.tgz", - "integrity": "sha512-l2VCsy3XXeraxIID9fx23eCb6iCBsxUQDnE8tWm6DFdszVAO7WVY/ChAD9wVit01y6B2PMupYiMmQwhgPHc9Ew==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.8.0.tgz", + "integrity": "sha512-Z/m38DX3L73ExO4Tpc9/iZWHmHnlzWG4njQbxsF5aSjwqmHNDDIm0rdEBArkwsBvR8U6EirlEHiQNYWCVh9sGQ==", "license": "MIT", "workspaces": [ "www" ], "dependencies": { - "@reduxjs/toolkit": "1.x.x || 2.x.x", + "@reduxjs/toolkit": "^1.9.0 || 2.x.x", "clsx": "^2.1.1", "decimal.js-light": "^2.5.1", "es-toolkit": "^1.39.3", @@ -16448,13 +16458,13 @@ } }, "node_modules/sass": { - "version": "1.97.3", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.3.tgz", - "integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==", + "version": "1.98.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.98.0.tgz", + "integrity": "sha512-+4N/u9dZ4PrgzGgPlKnaaRQx64RO0JBKs9sDhQ2pLgN6JQZ25uPQZKQYaBJU48Kd5BxgXoJ4e09Dq7nMcOUW3A==", "license": "MIT", "dependencies": { "chokidar": "^4.0.0", - "immutable": "^5.0.2", + "immutable": "^5.1.5", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { @@ -17019,9 +17029,9 @@ "license": "MIT" }, "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", + "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", "dev": true, "license": "MIT" }, @@ -17623,9 +17633,9 @@ } }, "node_modules/tinyrainbow": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", - "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", "dev": true, "license": "MIT", "engines": { @@ -18592,31 +18602,31 @@ } }, "node_modules/vitest": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", - "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.0.tgz", + "integrity": "sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.0.18", - "@vitest/mocker": "4.0.18", - "@vitest/pretty-format": "4.0.18", - "@vitest/runner": "4.0.18", - "@vitest/snapshot": "4.0.18", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "es-module-lexer": "^1.7.0", - "expect-type": "^1.2.2", + "@vitest/expect": "4.1.0", + "@vitest/mocker": "4.1.0", + "@vitest/pretty-format": "4.1.0", + "@vitest/runner": "4.1.0", + "@vitest/snapshot": "4.1.0", + "@vitest/spy": "4.1.0", + "@vitest/utils": "4.1.0", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", - "std-env": "^3.10.0", + "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", - "vite": "^6.0.0 || ^7.0.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0", "why-is-node-running": "^2.3.0" }, "bin": { @@ -18632,12 +18642,13 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.0.18", - "@vitest/browser-preview": "4.0.18", - "@vitest/browser-webdriverio": "4.0.18", - "@vitest/ui": "4.0.18", + "@vitest/browser-playwright": "4.1.0", + "@vitest/browser-preview": "4.1.0", + "@vitest/browser-webdriverio": "4.1.0", + "@vitest/ui": "4.1.0", "happy-dom": "*", - "jsdom": "*" + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" }, "peerDependenciesMeta": { "@edge-runtime/vm": { @@ -18666,13 +18677,16 @@ }, "jsdom": { "optional": true + }, + "vite": { + "optional": false } } }, "node_modules/vitest/node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "dev": true, "license": "MIT" }, @@ -19501,21 +19515,11 @@ } }, "node_modules/zen-observable": { - "version": "0.8.15", - "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", - "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.10.0.tgz", + "integrity": "sha512-iI3lT0iojZhKwT5DaFy2Ce42n3yFcLdFyOh01G7H0flMY60P8MJuVFEoJoNwXlmAyQ45GrjL6AcZmmlv8A5rbw==", "license": "MIT" }, - "node_modules/zen-observable-ts": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz", - "integrity": "sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==", - "license": "MIT", - "dependencies": { - "@types/zen-observable": "0.8.3", - "zen-observable": "0.8.15" - } - }, "node_modules/zod": { "version": "3.25.76", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", diff --git a/client/package.json b/client/package.json index 1f14bec96..e44ee619a 100644 --- a/client/package.json +++ b/client/package.json @@ -8,7 +8,7 @@ "private": true, "proxy": "http://localhost:4000", "dependencies": { - "@amplitude/analytics-browser": "^2.35.3", + "@amplitude/analytics-browser": "^2.36.6", "@ant-design/pro-layout": "^7.22.6", "@apollo/client": "^4.1.6", "@dnd-kit/core": "^6.3.1", @@ -16,45 +16,45 @@ "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", "@emotion/is-prop-valid": "^1.4.0", - "@fingerprintjs/fingerprintjs": "^5.0.1", - "@firebase/analytics": "^0.10.19", - "@firebase/app": "^0.14.8", - "@firebase/auth": "^1.12.0", - "@firebase/firestore": "^4.11.0", - "@firebase/messaging": "^0.12.22", + "@fingerprintjs/fingerprintjs": "^5.1.0", + "@firebase/analytics": "^0.10.20", + "@firebase/app": "^0.14.9", + "@firebase/auth": "^1.12.1", + "@firebase/firestore": "^4.12.0", + "@firebase/messaging": "^0.12.24", "@jsreport/browser-client": "^3.1.0", "@reduxjs/toolkit": "^2.11.2", - "@sentry/cli": "^3.2.2", - "@sentry/react": "^10.40.0", + "@sentry/cli": "^3.3.3", + "@sentry/react": "^10.43.0", "@sentry/vite-plugin": "^4.9.1", "@splitsoftware/splitio-react": "^2.6.1", "@tanem/react-nprogress": "^5.0.63", - "antd": "^6.3.1", + "antd": "^6.3.3", "apollo-link-logger": "^3.0.0", "autosize": "^6.0.1", - "axios": "^1.13.5", + "axios": "^1.13.6", "classnames": "^2.5.1", "css-box-model": "^1.2.1", - "dayjs": "^1.11.19", + "dayjs": "^1.11.20", "dayjs-business-days2": "^1.3.2", "dinero.js": "^1.9.1", "dotenv": "^17.3.1", "env-cmd": "^11.0.0", "exifr": "^7.1.3", - "graphql": "^16.13.0", + "graphql": "^16.13.1", "graphql-ws": "^6.0.7", - "i18next": "^25.8.13", + "i18next": "^25.8.18", "i18next-browser-languagedetector": "^8.2.1", "immutability-helper": "^3.1.1", - "libphonenumber-js": "^1.12.38", - "lightningcss": "^1.31.1", - "logrocket": "^12.0.0", + "libphonenumber-js": "^1.12.40", + "lightningcss": "^1.32.0", + "logrocket": "^12.1.0", "markerjs2": "^2.32.7", "memoize-one": "^6.0.0", "normalize-url": "^8.1.1", "object-hash": "^3.0.0", "phone": "^3.1.71", - "posthog-js": "^1.355.0", + "posthog-js": "^1.360.2", "prop-types": "^15.8.1", "query-string": "^9.3.1", "raf-schd": "^4.0.3", @@ -65,8 +65,8 @@ "react-dom": "^19.2.4", "react-grid-gallery": "^1.0.1", "react-grid-layout": "^2.2.2", - "react-i18next": "^16.5.4", - "react-icons": "^5.5.0", + "react-i18next": "^16.5.8", + "react-icons": "^5.6.0", "react-image-lightbox": "^5.1.4", "react-markdown": "^10.1.0", "react-number-format": "^5.4.3", @@ -76,8 +76,8 @@ "react-resizable": "^3.1.3", "react-router-dom": "^7.13.1", "react-sticky": "^6.0.3", - "react-virtuoso": "^4.18.1", - "recharts": "^3.7.0", + "react-virtuoso": "^4.18.3", + "recharts": "^3.8.0", "redux": "^5.0.1", "redux-actions": "^3.0.3", "redux-persist": "^6.0.0", @@ -85,7 +85,7 @@ "redux-state-sync": "^3.1.4", "reselect": "^5.1.1", "rxjs": "^7.8.2", - "sass": "^1.97.3", + "sass": "^1.98.0", "socket.io-client": "^4.8.3", "styled-components": "^6.3.11", "vite-plugin-ejs": "^1.7.0", @@ -140,7 +140,7 @@ "@ant-design/icons": "^6.1.0", "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@babel/preset-react": "^7.28.5", - "@dotenvx/dotenvx": "^1.52.0", + "@dotenvx/dotenvx": "^1.55.1", "@emotion/babel-plugin": "^11.13.5", "@emotion/react": "^11.14.0", "@eslint/js": "^9.39.2", @@ -156,9 +156,9 @@ "eslint": "^9.39.2", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-compiler": "^19.1.0-rc.2", - "globals": "^17.3.0", + "globals": "^17.4.0", "jsdom": "^28.1.0", - "memfs": "^4.56.10", + "memfs": "^4.56.11", "os-browserify": "^0.3.0", "playwright": "^1.58.2", "react-error-overlay": "^6.1.0", @@ -170,7 +170,7 @@ "vite-plugin-node-polyfills": "^0.25.0", "vite-plugin-pwa": "^1.2.0", "vite-plugin-style-import": "^2.0.0", - "vitest": "^4.0.18", + "vitest": "^4.1.0", "workbox-window": "^7.4.0" } } diff --git a/client/src/components/_test/test.page.jsx b/client/src/components/_test/test.page.jsx index 87ef90e95..a50a7d894 100644 --- a/client/src/components/_test/test.page.jsx +++ b/client/src/components/_test/test.page.jsx @@ -1,7 +1,11 @@ -import { Button } from "antd"; +import { Button, Card, Divider, Form, Space, Typography } from "antd"; import { connect } from "react-redux"; +import queryString from "query-string"; +import { useLocation } from "react-router-dom"; import { createStructuredSelector } from "reselect"; import { setModalContext } from "../../redux/modals/modals.actions"; +import { PayrollLaborAllocationsTable } from "../labor-allocations-table/labor-allocations-table.payroll.component.jsx"; +import { TimeTicketTaskModalComponent } from "../time-ticket-task-modal/time-ticket-task-modal.component.jsx"; const mapStateToProps = createStructuredSelector({}); @@ -9,8 +13,109 @@ const mapDispatchToProps = (dispatch) => ({ setRefundPaymentContext: (context) => dispatch(setModalContext({ context: context, modal: "refund_payment" })) }); +const commissionCutFixture = { + bodyshop: { + features: { + timetickets: true + }, + employees: [ + { id: "emp-1", first_name: "Avery", last_name: "Johnson" }, + { id: "emp-2", first_name: "Morgan", last_name: "Lee" } + ], + md_tasks_presets: { + presets: [ + { + name: "Body Prep", + percent: 50, + hourstype: ["LAA", "LAB"], + nextstatus: "In Progress" + } + ] + } + }, + jobId: "fixture-job-1", + joblines: [ + { + id: "line-1", + mod_lbr_ty: "LAA", + mod_lb_hrs: 4, + assigned_team: "team-1", + convertedtolbr: false + } + ], + previewValues: { + task: "Body Prep", + timetickets: [ + { + employeeid: "emp-1", + cost_center: "Body", + ciecacode: "LAA", + productivehrs: 2, + rate: 40, + payoutamount: 80, + payout_context: { + payout_method: "commission" + } + }, + { + employeeid: "emp-2", + cost_center: "Refinish", + ciecacode: "LAB", + productivehrs: 1, + rate: 28, + payoutamount: 28, + payout_context: { + payout_method: "hourly" + } + } + ] + } +}; + +function CommissionCutHarness() { + const [form] = Form.useForm(); + + return ( + + Commission Cut Test Harness + + This fixture keeps commission-cut browser checks stable by rendering representative payroll and preview UI with + local data. + + + {}} + /> + + + +
+ + +
+
+ ); +} + function Test({ setRefundPaymentContext, refundPaymentModal }) { + const search = queryString.parse(useLocation().search); console.log("refundPaymentModal", refundPaymentModal); + + if (search.fixture === "commission-cut") { + return ; + } + return (
+ + ); + + fireEvent.click(screen.getByRole("button", { name: "Edit Adjustment" })); + + fireEvent.change(screen.getByRole("spinbutton"), { + target: { value: "3.7" } + }); + + fireEvent.click(screen.getByRole("button", { name: "Save" })); + + await waitFor(() => { + expect(updateAdjustmentsMock).toHaveBeenCalledWith({ + variables: { + jobId: "job-1", + job: { + lbr_adjustments: { + LAA: 3.7, + LAB: 0.5 + } + } + }, + refetchQueries: ["QUERY_JOB"] + }); + }); + + expect(jobmodifylbradjMock).toHaveBeenCalledWith({ + mod_lbr_ty: "LAA", + hours: 2.5 + }); + expect(insertAuditTrailMock).toHaveBeenCalledWith({ + jobid: "job-1", + operation: "audit-entry", + type: "jobmodifylbradj" + }); + expect(notification.success).toHaveBeenCalledWith({ + title: "Saved" + }); + }); +}); diff --git a/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx b/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx index 3bcc32f14..02a9366f6 100644 --- a/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx +++ b/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx @@ -21,6 +21,8 @@ const mapStateToProps = createStructuredSelector({ technician: selectTechnician }); +const getRequestErrorMessage = (error) => error?.response?.data?.error || error?.message || ""; + export function PayrollLaborAllocationsTable({ jobId, joblines, @@ -43,16 +45,23 @@ export function PayrollLaborAllocationsTable({ }); const notification = useNotification(); - useEffect(() => { - async function CalculateTotals() { + const loadTotals = async () => { + try { const { data } = await axios.post("/payroll/calculatelabor", { jobid: jobId }); setTotals(data); + } catch (error) { + setTotals([]); + notification.error({ + title: getRequestErrorMessage(error) + }); } + }; + useEffect(() => { if (!!joblines && !!timetickets && !!bodyshop) { - CalculateTotals(); + loadTotals(); } if (!jobId) setTotals([]); }, [joblines, timetickets, bodyshop, adjustments, jobId]); @@ -210,28 +219,36 @@ export function PayrollLaborAllocationsTable({ } > -
- - - - - - - - - - - - - {(fields, { add, remove, move }) => { - return ( -
- {fields.map((field, index) => ( - - - - - - - - - - - - - - - - - - - - - + {isTeamHydrating ? ( + + ) : ( + + + + + + + + + + + + + + {(fields, { add, remove, move }) => { + return ( +
+ {fields.map((field, index) => { + const teamMember = normalizeTeamMember(teamMembers[field.name]); - + + +