dp-widgets-framework 1.7.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.esm.js +218 -8
- package/dist/index.js +217 -7
- package/package.json +2 -1
package/dist/index.esm.js
CHANGED
|
@@ -7,7 +7,7 @@ import * as LabelPrimitive from '@radix-ui/react-label';
|
|
|
7
7
|
import { cva } from 'class-variance-authority';
|
|
8
8
|
import * as SwitchPrimitives from '@radix-ui/react-switch';
|
|
9
9
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
10
|
-
import { ChevronDown, ChevronUp, Check, AlertCircle, MoveUp, MoveDown, Trash2, Plus, Bot, Type, Layout, LayoutGrid, BarChart as BarChart$1, Filter, Search, ArrowUp, ArrowDown, ChevronRight, RefreshCw,
|
|
10
|
+
import { ChevronDown, ChevronUp, Check, AlertCircle, MoveUp, MoveDown, Trash2, Plus, Bot, Type, Layout, LayoutGrid, BarChart as BarChart$1, Filter, Search, ArrowUp, ArrowDown, ChevronRight, RefreshCw, Loader2, Download, Send, X, AlignVerticalSpaceAround, LineChart as LineChart$1, PieChart as PieChart$1, Table, FileText, SlidersHorizontal, GripHorizontal, Edit, MessageCircleX, ChevronLeft, Maximize2, Grid3X3, Edit2 } from 'lucide-react';
|
|
11
11
|
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|
12
12
|
import { Slot, createSlot, createSlottable } from '@radix-ui/react-slot';
|
|
13
13
|
import { debounce as debounce$1 } from 'lodash';
|
|
@@ -17,6 +17,7 @@ import { v4 } from 'uuid';
|
|
|
17
17
|
import * as ReactDOM from 'react-dom';
|
|
18
18
|
import { TextMessage, Role } from '@copilotkit/runtime-client-gql';
|
|
19
19
|
import { CopilotKit, useCopilotContext, useCoAgent, useCopilotChat } from '@copilotkit/react-core';
|
|
20
|
+
import jsPDF from 'jspdf';
|
|
20
21
|
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
21
22
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
22
23
|
import { format } from 'date-fns';
|
|
@@ -44409,6 +44410,175 @@ function SpacerWidget({ widget }) {
|
|
|
44409
44410
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full", style: styles });
|
|
44410
44411
|
}
|
|
44411
44412
|
|
|
44413
|
+
const WISENBAKER_PRIMARY = "#8f002d";
|
|
44414
|
+
const WISENBAKER_GRAY = "#475569";
|
|
44415
|
+
function parseMarkdown(text) {
|
|
44416
|
+
const segments = [];
|
|
44417
|
+
const regex = /\*\*(.+?)\*\*/g;
|
|
44418
|
+
let lastIndex = 0;
|
|
44419
|
+
let match;
|
|
44420
|
+
while ((match = regex.exec(text)) !== null) {
|
|
44421
|
+
if (match.index > lastIndex) {
|
|
44422
|
+
segments.push({ text: text.slice(lastIndex, match.index), bold: false });
|
|
44423
|
+
}
|
|
44424
|
+
segments.push({ text: match[1], bold: true });
|
|
44425
|
+
lastIndex = regex.lastIndex;
|
|
44426
|
+
}
|
|
44427
|
+
if (lastIndex < text.length) {
|
|
44428
|
+
segments.push({ text: text.slice(lastIndex), bold: false });
|
|
44429
|
+
}
|
|
44430
|
+
return segments.length > 0 ? segments : [{ text, bold: false }];
|
|
44431
|
+
}
|
|
44432
|
+
function formatLine(line) {
|
|
44433
|
+
const bulletMatch = line.match(/^(\s*)[\*\-•]\s+(.*)$/);
|
|
44434
|
+
if (bulletMatch) {
|
|
44435
|
+
const indent = bulletMatch[1].length;
|
|
44436
|
+
return { text: bulletMatch[2], isBullet: true, indent };
|
|
44437
|
+
}
|
|
44438
|
+
const numberedMatch = line.match(/^(\s*)\d+\.\s+(.*)$/);
|
|
44439
|
+
if (numberedMatch) {
|
|
44440
|
+
const indent = numberedMatch[1].length;
|
|
44441
|
+
return { text: numberedMatch[2], isBullet: true, indent };
|
|
44442
|
+
}
|
|
44443
|
+
return { text: line, isBullet: false, indent: 0 };
|
|
44444
|
+
}
|
|
44445
|
+
function generateExportFilename(widgetId) {
|
|
44446
|
+
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
44447
|
+
return `NSight_Chat_Export_${widgetId}_${date}.pdf`;
|
|
44448
|
+
}
|
|
44449
|
+
function exportChatToPDF(options) {
|
|
44450
|
+
const { widgetId, messages, dashboardName } = options;
|
|
44451
|
+
const doc = new jsPDF();
|
|
44452
|
+
let yPosition = 25;
|
|
44453
|
+
const pageHeight = doc.internal.pageSize.height;
|
|
44454
|
+
const pageWidth = doc.internal.pageSize.width;
|
|
44455
|
+
const margin = 20;
|
|
44456
|
+
const contentWidth = pageWidth - margin * 2;
|
|
44457
|
+
const maxWidth = contentWidth - 10;
|
|
44458
|
+
const checkPageBreak = (requiredSpace = 20) => {
|
|
44459
|
+
if (yPosition > pageHeight - requiredSpace) {
|
|
44460
|
+
doc.addPage();
|
|
44461
|
+
yPosition = 25;
|
|
44462
|
+
}
|
|
44463
|
+
};
|
|
44464
|
+
const renderFormattedText = (text, x, maxW, baseIndent = 0) => {
|
|
44465
|
+
const lines = text.split("\n");
|
|
44466
|
+
lines.forEach((line) => {
|
|
44467
|
+
const { text: lineText, isBullet, indent } = formatLine(line);
|
|
44468
|
+
const lineIndent = x + baseIndent + indent * 2;
|
|
44469
|
+
if (isBullet) {
|
|
44470
|
+
checkPageBreak(10);
|
|
44471
|
+
doc.setFont("helvetica", "normal");
|
|
44472
|
+
doc.text("\u2022", lineIndent, yPosition);
|
|
44473
|
+
}
|
|
44474
|
+
const textX = isBullet ? lineIndent + 5 : lineIndent;
|
|
44475
|
+
const textMaxWidth = maxW - (textX - x);
|
|
44476
|
+
const segments = parseMarkdown(lineText);
|
|
44477
|
+
let currentLine = "";
|
|
44478
|
+
let currentX = textX;
|
|
44479
|
+
segments.forEach((segment) => {
|
|
44480
|
+
doc.setFont("helvetica", segment.bold ? "bold" : "normal");
|
|
44481
|
+
const words = segment.text.split(" ");
|
|
44482
|
+
words.forEach((word, wordIndex) => {
|
|
44483
|
+
const testLine = currentLine + (currentLine ? " " : "") + word;
|
|
44484
|
+
const testWidth = doc.getTextWidth(testLine);
|
|
44485
|
+
if (testWidth > textMaxWidth && currentLine) {
|
|
44486
|
+
checkPageBreak(10);
|
|
44487
|
+
doc.text(currentLine, currentX, yPosition);
|
|
44488
|
+
yPosition += 5;
|
|
44489
|
+
currentLine = word;
|
|
44490
|
+
currentX = isBullet ? lineIndent + 5 : x + baseIndent;
|
|
44491
|
+
} else {
|
|
44492
|
+
currentLine = testLine;
|
|
44493
|
+
}
|
|
44494
|
+
});
|
|
44495
|
+
});
|
|
44496
|
+
if (currentLine) {
|
|
44497
|
+
checkPageBreak(10);
|
|
44498
|
+
const lastSegment = segments[segments.length - 1];
|
|
44499
|
+
doc.setFont("helvetica", (lastSegment == null ? void 0 : lastSegment.bold) ? "bold" : "normal");
|
|
44500
|
+
doc.text(currentLine, currentX, yPosition);
|
|
44501
|
+
yPosition += 5;
|
|
44502
|
+
}
|
|
44503
|
+
});
|
|
44504
|
+
};
|
|
44505
|
+
doc.setFontSize(18);
|
|
44506
|
+
doc.setFont("helvetica", "bold");
|
|
44507
|
+
doc.setTextColor(WISENBAKER_PRIMARY);
|
|
44508
|
+
doc.text("Wisenbaker AI Analytics", margin, yPosition);
|
|
44509
|
+
yPosition += 8;
|
|
44510
|
+
doc.setFontSize(11);
|
|
44511
|
+
doc.setFont("helvetica", "normal");
|
|
44512
|
+
doc.setTextColor(WISENBAKER_GRAY);
|
|
44513
|
+
doc.text("Chat Export", margin, yPosition);
|
|
44514
|
+
yPosition += 12;
|
|
44515
|
+
doc.setFontSize(9);
|
|
44516
|
+
doc.setTextColor("#666666");
|
|
44517
|
+
if (dashboardName) {
|
|
44518
|
+
doc.setFont("helvetica", "bold");
|
|
44519
|
+
doc.text("Dashboard:", margin, yPosition);
|
|
44520
|
+
doc.setFont("helvetica", "normal");
|
|
44521
|
+
doc.text(dashboardName, margin + 38, yPosition);
|
|
44522
|
+
yPosition += 5;
|
|
44523
|
+
}
|
|
44524
|
+
doc.setFont("helvetica", "bold");
|
|
44525
|
+
doc.text("Exported:", margin, yPosition);
|
|
44526
|
+
doc.setFont("helvetica", "normal");
|
|
44527
|
+
doc.text((/* @__PURE__ */ new Date()).toLocaleString(), margin + 38, yPosition);
|
|
44528
|
+
doc.setFont("helvetica", "bold");
|
|
44529
|
+
doc.text("Messages:", margin + 100, yPosition);
|
|
44530
|
+
doc.setFont("helvetica", "normal");
|
|
44531
|
+
doc.text(String(messages.length), margin + 130, yPosition);
|
|
44532
|
+
yPosition += 12;
|
|
44533
|
+
doc.setDrawColor(200, 200, 200);
|
|
44534
|
+
doc.setLineWidth(0.5);
|
|
44535
|
+
doc.line(margin, yPosition, pageWidth - margin, yPosition);
|
|
44536
|
+
yPosition += 8;
|
|
44537
|
+
messages.forEach((message, index) => {
|
|
44538
|
+
checkPageBreak(30);
|
|
44539
|
+
const isUser = message.role === "user";
|
|
44540
|
+
const roleLabel = isUser ? "You" : "AI Assistant";
|
|
44541
|
+
const timestamp = message.createdAt ? new Date(message.createdAt).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) : "";
|
|
44542
|
+
const bgColor = isUser ? [143, 0, 45] : [241, 243, 245];
|
|
44543
|
+
doc.setFillColor(bgColor[0], bgColor[1], bgColor[2]);
|
|
44544
|
+
doc.setFontSize(9);
|
|
44545
|
+
doc.setFont("helvetica", "bold");
|
|
44546
|
+
doc.setTextColor(isUser ? WISENBAKER_PRIMARY : WISENBAKER_GRAY);
|
|
44547
|
+
doc.text(roleLabel, margin, yPosition);
|
|
44548
|
+
if (timestamp) {
|
|
44549
|
+
doc.setFont("helvetica", "normal");
|
|
44550
|
+
doc.setTextColor("#888888");
|
|
44551
|
+
doc.text(timestamp, margin + doc.getTextWidth(roleLabel) + 5, yPosition);
|
|
44552
|
+
}
|
|
44553
|
+
yPosition += 6;
|
|
44554
|
+
doc.setFontSize(10);
|
|
44555
|
+
doc.setTextColor("#333333");
|
|
44556
|
+
doc.setFont("helvetica", "normal");
|
|
44557
|
+
renderFormattedText(message.content, margin + 5, maxWidth - 5, 0);
|
|
44558
|
+
yPosition += 8;
|
|
44559
|
+
if (index < messages.length - 1) {
|
|
44560
|
+
doc.setDrawColor(230, 230, 230);
|
|
44561
|
+
doc.setLineWidth(0.3);
|
|
44562
|
+
doc.line(margin + 10, yPosition - 4, pageWidth - margin - 10, yPosition - 4);
|
|
44563
|
+
}
|
|
44564
|
+
});
|
|
44565
|
+
const totalPages = doc.getNumberOfPages();
|
|
44566
|
+
for (let i = 1; i <= totalPages; i++) {
|
|
44567
|
+
doc.setPage(i);
|
|
44568
|
+
doc.setFontSize(8);
|
|
44569
|
+
doc.setTextColor("#999999");
|
|
44570
|
+
doc.setFont("helvetica", "normal");
|
|
44571
|
+
doc.text(
|
|
44572
|
+
`Wisenbaker AI Analytics \u2022 Page ${i} of ${totalPages}`,
|
|
44573
|
+
pageWidth / 2,
|
|
44574
|
+
pageHeight - 10,
|
|
44575
|
+
{ align: "center" }
|
|
44576
|
+
);
|
|
44577
|
+
}
|
|
44578
|
+
const filename = generateExportFilename(widgetId);
|
|
44579
|
+
doc.save(filename);
|
|
44580
|
+
}
|
|
44581
|
+
|
|
44412
44582
|
var __defProp$b = Object.defineProperty;
|
|
44413
44583
|
var __defProps$9 = Object.defineProperties;
|
|
44414
44584
|
var __getOwnPropDescs$9 = Object.getOwnPropertyDescriptors;
|
|
@@ -44457,7 +44627,8 @@ function CopilotKitChatbot({
|
|
|
44457
44627
|
styles,
|
|
44458
44628
|
onResetReady,
|
|
44459
44629
|
widgetIds,
|
|
44460
|
-
datasetId
|
|
44630
|
+
datasetId,
|
|
44631
|
+
dashboardName
|
|
44461
44632
|
}) {
|
|
44462
44633
|
var _a, _b, _c, _d;
|
|
44463
44634
|
const { threadId, setThreadId } = useCopilotContext();
|
|
@@ -44474,7 +44645,24 @@ function CopilotKitChatbot({
|
|
|
44474
44645
|
const { reset, visibleMessages, appendMessage, isLoading } = useCopilotChat();
|
|
44475
44646
|
const [inputValue, setInputValue] = useState("");
|
|
44476
44647
|
const [chatMessages, setChatMessages] = useState([]);
|
|
44648
|
+
const [isExporting, setIsExporting] = useState(false);
|
|
44477
44649
|
const messagesEndRef = React__default.useRef(null);
|
|
44650
|
+
const handleExport = async () => {
|
|
44651
|
+
if (chatMessages.length === 0) return;
|
|
44652
|
+
setIsExporting(true);
|
|
44653
|
+
try {
|
|
44654
|
+
exportChatToPDF({
|
|
44655
|
+
widgetId: widget.id,
|
|
44656
|
+
widgetTitle: widget.title,
|
|
44657
|
+
messages: chatMessages,
|
|
44658
|
+
dashboardName
|
|
44659
|
+
});
|
|
44660
|
+
} catch (error) {
|
|
44661
|
+
console.error("Export failed:", error);
|
|
44662
|
+
} finally {
|
|
44663
|
+
setIsExporting(false);
|
|
44664
|
+
}
|
|
44665
|
+
};
|
|
44478
44666
|
const scrollToBottom = () => {
|
|
44479
44667
|
var _a2;
|
|
44480
44668
|
const el = messagesEndRef.current;
|
|
@@ -44549,6 +44737,25 @@ function CopilotKitChatbot({
|
|
|
44549
44737
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-medium", children: widget.title })
|
|
44550
44738
|
] }) }),
|
|
44551
44739
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 h-full flex flex-col", children: [
|
|
44740
|
+
chatMessages.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-start px-4 py-2 border-b border-gray-100", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
44741
|
+
"button",
|
|
44742
|
+
{
|
|
44743
|
+
onClick: handleExport,
|
|
44744
|
+
disabled: isExporting,
|
|
44745
|
+
className: cn(
|
|
44746
|
+
"flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md",
|
|
44747
|
+
"bg-gray-100 border border-gray-200",
|
|
44748
|
+
"text-gray-700 hover:bg-gray-200 hover:border-gray-300",
|
|
44749
|
+
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
44750
|
+
"transition-colors duration-150"
|
|
44751
|
+
),
|
|
44752
|
+
title: "Export conversation as PDF",
|
|
44753
|
+
children: [
|
|
44754
|
+
isExporting ? /* @__PURE__ */ jsxRuntimeExports.jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "h-3.5 w-3.5" }),
|
|
44755
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Export PDF" })
|
|
44756
|
+
]
|
|
44757
|
+
}
|
|
44758
|
+
) }),
|
|
44552
44759
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto p-4 space-y-4", children: chatMessages.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center text-gray-500 text-xs mt-8", children: ((_b = widget.config) == null ? void 0 : _b.copilotInitialMessage) || ((_c = widget.config) == null ? void 0 : _c.placeholder) || "How can I help you today?" }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
44553
44760
|
chatMessages.map((message) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
44554
44761
|
"div",
|
|
@@ -44624,7 +44831,8 @@ function ChatbotWidget({
|
|
|
44624
44831
|
widgetBackendUrl,
|
|
44625
44832
|
onResetReady,
|
|
44626
44833
|
widgetIds,
|
|
44627
|
-
datasetId
|
|
44834
|
+
datasetId,
|
|
44835
|
+
dashboardName
|
|
44628
44836
|
}) {
|
|
44629
44837
|
var _a, _b;
|
|
44630
44838
|
const styles = getStyleValues$4((_a = widget.config) == null ? void 0 : _a.styles);
|
|
@@ -44648,7 +44856,8 @@ function ChatbotWidget({
|
|
|
44648
44856
|
styles,
|
|
44649
44857
|
onResetReady,
|
|
44650
44858
|
widgetIds,
|
|
44651
|
-
datasetId
|
|
44859
|
+
datasetId,
|
|
44860
|
+
dashboardName
|
|
44652
44861
|
}
|
|
44653
44862
|
)
|
|
44654
44863
|
}
|
|
@@ -47165,7 +47374,8 @@ function WidgetRenderer({
|
|
|
47165
47374
|
datasetId,
|
|
47166
47375
|
pageId,
|
|
47167
47376
|
onApplyFilters,
|
|
47168
|
-
isEditing = false
|
|
47377
|
+
isEditing = false,
|
|
47378
|
+
dashboardName
|
|
47169
47379
|
}) {
|
|
47170
47380
|
const handleConfigUpdate = (config) => {
|
|
47171
47381
|
if (onConfigUpdate) {
|
|
@@ -47197,7 +47407,7 @@ function WidgetRenderer({
|
|
|
47197
47407
|
}
|
|
47198
47408
|
);
|
|
47199
47409
|
case "chatbot":
|
|
47200
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(ChatbotWidget, { widget, showHeader: false, widgetBackendUrl, onResetReady, widgetIds, datasetId });
|
|
47410
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(ChatbotWidget, { widget, showHeader: false, widgetBackendUrl, onResetReady, widgetIds, datasetId, dashboardName });
|
|
47201
47411
|
case "filters":
|
|
47202
47412
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
47203
47413
|
FiltersWidget,
|
|
@@ -48806,7 +49016,7 @@ function WidgetDashboard({
|
|
|
48806
49016
|
containerPadding: [0, 0],
|
|
48807
49017
|
margin: [16, 16],
|
|
48808
49018
|
children: displayWidgets.map((w) => {
|
|
48809
|
-
var _a, _b;
|
|
49019
|
+
var _a, _b, _c;
|
|
48810
49020
|
const filterStatus = w.type === "agent" ? getWidgetFilterStatus(w.id) : null;
|
|
48811
49021
|
const badgeInfo = filterStatus ? getFilterStatusBadge(filterStatus.status) : null;
|
|
48812
49022
|
const isFocusMode = focusWidgetId && w.id === focusWidgetId;
|
|
@@ -48845,7 +49055,7 @@ function WidgetDashboard({
|
|
|
48845
49055
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { onClick: () => handleClearChat(w == null ? void 0 : w.id), onMouseOver: () => setVisibleClearButton(w == null ? void 0 : w.id), onMouseLeave: () => setVisibleClearButton(""), className: "absolute top-[12px] right-0 z-40 flex align-middle justify-center gap-2 text-sm px-4 py-2 border-primary-300 rounded-l-sm w-fit bg-primary-700 text-white cursor-pointer shadow-md transition-all", children: /* @__PURE__ */ jsxRuntimeExports.jsx(MessageCircleX, { className: "w-5 h-5" }) }),
|
|
48846
49056
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `absolute top-[56px] right-[16px] z-50 w-max py-1 text-xs px-2 rounded-sm text-white bg-gray-950 ${visibleClearButton === (w == null ? void 0 : w.id) ? "block" : "hidden"}`, children: "Clear Chat" })
|
|
48847
49057
|
] }),
|
|
48848
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(WidgetRenderer, { widget: w, widgetBackendUrl, onResetReady: handleResetReady, widgetIds: widgets.filter((widget) => widget.type !== "chatbot").map((widget) => widget.id), datasetId, pageId, onApplyFilters, isEditing })
|
|
49058
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(WidgetRenderer, { widget: w, widgetBackendUrl, onResetReady: handleResetReady, widgetIds: widgets.filter((widget) => widget.type !== "chatbot").map((widget) => widget.id), datasetId, pageId, onApplyFilters, isEditing, dashboardName: ((_c = pageData == null ? void 0 : pageData.basic) == null ? void 0 : _c.title) || (pageData == null ? void 0 : pageData.name) || (pageData == null ? void 0 : pageData.title) })
|
|
48849
49059
|
] })
|
|
48850
49060
|
] }, w.id);
|
|
48851
49061
|
})
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ var uuid = require('uuid');
|
|
|
18
18
|
var ReactDOM = require('react-dom');
|
|
19
19
|
var runtimeClientGql = require('@copilotkit/runtime-client-gql');
|
|
20
20
|
var reactCore = require('@copilotkit/react-core');
|
|
21
|
+
var jsPDF = require('jspdf');
|
|
21
22
|
var CheckboxPrimitive = require('@radix-ui/react-checkbox');
|
|
22
23
|
var DialogPrimitive = require('@radix-ui/react-dialog');
|
|
23
24
|
var dateFns = require('date-fns');
|
|
@@ -44437,6 +44438,175 @@ function SpacerWidget({ widget }) {
|
|
|
44437
44438
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-full", style: styles });
|
|
44438
44439
|
}
|
|
44439
44440
|
|
|
44441
|
+
const WISENBAKER_PRIMARY = "#8f002d";
|
|
44442
|
+
const WISENBAKER_GRAY = "#475569";
|
|
44443
|
+
function parseMarkdown(text) {
|
|
44444
|
+
const segments = [];
|
|
44445
|
+
const regex = /\*\*(.+?)\*\*/g;
|
|
44446
|
+
let lastIndex = 0;
|
|
44447
|
+
let match;
|
|
44448
|
+
while ((match = regex.exec(text)) !== null) {
|
|
44449
|
+
if (match.index > lastIndex) {
|
|
44450
|
+
segments.push({ text: text.slice(lastIndex, match.index), bold: false });
|
|
44451
|
+
}
|
|
44452
|
+
segments.push({ text: match[1], bold: true });
|
|
44453
|
+
lastIndex = regex.lastIndex;
|
|
44454
|
+
}
|
|
44455
|
+
if (lastIndex < text.length) {
|
|
44456
|
+
segments.push({ text: text.slice(lastIndex), bold: false });
|
|
44457
|
+
}
|
|
44458
|
+
return segments.length > 0 ? segments : [{ text, bold: false }];
|
|
44459
|
+
}
|
|
44460
|
+
function formatLine(line) {
|
|
44461
|
+
const bulletMatch = line.match(/^(\s*)[\*\-•]\s+(.*)$/);
|
|
44462
|
+
if (bulletMatch) {
|
|
44463
|
+
const indent = bulletMatch[1].length;
|
|
44464
|
+
return { text: bulletMatch[2], isBullet: true, indent };
|
|
44465
|
+
}
|
|
44466
|
+
const numberedMatch = line.match(/^(\s*)\d+\.\s+(.*)$/);
|
|
44467
|
+
if (numberedMatch) {
|
|
44468
|
+
const indent = numberedMatch[1].length;
|
|
44469
|
+
return { text: numberedMatch[2], isBullet: true, indent };
|
|
44470
|
+
}
|
|
44471
|
+
return { text: line, isBullet: false, indent: 0 };
|
|
44472
|
+
}
|
|
44473
|
+
function generateExportFilename(widgetId) {
|
|
44474
|
+
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
44475
|
+
return `NSight_Chat_Export_${widgetId}_${date}.pdf`;
|
|
44476
|
+
}
|
|
44477
|
+
function exportChatToPDF(options) {
|
|
44478
|
+
const { widgetId, messages, dashboardName } = options;
|
|
44479
|
+
const doc = new jsPDF();
|
|
44480
|
+
let yPosition = 25;
|
|
44481
|
+
const pageHeight = doc.internal.pageSize.height;
|
|
44482
|
+
const pageWidth = doc.internal.pageSize.width;
|
|
44483
|
+
const margin = 20;
|
|
44484
|
+
const contentWidth = pageWidth - margin * 2;
|
|
44485
|
+
const maxWidth = contentWidth - 10;
|
|
44486
|
+
const checkPageBreak = (requiredSpace = 20) => {
|
|
44487
|
+
if (yPosition > pageHeight - requiredSpace) {
|
|
44488
|
+
doc.addPage();
|
|
44489
|
+
yPosition = 25;
|
|
44490
|
+
}
|
|
44491
|
+
};
|
|
44492
|
+
const renderFormattedText = (text, x, maxW, baseIndent = 0) => {
|
|
44493
|
+
const lines = text.split("\n");
|
|
44494
|
+
lines.forEach((line) => {
|
|
44495
|
+
const { text: lineText, isBullet, indent } = formatLine(line);
|
|
44496
|
+
const lineIndent = x + baseIndent + indent * 2;
|
|
44497
|
+
if (isBullet) {
|
|
44498
|
+
checkPageBreak(10);
|
|
44499
|
+
doc.setFont("helvetica", "normal");
|
|
44500
|
+
doc.text("\u2022", lineIndent, yPosition);
|
|
44501
|
+
}
|
|
44502
|
+
const textX = isBullet ? lineIndent + 5 : lineIndent;
|
|
44503
|
+
const textMaxWidth = maxW - (textX - x);
|
|
44504
|
+
const segments = parseMarkdown(lineText);
|
|
44505
|
+
let currentLine = "";
|
|
44506
|
+
let currentX = textX;
|
|
44507
|
+
segments.forEach((segment) => {
|
|
44508
|
+
doc.setFont("helvetica", segment.bold ? "bold" : "normal");
|
|
44509
|
+
const words = segment.text.split(" ");
|
|
44510
|
+
words.forEach((word, wordIndex) => {
|
|
44511
|
+
const testLine = currentLine + (currentLine ? " " : "") + word;
|
|
44512
|
+
const testWidth = doc.getTextWidth(testLine);
|
|
44513
|
+
if (testWidth > textMaxWidth && currentLine) {
|
|
44514
|
+
checkPageBreak(10);
|
|
44515
|
+
doc.text(currentLine, currentX, yPosition);
|
|
44516
|
+
yPosition += 5;
|
|
44517
|
+
currentLine = word;
|
|
44518
|
+
currentX = isBullet ? lineIndent + 5 : x + baseIndent;
|
|
44519
|
+
} else {
|
|
44520
|
+
currentLine = testLine;
|
|
44521
|
+
}
|
|
44522
|
+
});
|
|
44523
|
+
});
|
|
44524
|
+
if (currentLine) {
|
|
44525
|
+
checkPageBreak(10);
|
|
44526
|
+
const lastSegment = segments[segments.length - 1];
|
|
44527
|
+
doc.setFont("helvetica", (lastSegment == null ? void 0 : lastSegment.bold) ? "bold" : "normal");
|
|
44528
|
+
doc.text(currentLine, currentX, yPosition);
|
|
44529
|
+
yPosition += 5;
|
|
44530
|
+
}
|
|
44531
|
+
});
|
|
44532
|
+
};
|
|
44533
|
+
doc.setFontSize(18);
|
|
44534
|
+
doc.setFont("helvetica", "bold");
|
|
44535
|
+
doc.setTextColor(WISENBAKER_PRIMARY);
|
|
44536
|
+
doc.text("Wisenbaker AI Analytics", margin, yPosition);
|
|
44537
|
+
yPosition += 8;
|
|
44538
|
+
doc.setFontSize(11);
|
|
44539
|
+
doc.setFont("helvetica", "normal");
|
|
44540
|
+
doc.setTextColor(WISENBAKER_GRAY);
|
|
44541
|
+
doc.text("Chat Export", margin, yPosition);
|
|
44542
|
+
yPosition += 12;
|
|
44543
|
+
doc.setFontSize(9);
|
|
44544
|
+
doc.setTextColor("#666666");
|
|
44545
|
+
if (dashboardName) {
|
|
44546
|
+
doc.setFont("helvetica", "bold");
|
|
44547
|
+
doc.text("Dashboard:", margin, yPosition);
|
|
44548
|
+
doc.setFont("helvetica", "normal");
|
|
44549
|
+
doc.text(dashboardName, margin + 38, yPosition);
|
|
44550
|
+
yPosition += 5;
|
|
44551
|
+
}
|
|
44552
|
+
doc.setFont("helvetica", "bold");
|
|
44553
|
+
doc.text("Exported:", margin, yPosition);
|
|
44554
|
+
doc.setFont("helvetica", "normal");
|
|
44555
|
+
doc.text((/* @__PURE__ */ new Date()).toLocaleString(), margin + 38, yPosition);
|
|
44556
|
+
doc.setFont("helvetica", "bold");
|
|
44557
|
+
doc.text("Messages:", margin + 100, yPosition);
|
|
44558
|
+
doc.setFont("helvetica", "normal");
|
|
44559
|
+
doc.text(String(messages.length), margin + 130, yPosition);
|
|
44560
|
+
yPosition += 12;
|
|
44561
|
+
doc.setDrawColor(200, 200, 200);
|
|
44562
|
+
doc.setLineWidth(0.5);
|
|
44563
|
+
doc.line(margin, yPosition, pageWidth - margin, yPosition);
|
|
44564
|
+
yPosition += 8;
|
|
44565
|
+
messages.forEach((message, index) => {
|
|
44566
|
+
checkPageBreak(30);
|
|
44567
|
+
const isUser = message.role === "user";
|
|
44568
|
+
const roleLabel = isUser ? "You" : "AI Assistant";
|
|
44569
|
+
const timestamp = message.createdAt ? new Date(message.createdAt).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) : "";
|
|
44570
|
+
const bgColor = isUser ? [143, 0, 45] : [241, 243, 245];
|
|
44571
|
+
doc.setFillColor(bgColor[0], bgColor[1], bgColor[2]);
|
|
44572
|
+
doc.setFontSize(9);
|
|
44573
|
+
doc.setFont("helvetica", "bold");
|
|
44574
|
+
doc.setTextColor(isUser ? WISENBAKER_PRIMARY : WISENBAKER_GRAY);
|
|
44575
|
+
doc.text(roleLabel, margin, yPosition);
|
|
44576
|
+
if (timestamp) {
|
|
44577
|
+
doc.setFont("helvetica", "normal");
|
|
44578
|
+
doc.setTextColor("#888888");
|
|
44579
|
+
doc.text(timestamp, margin + doc.getTextWidth(roleLabel) + 5, yPosition);
|
|
44580
|
+
}
|
|
44581
|
+
yPosition += 6;
|
|
44582
|
+
doc.setFontSize(10);
|
|
44583
|
+
doc.setTextColor("#333333");
|
|
44584
|
+
doc.setFont("helvetica", "normal");
|
|
44585
|
+
renderFormattedText(message.content, margin + 5, maxWidth - 5, 0);
|
|
44586
|
+
yPosition += 8;
|
|
44587
|
+
if (index < messages.length - 1) {
|
|
44588
|
+
doc.setDrawColor(230, 230, 230);
|
|
44589
|
+
doc.setLineWidth(0.3);
|
|
44590
|
+
doc.line(margin + 10, yPosition - 4, pageWidth - margin - 10, yPosition - 4);
|
|
44591
|
+
}
|
|
44592
|
+
});
|
|
44593
|
+
const totalPages = doc.getNumberOfPages();
|
|
44594
|
+
for (let i = 1; i <= totalPages; i++) {
|
|
44595
|
+
doc.setPage(i);
|
|
44596
|
+
doc.setFontSize(8);
|
|
44597
|
+
doc.setTextColor("#999999");
|
|
44598
|
+
doc.setFont("helvetica", "normal");
|
|
44599
|
+
doc.text(
|
|
44600
|
+
`Wisenbaker AI Analytics \u2022 Page ${i} of ${totalPages}`,
|
|
44601
|
+
pageWidth / 2,
|
|
44602
|
+
pageHeight - 10,
|
|
44603
|
+
{ align: "center" }
|
|
44604
|
+
);
|
|
44605
|
+
}
|
|
44606
|
+
const filename = generateExportFilename(widgetId);
|
|
44607
|
+
doc.save(filename);
|
|
44608
|
+
}
|
|
44609
|
+
|
|
44440
44610
|
var __defProp$b = Object.defineProperty;
|
|
44441
44611
|
var __defProps$9 = Object.defineProperties;
|
|
44442
44612
|
var __getOwnPropDescs$9 = Object.getOwnPropertyDescriptors;
|
|
@@ -44485,7 +44655,8 @@ function CopilotKitChatbot({
|
|
|
44485
44655
|
styles,
|
|
44486
44656
|
onResetReady,
|
|
44487
44657
|
widgetIds,
|
|
44488
|
-
datasetId
|
|
44658
|
+
datasetId,
|
|
44659
|
+
dashboardName
|
|
44489
44660
|
}) {
|
|
44490
44661
|
var _a, _b, _c, _d;
|
|
44491
44662
|
const { threadId, setThreadId } = reactCore.useCopilotContext();
|
|
@@ -44502,7 +44673,24 @@ function CopilotKitChatbot({
|
|
|
44502
44673
|
const { reset, visibleMessages, appendMessage, isLoading } = reactCore.useCopilotChat();
|
|
44503
44674
|
const [inputValue, setInputValue] = React.useState("");
|
|
44504
44675
|
const [chatMessages, setChatMessages] = React.useState([]);
|
|
44676
|
+
const [isExporting, setIsExporting] = React.useState(false);
|
|
44505
44677
|
const messagesEndRef = React.useRef(null);
|
|
44678
|
+
const handleExport = async () => {
|
|
44679
|
+
if (chatMessages.length === 0) return;
|
|
44680
|
+
setIsExporting(true);
|
|
44681
|
+
try {
|
|
44682
|
+
exportChatToPDF({
|
|
44683
|
+
widgetId: widget.id,
|
|
44684
|
+
widgetTitle: widget.title,
|
|
44685
|
+
messages: chatMessages,
|
|
44686
|
+
dashboardName
|
|
44687
|
+
});
|
|
44688
|
+
} catch (error) {
|
|
44689
|
+
console.error("Export failed:", error);
|
|
44690
|
+
} finally {
|
|
44691
|
+
setIsExporting(false);
|
|
44692
|
+
}
|
|
44693
|
+
};
|
|
44506
44694
|
const scrollToBottom = () => {
|
|
44507
44695
|
var _a2;
|
|
44508
44696
|
const el = messagesEndRef.current;
|
|
@@ -44577,6 +44765,25 @@ function CopilotKitChatbot({
|
|
|
44577
44765
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-medium", children: widget.title })
|
|
44578
44766
|
] }) }),
|
|
44579
44767
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 h-full flex flex-col", children: [
|
|
44768
|
+
chatMessages.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-start px-4 py-2 border-b border-gray-100", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
44769
|
+
"button",
|
|
44770
|
+
{
|
|
44771
|
+
onClick: handleExport,
|
|
44772
|
+
disabled: isExporting,
|
|
44773
|
+
className: cn(
|
|
44774
|
+
"flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md",
|
|
44775
|
+
"bg-gray-100 border border-gray-200",
|
|
44776
|
+
"text-gray-700 hover:bg-gray-200 hover:border-gray-300",
|
|
44777
|
+
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
44778
|
+
"transition-colors duration-150"
|
|
44779
|
+
),
|
|
44780
|
+
title: "Export conversation as PDF",
|
|
44781
|
+
children: [
|
|
44782
|
+
isExporting ? /* @__PURE__ */ jsxRuntimeExports.jsx(lucideReact.Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(lucideReact.Download, { className: "h-3.5 w-3.5" }),
|
|
44783
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Export PDF" })
|
|
44784
|
+
]
|
|
44785
|
+
}
|
|
44786
|
+
) }),
|
|
44580
44787
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto p-4 space-y-4", children: chatMessages.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center text-gray-500 text-xs mt-8", children: ((_b = widget.config) == null ? void 0 : _b.copilotInitialMessage) || ((_c = widget.config) == null ? void 0 : _c.placeholder) || "How can I help you today?" }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
44581
44788
|
chatMessages.map((message) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
44582
44789
|
"div",
|
|
@@ -44652,7 +44859,8 @@ function ChatbotWidget({
|
|
|
44652
44859
|
widgetBackendUrl,
|
|
44653
44860
|
onResetReady,
|
|
44654
44861
|
widgetIds,
|
|
44655
|
-
datasetId
|
|
44862
|
+
datasetId,
|
|
44863
|
+
dashboardName
|
|
44656
44864
|
}) {
|
|
44657
44865
|
var _a, _b;
|
|
44658
44866
|
const styles = getStyleValues$4((_a = widget.config) == null ? void 0 : _a.styles);
|
|
@@ -44676,7 +44884,8 @@ function ChatbotWidget({
|
|
|
44676
44884
|
styles,
|
|
44677
44885
|
onResetReady,
|
|
44678
44886
|
widgetIds,
|
|
44679
|
-
datasetId
|
|
44887
|
+
datasetId,
|
|
44888
|
+
dashboardName
|
|
44680
44889
|
}
|
|
44681
44890
|
)
|
|
44682
44891
|
}
|
|
@@ -47193,7 +47402,8 @@ function WidgetRenderer({
|
|
|
47193
47402
|
datasetId,
|
|
47194
47403
|
pageId,
|
|
47195
47404
|
onApplyFilters,
|
|
47196
|
-
isEditing = false
|
|
47405
|
+
isEditing = false,
|
|
47406
|
+
dashboardName
|
|
47197
47407
|
}) {
|
|
47198
47408
|
const handleConfigUpdate = (config) => {
|
|
47199
47409
|
if (onConfigUpdate) {
|
|
@@ -47225,7 +47435,7 @@ function WidgetRenderer({
|
|
|
47225
47435
|
}
|
|
47226
47436
|
);
|
|
47227
47437
|
case "chatbot":
|
|
47228
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(ChatbotWidget, { widget, showHeader: false, widgetBackendUrl, onResetReady, widgetIds, datasetId });
|
|
47438
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(ChatbotWidget, { widget, showHeader: false, widgetBackendUrl, onResetReady, widgetIds, datasetId, dashboardName });
|
|
47229
47439
|
case "filters":
|
|
47230
47440
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
47231
47441
|
FiltersWidget,
|
|
@@ -48834,7 +49044,7 @@ function WidgetDashboard({
|
|
|
48834
49044
|
containerPadding: [0, 0],
|
|
48835
49045
|
margin: [16, 16],
|
|
48836
49046
|
children: displayWidgets.map((w) => {
|
|
48837
|
-
var _a, _b;
|
|
49047
|
+
var _a, _b, _c;
|
|
48838
49048
|
const filterStatus = w.type === "agent" ? getWidgetFilterStatus(w.id) : null;
|
|
48839
49049
|
const badgeInfo = filterStatus ? getFilterStatusBadge(filterStatus.status) : null;
|
|
48840
49050
|
const isFocusMode = focusWidgetId && w.id === focusWidgetId;
|
|
@@ -48873,7 +49083,7 @@ function WidgetDashboard({
|
|
|
48873
49083
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { onClick: () => handleClearChat(w == null ? void 0 : w.id), onMouseOver: () => setVisibleClearButton(w == null ? void 0 : w.id), onMouseLeave: () => setVisibleClearButton(""), className: "absolute top-[12px] right-0 z-40 flex align-middle justify-center gap-2 text-sm px-4 py-2 border-primary-300 rounded-l-sm w-fit bg-primary-700 text-white cursor-pointer shadow-md transition-all", children: /* @__PURE__ */ jsxRuntimeExports.jsx(lucideReact.MessageCircleX, { className: "w-5 h-5" }) }),
|
|
48874
49084
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `absolute top-[56px] right-[16px] z-50 w-max py-1 text-xs px-2 rounded-sm text-white bg-gray-950 ${visibleClearButton === (w == null ? void 0 : w.id) ? "block" : "hidden"}`, children: "Clear Chat" })
|
|
48875
49085
|
] }),
|
|
48876
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(WidgetRenderer, { widget: w, widgetBackendUrl, onResetReady: handleResetReady, widgetIds: widgets.filter((widget) => widget.type !== "chatbot").map((widget) => widget.id), datasetId, pageId, onApplyFilters, isEditing })
|
|
49086
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(WidgetRenderer, { widget: w, widgetBackendUrl, onResetReady: handleResetReady, widgetIds: widgets.filter((widget) => widget.type !== "chatbot").map((widget) => widget.id), datasetId, pageId, onApplyFilters, isEditing, dashboardName: ((_c = pageData == null ? void 0 : pageData.basic) == null ? void 0 : _c.title) || (pageData == null ? void 0 : pageData.name) || (pageData == null ? void 0 : pageData.title) })
|
|
48877
49087
|
] })
|
|
48878
49088
|
] }, w.id);
|
|
48879
49089
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dp-widgets-framework",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org"
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"express": "^4.21.2",
|
|
91
91
|
"express-validator": "^7.2.1",
|
|
92
92
|
"framer-motion": "^12.0.6",
|
|
93
|
+
"jspdf": "^2.5.2",
|
|
93
94
|
"lodash": "^4.17.21",
|
|
94
95
|
"lucide-react": "^0.474.0",
|
|
95
96
|
"next": "14.0.4",
|