@qoretechnologies/reqraft 0.10.8 → 0.10.9-pr.74.g452d4d3
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/components/form/engine/CompactRow.d.ts.map +1 -1
- package/dist/components/form/engine/CompactRow.js +1 -22
- package/dist/components/form/engine/CompactRow.js.map +1 -1
- package/dist/components/form/engine/compactRowStyles.d.ts +0 -1
- package/dist/components/form/engine/compactRowStyles.d.ts.map +1 -1
- package/dist/components/form/engine/compactRowStyles.js +4 -19
- package/dist/components/form/engine/compactRowStyles.js.map +1 -1
- package/dist/components/supportTicket/AttachmentChips.d.ts +7 -0
- package/dist/components/supportTicket/AttachmentChips.d.ts.map +1 -0
- package/dist/components/supportTicket/AttachmentChips.js +26 -0
- package/dist/components/supportTicket/AttachmentChips.js.map +1 -0
- package/dist/components/supportTicket/InterfaceReferenceTags.d.ts +25 -0
- package/dist/components/supportTicket/InterfaceReferenceTags.d.ts.map +1 -0
- package/dist/components/supportTicket/InterfaceReferenceTags.js +28 -0
- package/dist/components/supportTicket/InterfaceReferenceTags.js.map +1 -0
- package/dist/components/supportTicket/TicketMetaTags.d.ts +24 -0
- package/dist/components/supportTicket/TicketMetaTags.d.ts.map +1 -0
- package/dist/components/supportTicket/TicketMetaTags.js +21 -0
- package/dist/components/supportTicket/TicketMetaTags.js.map +1 -0
- package/dist/components/supportTicket/TicketReplyBox.d.ts +59 -0
- package/dist/components/supportTicket/TicketReplyBox.d.ts.map +1 -0
- package/dist/components/supportTicket/TicketReplyBox.js +169 -0
- package/dist/components/supportTicket/TicketReplyBox.js.map +1 -0
- package/dist/components/supportTicket/fileToAttachment.d.ts +9 -0
- package/dist/components/supportTicket/fileToAttachment.d.ts.map +1 -0
- package/dist/components/supportTicket/fileToAttachment.js +28 -0
- package/dist/components/supportTicket/fileToAttachment.js.map +1 -0
- package/dist/components/supportTicket/index.d.ts +7 -0
- package/dist/components/supportTicket/index.d.ts.map +1 -0
- package/dist/components/supportTicket/index.js +23 -0
- package/dist/components/supportTicket/index.js.map +1 -0
- package/dist/components/supportTicket/meta.d.ts +55 -0
- package/dist/components/supportTicket/meta.d.ts.map +1 -0
- package/dist/components/supportTicket/meta.js +77 -0
- package/dist/components/supportTicket/meta.js.map +1 -0
- package/dist/components/ticketThread/TicketThread.d.ts +36 -0
- package/dist/components/ticketThread/TicketThread.d.ts.map +1 -0
- package/dist/components/ticketThread/TicketThread.js +137 -0
- package/dist/components/ticketThread/TicketThread.js.map +1 -0
- package/dist/components/ticketThread/index.d.ts +3 -0
- package/dist/components/ticketThread/index.d.ts.map +1 -0
- package/dist/components/ticketThread/index.js +6 -0
- package/dist/components/ticketThread/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/form/engine/CompactRow.tsx +1 -57
- package/src/components/form/engine/FormEngine.stories.tsx +0 -67
- package/src/components/form/engine/compactRowStyles.ts +0 -21
- package/src/components/supportTicket/AttachmentChips.tsx +50 -0
- package/src/components/supportTicket/InterfaceReferenceTags.stories.tsx +102 -0
- package/src/components/supportTicket/InterfaceReferenceTags.tsx +62 -0
- package/src/components/supportTicket/TicketMetaTags.stories.tsx +71 -0
- package/src/components/supportTicket/TicketMetaTags.tsx +58 -0
- package/src/components/supportTicket/TicketReplyBox.stories.tsx +111 -0
- package/src/components/supportTicket/TicketReplyBox.tsx +251 -0
- package/src/components/supportTicket/fileToAttachment.ts +24 -0
- package/src/components/supportTicket/index.ts +6 -0
- package/src/components/supportTicket/meta.ts +135 -0
- package/src/components/ticketThread/TicketThread.stories.tsx +192 -0
- package/src/components/ticketThread/TicketThread.tsx +331 -0
- package/src/components/ticketThread/index.ts +6 -0
- package/src/index.tsx +2 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
|
|
3
|
+
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
|
|
4
|
+
return cooked;
|
|
5
|
+
};
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.TicketThread = void 0;
|
|
11
|
+
var jsx_runtime_1 = require("react/jsx-runtime");
|
|
12
|
+
var reqore_1 = require("@qoretechnologies/reqore");
|
|
13
|
+
var react_markdown_1 = __importDefault(require("react-markdown"));
|
|
14
|
+
var styled_components_1 = __importDefault(require("styled-components"));
|
|
15
|
+
var supportTicket_1 = require("../supportTicket");
|
|
16
|
+
var AUTHOR_META = {
|
|
17
|
+
customer: { icon: 'User3Line' },
|
|
18
|
+
staff: { icon: 'CustomerService2Line' },
|
|
19
|
+
system: { icon: 'InformationLine' },
|
|
20
|
+
};
|
|
21
|
+
/** Compact relative-time label from an ISO timestamp. */
|
|
22
|
+
var timeAgo = function (iso) {
|
|
23
|
+
if (!iso) {
|
|
24
|
+
return '';
|
|
25
|
+
}
|
|
26
|
+
var then = new Date(iso).getTime();
|
|
27
|
+
if (Number.isNaN(then)) {
|
|
28
|
+
return '';
|
|
29
|
+
}
|
|
30
|
+
var seconds = Math.round((then - Date.now()) / 1000);
|
|
31
|
+
var rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
|
|
32
|
+
var units = [
|
|
33
|
+
['year', 31536000],
|
|
34
|
+
['month', 2592000],
|
|
35
|
+
['week', 604800],
|
|
36
|
+
['day', 86400],
|
|
37
|
+
['hour', 3600],
|
|
38
|
+
['minute', 60],
|
|
39
|
+
['second', 1],
|
|
40
|
+
];
|
|
41
|
+
for (var _i = 0, units_1 = units; _i < units_1.length; _i++) {
|
|
42
|
+
var _a = units_1[_i], unit = _a[0], per = _a[1];
|
|
43
|
+
if (Math.abs(seconds) >= per || unit === 'second') {
|
|
44
|
+
return rtf.format(Math.round(seconds / per), unit);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return '';
|
|
48
|
+
};
|
|
49
|
+
/** Human-readable file size, e.g. "12.3 KB". */
|
|
50
|
+
var formatBytes = function (bytes) {
|
|
51
|
+
if (bytes < 1024) {
|
|
52
|
+
return "".concat(bytes, " B");
|
|
53
|
+
}
|
|
54
|
+
var units = ['KB', 'MB', 'GB'];
|
|
55
|
+
var value = bytes / 1024;
|
|
56
|
+
var unit = 0;
|
|
57
|
+
while (value >= 1024 && unit < units.length - 1) {
|
|
58
|
+
value /= 1024;
|
|
59
|
+
unit += 1;
|
|
60
|
+
}
|
|
61
|
+
return "".concat(value.toFixed(1), " ").concat(units[unit]);
|
|
62
|
+
};
|
|
63
|
+
/** The label shown above a run of messages. Customer view masks staff identity as
|
|
64
|
+
* "Qorus Support"; staff view shows the real author with a role prefix. Internal
|
|
65
|
+
* notes always label as "Internal note" regardless of viewer. */
|
|
66
|
+
var authorLabel = function (message, viewerRole) {
|
|
67
|
+
if (message.internal) {
|
|
68
|
+
return 'Internal note';
|
|
69
|
+
}
|
|
70
|
+
if (viewerRole === 'customer') {
|
|
71
|
+
return message.author_type === 'customer' ? 'You' : 'Qorus Support';
|
|
72
|
+
}
|
|
73
|
+
return "".concat(message.author_type === 'staff' ? 'Support' : 'Customer', " \u00B7 ").concat(message.author_id);
|
|
74
|
+
};
|
|
75
|
+
/** Per-role bubble tint: staff green, customer blue, internal notes amber. */
|
|
76
|
+
var bubbleIntent = function (message) {
|
|
77
|
+
if (message.internal) {
|
|
78
|
+
return 'warning';
|
|
79
|
+
}
|
|
80
|
+
return message.author_type === 'staff' ? 'success' : 'info';
|
|
81
|
+
};
|
|
82
|
+
var StyledThread = styled_components_1.default.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n display: flex;\n flex-direction: column;\n gap: 14px;\n width: 100%;\n"], ["\n display: flex;\n flex-direction: column;\n gap: 14px;\n width: 100%;\n"])));
|
|
83
|
+
// System messages read as a centered muted note between bubble clusters; the
|
|
84
|
+
// nested rule flattens react-markdown's own <p> margins so it sits on one line.
|
|
85
|
+
var StyledSystemRow = styled_components_1.default.div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n font-size: 11px;\n opacity: 0.55;\n text-align: center;\n p {\n margin: 0;\n }\n"], ["\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n font-size: 11px;\n opacity: 0.55;\n text-align: center;\n p {\n margin: 0;\n }\n"])));
|
|
86
|
+
/** The inner content of a message bubble: an optional author label (shown once
|
|
87
|
+
* per same-author run), the markdown body, attachment chips, and reference chips. */
|
|
88
|
+
var BubbleContent = function (_a) {
|
|
89
|
+
var _b, _c;
|
|
90
|
+
var message = _a.message, showLabel = _a.showLabel, viewerRole = _a.viewerRole, onDownloadAttachment = _a.onDownloadAttachment, resolveInterfaceIcon = _a.resolveInterfaceIcon, onInterfaceClick = _a.onInterfaceClick;
|
|
91
|
+
var isInternal = !!message.internal;
|
|
92
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [showLabel ? ((0, jsx_runtime_1.jsxs)(reqore_1.ReqoreControlGroup, { verticalAlign: 'center', gapSize: 'tiny', style: { marginBottom: 4 }, children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreIcon, { icon: isInternal ? 'EyeOffLine' : AUTHOR_META[message.author_type].icon, size: 'tiny' }), (0, jsx_runtime_1.jsx)(reqore_1.ReqoreP, { size: 'small', effect: { weight: 'bold', opacity: 0.7 }, children: authorLabel(message, viewerRole) })] })) : null, (0, jsx_runtime_1.jsx)(react_markdown_1.default, { children: message.body }), ((_b = message.attachments) === null || _b === void 0 ? void 0 : _b.length) ? ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreControlGroup, { wrap: true, gapSize: 'small', style: { marginTop: 8 }, children: message.attachments.map(function (a) { return ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreButton, { icon: 'Download2Line', size: 'small', flat: true, badge: formatBytes(a.size_bytes), tooltip: "".concat(a.content_type, " \u00B7 download"), onClick: function () { return onDownloadAttachment === null || onDownloadAttachment === void 0 ? void 0 : onDownloadAttachment(a.attachment_id, a.filename); }, children: a.filename }, a.attachment_id)); }) })) : null, ((_c = message.referenced_interfaces) === null || _c === void 0 ? void 0 : _c.length) ? ((0, jsx_runtime_1.jsx)("div", { style: { marginTop: 8 }, children: (0, jsx_runtime_1.jsx)(supportTicket_1.InterfaceReferenceTags, { references: message.referenced_interfaces, resolveInterfaceIcon: resolveInterfaceIcon, onInterfaceClick: onInterfaceClick }) })) : null] }));
|
|
93
|
+
};
|
|
94
|
+
/** Split the thread into centered system lines and runs of consecutive
|
|
95
|
+
* non-system messages (each run becomes one auto-clustered bubble group). */
|
|
96
|
+
var toSegments = function (messages) {
|
|
97
|
+
var segments = [];
|
|
98
|
+
for (var _i = 0, messages_1 = messages; _i < messages_1.length; _i++) {
|
|
99
|
+
var message = messages_1[_i];
|
|
100
|
+
if (message.author_type === 'system') {
|
|
101
|
+
segments.push({ kind: 'system', message: message });
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
var last = segments[segments.length - 1];
|
|
105
|
+
if ((last === null || last === void 0 ? void 0 : last.kind) === 'bubbles') {
|
|
106
|
+
last.messages.push(message);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
segments.push({ kind: 'bubbles', messages: [message] });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return segments;
|
|
113
|
+
};
|
|
114
|
+
var TicketThread = function (_a) {
|
|
115
|
+
var messages = _a.messages, _b = _a.viewerRole, viewerRole = _b === void 0 ? 'customer' : _b, loading = _a.loading, onDownloadAttachment = _a.onDownloadAttachment, resolveInterfaceIcon = _a.resolveInterfaceIcon, onInterfaceClick = _a.onInterfaceClick;
|
|
116
|
+
if (loading) {
|
|
117
|
+
return ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreControlGroup, { vertical: true, fluid: true, horizontalAlign: 'center', style: { padding: '24px 0' }, children: (0, jsx_runtime_1.jsx)(reqore_1.ReqoreSpinner, { type: 5, iconColor: 'info', size: 'big', children: "Loading conversation\u2026" }) }));
|
|
118
|
+
}
|
|
119
|
+
if (!messages.length) {
|
|
120
|
+
return (0, jsx_runtime_1.jsx)(reqore_1.ReqoreEmptyState, { icon: 'Chat3Line', title: 'No messages yet' });
|
|
121
|
+
}
|
|
122
|
+
return ((0, jsx_runtime_1.jsxs)(StyledThread, { children: [toSegments(messages).map(function (segment, index) {
|
|
123
|
+
return segment.kind === 'system' ? ((0, jsx_runtime_1.jsxs)(StyledSystemRow, { children: [(0, jsx_runtime_1.jsx)(reqore_1.ReqoreIcon, { icon: 'InformationLine', size: 'tiny' }), (0, jsx_runtime_1.jsx)(react_markdown_1.default, { children: segment.message.body })] }, segment.message.message_id)) : ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreBubbleGroup, { children: segment.messages.map(function (message, i) {
|
|
124
|
+
var previous = segment.messages[i - 1];
|
|
125
|
+
// Label once per same-author run; an internal note always gets its
|
|
126
|
+
// own label even from the same staff author.
|
|
127
|
+
var showLabel = !previous ||
|
|
128
|
+
previous.author_type !== message.author_type ||
|
|
129
|
+
!!previous.internal !== !!message.internal;
|
|
130
|
+
var isSelf = message.author_type === viewerRole;
|
|
131
|
+
return ((0, jsx_runtime_1.jsx)(reqore_1.ReqoreBubble, { align: isSelf ? 'right' : 'left', intent: bubbleIntent(message), minimal: !message.internal, flat: !message.internal, timestamp: timeAgo(message.created) || undefined, children: (0, jsx_runtime_1.jsx)(BubbleContent, { message: message, showLabel: showLabel, viewerRole: viewerRole, onDownloadAttachment: onDownloadAttachment, resolveInterfaceIcon: resolveInterfaceIcon, onInterfaceClick: onInterfaceClick }) }, message.message_id));
|
|
132
|
+
}) }, "group-".concat(index)));
|
|
133
|
+
}), (0, jsx_runtime_1.jsxs)(reqore_1.ReqoreP, { size: 'tiny', effect: { opacity: 0.5, textAlign: 'center' }, children: [messages.length, " message", messages.length === 1 ? '' : 's'] })] }));
|
|
134
|
+
};
|
|
135
|
+
exports.TicketThread = TicketThread;
|
|
136
|
+
var templateObject_1, templateObject_2;
|
|
137
|
+
//# sourceMappingURL=TicketThread.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TicketThread.js","sourceRoot":"","sources":["../../../src/components/ticketThread/TicketThread.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ticketThread/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EACV,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TicketThread = void 0;
|
|
4
|
+
var TicketThread_1 = require("./TicketThread");
|
|
5
|
+
Object.defineProperty(exports, "TicketThread", { enumerable: true, get: function () { return TicketThread_1.TicketThread; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ticketThread/index.ts"],"names":[],"mappings":";;;AAAA,+CAA8C;AAArC,4GAAA,YAAY,OAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -20,4 +20,6 @@ export type { ILspCompletionItem, ILspDiagnostic, ILspMarkupContent, ILspParamet
|
|
|
20
20
|
export * from './components/smartEditor';
|
|
21
21
|
export * from './components/dpqlEditor';
|
|
22
22
|
export * from './components/qonsoleSmartInput';
|
|
23
|
+
export * from './components/supportTicket';
|
|
24
|
+
export * from './components/ticketThread';
|
|
23
25
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,4BAA4B,EAC5B,gCAAgC,GACjC,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,YAAY,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,cAAc,mCAAmC,CAAC;AAClD,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,kBAAkB,GACnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,gBAAgB,IAAI,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC/F,YAAY,EACV,YAAY,EACZ,iBAAiB,GAClB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,YAAY,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAClE,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,wBAAwB,EACxB,YAAY,EACZ,SAAS,EACT,iBAAiB,EACjB,wBAAwB,EACxB,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,EACxB,YAAY,EACZ,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,4BAA4B,EAC5B,gCAAgC,GACjC,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,YAAY,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,cAAc,mCAAmC,CAAC;AAClD,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,kBAAkB,GACnB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,gBAAgB,IAAI,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC/F,YAAY,EACV,YAAY,EACZ,iBAAiB,GAClB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,YAAY,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAClE,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,wBAAwB,EACxB,YAAY,EACZ,SAAS,EACT,iBAAiB,EACjB,wBAAwB,EACxB,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,EACxB,YAAY,EACZ,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -46,4 +46,6 @@ Object.defineProperty(exports, "ReqraftLspClient", { enumerable: true, get: func
|
|
|
46
46
|
__exportStar(require("./components/smartEditor"), exports);
|
|
47
47
|
__exportStar(require("./components/dpqlEditor"), exports);
|
|
48
48
|
__exportStar(require("./components/qonsoleSmartInput"), exports);
|
|
49
|
+
__exportStar(require("./components/supportTicket"), exports);
|
|
50
|
+
__exportStar(require("./components/ticketThread"), exports);
|
|
49
51
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,uDAAqC;AACrC,qDAQ+B;AAP7B,4GAAA,aAAa,OAAA;AACb,sHAAA,uBAAuB,OAAA;AACvB,yGAAA,UAAU,OAAA;AACV,+GAAA,gBAAgB,OAAA;AAChB,6GAAA,cAAc,OAAA;AACd,2HAAA,4BAA4B,OAAA;AAC5B,+HAAA,gCAAgC,OAAA;AAGlC,+CAAqD;AAA5C,mGAAA,WAAW,OAAA;AAQpB,sDAAqD;AAA5C,oGAAA,QAAQ,OAAA;AAEjB,4DAAkE;AAAzD,+GAAA,iBAAiB,OAAA;AAE1B,oEAAkD;AAClD,+DAIqC;AAHnC,oHAAA,iBAAiB,OAAA;AACjB,kHAAA,eAAe,OAAA;AACf,qHAAA,kBAAkB,OAAA;AAEpB,gEAA+F;AAAtF,sHAAA,gBAAgB,OAA2B;AAKpD,uCAAsC;AAA7B,8FAAA,KAAK,OAAA;AACd,oDAAkC;AAClC,+CAAqD;AAA5C,6GAAA,gBAAgB,OAAA;AAiBzB,2DAAyC;AACzC,0DAAwC;AACxC,iEAA+C"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,uDAAqC;AACrC,qDAQ+B;AAP7B,4GAAA,aAAa,OAAA;AACb,sHAAA,uBAAuB,OAAA;AACvB,yGAAA,UAAU,OAAA;AACV,+GAAA,gBAAgB,OAAA;AAChB,6GAAA,cAAc,OAAA;AACd,2HAAA,4BAA4B,OAAA;AAC5B,+HAAA,gCAAgC,OAAA;AAGlC,+CAAqD;AAA5C,mGAAA,WAAW,OAAA;AAQpB,sDAAqD;AAA5C,oGAAA,QAAQ,OAAA;AAEjB,4DAAkE;AAAzD,+GAAA,iBAAiB,OAAA;AAE1B,oEAAkD;AAClD,+DAIqC;AAHnC,oHAAA,iBAAiB,OAAA;AACjB,kHAAA,eAAe,OAAA;AACf,qHAAA,kBAAkB,OAAA;AAEpB,gEAA+F;AAAtF,sHAAA,gBAAgB,OAA2B;AAKpD,uCAAsC;AAA7B,8FAAA,KAAK,OAAA;AACd,oDAAkC;AAClC,+CAAqD;AAA5C,6GAAA,gBAAgB,OAAA;AAiBzB,2DAAyC;AACzC,0DAAwC;AACxC,iEAA+C;AAC/C,6DAA2C;AAC3C,4DAA0C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qoretechnologies/reqraft",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.9-pr.74.g452d4d3",
|
|
4
4
|
"description": "ReQraft is a collection of React components and hooks that are used across Qore Technologies' products made using the ReQore component library from Qore.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -35,7 +35,6 @@ import {
|
|
|
35
35
|
StyledActionSlot,
|
|
36
36
|
StyledCardHeading,
|
|
37
37
|
StyledCardLabel,
|
|
38
|
-
StyledCodePreview,
|
|
39
38
|
StyledColorSwatch,
|
|
40
39
|
StyledColumn,
|
|
41
40
|
StyledEditCard,
|
|
@@ -257,26 +256,6 @@ export const CompactRow = memo(
|
|
|
257
256
|
);
|
|
258
257
|
}
|
|
259
258
|
|
|
260
|
-
// Code-editor read summary: replace the truncated string with a chip
|
|
261
|
-
// showing line count + character count. The actual code renders below
|
|
262
|
-
// the row as a monospace `<pre>` inside a `ReqoreCollapsibleContent` —
|
|
263
|
-
// see `showCodePreview` below. Keeps the row height fixed while making
|
|
264
|
-
// multi-line source readable without opening the full editor.
|
|
265
|
-
if (valueType === 'code-editor' && typeof field?.value === 'string') {
|
|
266
|
-
const lines = field.value.split('\n').length;
|
|
267
|
-
const chars = field.value.length;
|
|
268
|
-
return (
|
|
269
|
-
<ReqoreTag
|
|
270
|
-
size='small'
|
|
271
|
-
minimal
|
|
272
|
-
intent='info'
|
|
273
|
-
icon='CodeLine'
|
|
274
|
-
label={`${lines} ${lines === 1 ? 'line' : 'lines'}`}
|
|
275
|
-
labelKey={`${chars} ${chars === 1 ? 'char' : 'chars'}`}
|
|
276
|
-
/>
|
|
277
|
-
);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
259
|
// Selected allowed-value / enum item with a logo (e.g. language images):
|
|
281
260
|
// render it beside the value, where it belongs — not as the field's icon.
|
|
282
261
|
const allowedImage = getAllowedValueImage(field?.value, schema);
|
|
@@ -934,16 +913,6 @@ export const CompactRow = memo(
|
|
|
934
913
|
return inner !== null && typeof inner === 'object';
|
|
935
914
|
});
|
|
936
915
|
const showStructuredPreview = hashEntries.length > 0 || isHashList;
|
|
937
|
-
// Multi-line code preview: a `code-editor` field with a non-empty string
|
|
938
|
-
// value gets a `<pre>`-based code block under the row, capped by a
|
|
939
|
-
// `ReqoreCollapsibleContent` so the collapsed height stays row-sized and
|
|
940
|
-
// "Show more" reveals the rest. Sits in the same inset the hash/list
|
|
941
|
-
// preview uses — mutually exclusive with `showStructuredPreview`.
|
|
942
|
-
const showCodePreview =
|
|
943
|
-
!hidden &&
|
|
944
|
-
valueType === 'code-editor' &&
|
|
945
|
-
typeof optionField?.value === 'string' &&
|
|
946
|
-
optionField.value.length > 0;
|
|
947
916
|
const typeLabel =
|
|
948
917
|
showFieldTypes ?
|
|
949
918
|
`<${(schema?.ui_type as string) || (schema?.type as string) || 'auto'}${(schema as { ui_element_type?: string } | undefined)?.ui_element_type ? `[${(schema as { ui_element_type?: string }).ui_element_type}]` : ''}>`
|
|
@@ -1095,7 +1064,7 @@ export const CompactRow = memo(
|
|
|
1095
1064
|
role='button'
|
|
1096
1065
|
tabIndex={0}
|
|
1097
1066
|
aria-label={label}
|
|
1098
|
-
className={`readfirst-row options-readfirst-value${hidden ? ' readfirst-row-hidden' : ''}${fieldDisabled ? ' readfirst-row-disabled' : ''}${isHighlighted ? ' readfirst-row-group-highlight' : ''}${isFlashed ? ' readfirst-row-flash' : ''}${showLabelDesc ? ' readfirst-row-info-open' : ''}${panelMessages.length || showStructuredPreview
|
|
1067
|
+
className={`readfirst-row options-readfirst-value${hidden ? ' readfirst-row-hidden' : ''}${fieldDisabled ? ' readfirst-row-disabled' : ''}${isHighlighted ? ' readfirst-row-group-highlight' : ''}${isFlashed ? ' readfirst-row-flash' : ''}${showLabelDesc ? ' readfirst-row-info-open' : ''}${panelMessages.length || showStructuredPreview ? ' readfirst-row-tall' : ''}${clusterBlockClass ? ' ' + clusterBlockClass : ''}`}
|
|
1099
1068
|
aria-disabled={fieldDisabled || undefined}
|
|
1100
1069
|
style={stripeStyle}
|
|
1101
1070
|
onClick={activate}
|
|
@@ -1206,31 +1175,6 @@ export const CompactRow = memo(
|
|
|
1206
1175
|
</ReqoreCollapsibleContent>
|
|
1207
1176
|
</StyledRowInset>
|
|
1208
1177
|
: null}
|
|
1209
|
-
{/* Code-editor preview: same inset placement as hash/list — a monospace
|
|
1210
|
-
`<pre>` block wrapped in `ReqoreCollapsibleContent` so the collapsed
|
|
1211
|
-
row stays row-height while multi-line source reveals via "Show more".
|
|
1212
|
-
Stopping propagation here (like the structured inset) — a click on
|
|
1213
|
-
the collapse button must not also open the field editor. */}
|
|
1214
|
-
{showCodePreview ?
|
|
1215
|
-
<StyledRowInset
|
|
1216
|
-
className='options-readfirst-inset options-readfirst-code-inset'
|
|
1217
|
-
onClick={(e) => e.stopPropagation()}
|
|
1218
|
-
>
|
|
1219
|
-
<ReqoreCollapsibleContent
|
|
1220
|
-
maxCollapsedHeight={96}
|
|
1221
|
-
buttonProps={{ className: 'options-readfirst-viewmore' }}
|
|
1222
|
-
>
|
|
1223
|
-
<StyledCodePreview
|
|
1224
|
-
className='options-readfirst-code'
|
|
1225
|
-
$bg={cHover}
|
|
1226
|
-
$border={`${cDivider}88`}
|
|
1227
|
-
$fg={cKey}
|
|
1228
|
-
>
|
|
1229
|
-
{optionField.value as string}
|
|
1230
|
-
</StyledCodePreview>
|
|
1231
|
-
</ReqoreCollapsibleContent>
|
|
1232
|
-
</StyledRowInset>
|
|
1233
|
-
: null}
|
|
1234
1178
|
</StyledRowValue>
|
|
1235
1179
|
<StyledRowActions>
|
|
1236
1180
|
{/* Column discipline (table treatment): variable-width chips lead and
|
|
@@ -715,73 +715,6 @@ export const OptionInheritsRenderPropFromSiblingCompact: Story = {
|
|
|
715
715
|
},
|
|
716
716
|
};
|
|
717
717
|
|
|
718
|
-
// Compact-row code-editor preview: a `code-editor` field with a multi-line
|
|
719
|
-
// string value renders (a) a "N lines · N chars" tag in the value cell instead
|
|
720
|
-
// of the truncated raw string, and (b) a monospace `<pre>` block under the row
|
|
721
|
-
// capped by a `ReqoreCollapsibleContent` — the "Show more" affordance the value
|
|
722
|
-
// cell couldn't provide on its own. Locks the compact preview so a future
|
|
723
|
-
// CompactRow refactor can't silently reduce a Qorus source-code field to an
|
|
724
|
-
// ellipsised one-liner again.
|
|
725
|
-
export const CompactRowCodeEditorPreview: Story = {
|
|
726
|
-
args: {
|
|
727
|
-
compact: true,
|
|
728
|
-
minColumnWidth: '360px',
|
|
729
|
-
componentOverrides: { 'code-editor': CodeEditorStandin },
|
|
730
|
-
value: {
|
|
731
|
-
language: { type: 'string', value: 'qore' },
|
|
732
|
-
source: {
|
|
733
|
-
type: 'string',
|
|
734
|
-
value:
|
|
735
|
-
'%new-style\n%require-types\n%strict-args\n' +
|
|
736
|
-
'%enable-all-warnings\n\n' +
|
|
737
|
-
'class ExampleJob inherits QorusJob {\n' +
|
|
738
|
-
' run() {\n' +
|
|
739
|
-
' logInfo("running");\n' +
|
|
740
|
-
' }\n' +
|
|
741
|
-
'}\n',
|
|
742
|
-
},
|
|
743
|
-
},
|
|
744
|
-
options: {
|
|
745
|
-
language: {
|
|
746
|
-
type: 'string',
|
|
747
|
-
ui_type: 'string',
|
|
748
|
-
display_name: 'Language',
|
|
749
|
-
allowed_values: [
|
|
750
|
-
{ display_name: 'Qore', value: { type: 'string', value: 'qore' } },
|
|
751
|
-
{ display_name: 'Python', value: { type: 'string', value: 'python' } },
|
|
752
|
-
{ display_name: 'Java', value: { type: 'string', value: 'java' } },
|
|
753
|
-
],
|
|
754
|
-
},
|
|
755
|
-
source: {
|
|
756
|
-
type: 'string',
|
|
757
|
-
ui_type: 'code-editor',
|
|
758
|
-
display_name: 'Source Code',
|
|
759
|
-
inherit_props: { language: 'language' },
|
|
760
|
-
},
|
|
761
|
-
},
|
|
762
|
-
},
|
|
763
|
-
play: async ({ canvasElement }) => {
|
|
764
|
-
// (a) The monospace preview mounted under the row — contains a substring
|
|
765
|
-
// only the source has, proving `showCodePreview` kicked in and the
|
|
766
|
-
// `StyledCodePreview` block is in the DOM.
|
|
767
|
-
await waitFor(
|
|
768
|
-
() => {
|
|
769
|
-
const preview = canvasElement.querySelector('.options-readfirst-code');
|
|
770
|
-
expect(preview).toBeTruthy();
|
|
771
|
-
expect(preview?.textContent).toContain('class ExampleJob inherits QorusJob');
|
|
772
|
-
},
|
|
773
|
-
{ timeout: 5000 }
|
|
774
|
-
);
|
|
775
|
-
// (b) The value cell replaced its truncated raw string with a summary tag —
|
|
776
|
-
// query the tag directly (its label + labelKey render on separate spans,
|
|
777
|
-
// so text-matching across them is fragile). Look for the CodeLine icon
|
|
778
|
-
// that only this tag mounts alongside the source-code row.
|
|
779
|
-
const sourceRow = canvasElement.querySelector('[data-field="source"]');
|
|
780
|
-
expect(sourceRow).toBeTruthy();
|
|
781
|
-
expect(sourceRow?.textContent ?? '').toMatch(/\d+\s*lines?/);
|
|
782
|
-
},
|
|
783
|
-
};
|
|
784
|
-
|
|
785
718
|
// qorus#347-followup, scope forwarding: this story exercises the nested
|
|
786
719
|
// case of the OptionInheritsRenderPropFromSibling contract. The parent
|
|
787
720
|
// form declares `methods: { ui_type: 'list', element_type: 'hash',
|
|
@@ -335,27 +335,6 @@ export const StyledRowInset = styled.div`
|
|
|
335
335
|
margin-top: 4px;
|
|
336
336
|
`;
|
|
337
337
|
|
|
338
|
-
// A collapsed code-block preview shown under the value summary for a
|
|
339
|
-
// `code-editor` field. Multi-line, monospace, subtle background — matches
|
|
340
|
-
// the aesthetic of the classic code-view surface but small enough to sit
|
|
341
|
-
// inside a read-row. Height is capped by the wrapping `ReqoreCollapsibleContent`
|
|
342
|
-
// so the "Show more" affordance stays useful.
|
|
343
|
-
export const StyledCodePreview = styled.pre<{ $bg: string; $border: string; $fg: string }>`
|
|
344
|
-
margin: 0;
|
|
345
|
-
padding: 8px 10px;
|
|
346
|
-
border-radius: 4px;
|
|
347
|
-
background: ${({ $bg }) => $bg};
|
|
348
|
-
border: 1px solid ${({ $border }) => $border};
|
|
349
|
-
color: ${({ $fg }) => $fg};
|
|
350
|
-
font-family:
|
|
351
|
-
ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
|
|
352
|
-
font-size: 11.5px;
|
|
353
|
-
line-height: 1.5;
|
|
354
|
-
white-space: pre;
|
|
355
|
-
overflow: auto;
|
|
356
|
-
max-width: 100%;
|
|
357
|
-
`;
|
|
358
|
-
|
|
359
338
|
// A small inline colour swatch shown before an rgbcolor value's hex string.
|
|
360
339
|
export const StyledColorSwatch = styled.span<{ $color: string; $border: string }>`
|
|
361
340
|
width: 12px;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { ReqoreControlGroup, ReqoreTag } from '@qoretechnologies/reqore';
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* Renders the files staged on a ticket composer as removable chips. Image files —
|
|
6
|
+
* whether uploaded, pasted, or captured as a screenshot — show a thumbnail;
|
|
7
|
+
* everything else shows a paperclip + filename. Thumbnail object URLs are created
|
|
8
|
+
* here and revoked when the file set changes or the component unmounts. Renders
|
|
9
|
+
* nothing when there are no staged files.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export interface IAttachmentChipsProps {
|
|
13
|
+
files: File[];
|
|
14
|
+
onRemove: (index: number) => void;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const AttachmentChips = ({ files, onRemove, disabled }: IAttachmentChipsProps) => {
|
|
19
|
+
const [thumbnails, setThumbnails] = useState<string[]>([]);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const urls = files.map((file) =>
|
|
23
|
+
file.type.startsWith('image/') ? URL.createObjectURL(file) : ''
|
|
24
|
+
);
|
|
25
|
+
setThumbnails(urls);
|
|
26
|
+
return () => urls.forEach((url) => url && URL.revokeObjectURL(url));
|
|
27
|
+
}, [files]);
|
|
28
|
+
|
|
29
|
+
if (!files.length) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<ReqoreControlGroup wrap gapSize='small' verticalAlign='center'>
|
|
35
|
+
{files.map((file, index) => {
|
|
36
|
+
const thumbnail = thumbnails[index];
|
|
37
|
+
return (
|
|
38
|
+
<ReqoreTag
|
|
39
|
+
key={`${file.name}-${index}`}
|
|
40
|
+
icon={thumbnail ? undefined : 'AttachmentLine'}
|
|
41
|
+
leftIconProps={thumbnail ? { image: thumbnail } : undefined}
|
|
42
|
+
label={file.name}
|
|
43
|
+
size='small'
|
|
44
|
+
onRemoveClick={disabled ? undefined : () => onRemove(index)}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
})}
|
|
48
|
+
</ReqoreControlGroup>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { expect, fn, userEvent, waitFor, within } from 'storybook/test';
|
|
3
|
+
import { StoryMeta } from '../../types';
|
|
4
|
+
import { InterfaceReferenceTags } from './InterfaceReferenceTags';
|
|
5
|
+
import { IInterfaceReference } from './meta';
|
|
6
|
+
|
|
7
|
+
// Several references, including two of the same kind (workflow), as `{kind, name}`
|
|
8
|
+
// snapshots — no `resolveInterfaceIcon` is passed, so the built-in per-kind default
|
|
9
|
+
// icons are exercised.
|
|
10
|
+
const REFERENCES: IInterfaceReference[] = [
|
|
11
|
+
{ interface_kind: 'workflow', interface_name: 'order-sync:1.2', reference_id: 'r1' },
|
|
12
|
+
{ interface_kind: 'workflow', interface_name: 'invoice-sync:2.3', reference_id: 'r2' },
|
|
13
|
+
{ interface_kind: 'service', interface_name: 'notification-svc', reference_id: 'r3' },
|
|
14
|
+
{ interface_kind: 'job', interface_name: 'nightly-cleanup', reference_id: 'r4' },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const meta = {
|
|
18
|
+
component: InterfaceReferenceTags,
|
|
19
|
+
title: 'Components/InterfaceReferenceTags',
|
|
20
|
+
args: {
|
|
21
|
+
references: REFERENCES,
|
|
22
|
+
label: 'References',
|
|
23
|
+
},
|
|
24
|
+
} as StoryMeta<typeof InterfaceReferenceTags>;
|
|
25
|
+
|
|
26
|
+
export default meta;
|
|
27
|
+
type Story = StoryObj<typeof meta>;
|
|
28
|
+
|
|
29
|
+
/** The ticket-header use: a "References" label followed by one chip per reference. */
|
|
30
|
+
export const Default: Story = {
|
|
31
|
+
async play({ canvasElement }) {
|
|
32
|
+
const canvas = within(canvasElement);
|
|
33
|
+
await expect(canvas.getByText('References')).toBeInTheDocument();
|
|
34
|
+
await expect(canvas.getByText('order-sync:1.2')).toBeInTheDocument();
|
|
35
|
+
await expect(canvas.getByText('invoice-sync:2.3')).toBeInTheDocument();
|
|
36
|
+
await expect(canvas.getByText('notification-svc')).toBeInTheDocument();
|
|
37
|
+
await expect(canvas.getByText('nightly-cleanup')).toBeInTheDocument();
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* When `onInterfaceClick` is passed the chips become interactive; clicking one
|
|
43
|
+
* calls it with that reference (the customer view, which can open the interface on
|
|
44
|
+
* its own instance, wires this).
|
|
45
|
+
*/
|
|
46
|
+
export const Clickable: Story = {
|
|
47
|
+
args: { onInterfaceClick: fn() },
|
|
48
|
+
async play({ canvasElement, args }) {
|
|
49
|
+
const canvas = within(canvasElement);
|
|
50
|
+
await userEvent.click(canvas.getByText('invoice-sync:2.3'));
|
|
51
|
+
await waitFor(() =>
|
|
52
|
+
expect(args.onInterfaceClick).toHaveBeenCalledWith(
|
|
53
|
+
expect.objectContaining({
|
|
54
|
+
interface_kind: 'workflow',
|
|
55
|
+
interface_name: 'invoice-sync:2.3',
|
|
56
|
+
})
|
|
57
|
+
)
|
|
58
|
+
);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/** The in-thread use: no label — the chips sit under a message. */
|
|
63
|
+
export const NoLabel: Story = {
|
|
64
|
+
args: { label: undefined },
|
|
65
|
+
async play({ canvasElement }) {
|
|
66
|
+
const canvas = within(canvasElement);
|
|
67
|
+
await expect(canvas.queryByText('References')).not.toBeInTheDocument();
|
|
68
|
+
await expect(canvas.getByText('order-sync:1.2')).toBeInTheDocument();
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* With no references the component renders nothing — no empty header, no chips —
|
|
74
|
+
* so a ticket without references shows a clean gap rather than a stray "References:"
|
|
75
|
+
* label. The dashed frame below is a story-only caption; the empty space inside it
|
|
76
|
+
* is the component.
|
|
77
|
+
*/
|
|
78
|
+
export const Empty: Story = {
|
|
79
|
+
args: { references: [] },
|
|
80
|
+
decorators: [
|
|
81
|
+
(Story) => (
|
|
82
|
+
<div
|
|
83
|
+
style={{
|
|
84
|
+
border: '1px dashed rgba(150, 150, 150, 0.4)',
|
|
85
|
+
borderRadius: 6,
|
|
86
|
+
padding: 12,
|
|
87
|
+
fontSize: 12,
|
|
88
|
+
opacity: 0.6,
|
|
89
|
+
}}
|
|
90
|
+
>
|
|
91
|
+
No references → the row renders nothing (no empty header, no chips):
|
|
92
|
+
<Story />
|
|
93
|
+
</div>
|
|
94
|
+
),
|
|
95
|
+
],
|
|
96
|
+
async play({ canvasElement }) {
|
|
97
|
+
// The dashed frame + caption are the decorator; the component itself renders
|
|
98
|
+
// nothing — no header text, no chips.
|
|
99
|
+
await expect(within(canvasElement).queryByText('References')).not.toBeInTheDocument();
|
|
100
|
+
await expect(within(canvasElement).queryByText('order-sync:1.2')).not.toBeInTheDocument();
|
|
101
|
+
},
|
|
102
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ReqoreControlGroup, ReqoreP, ReqoreTag } from '@qoretechnologies/reqore';
|
|
2
|
+
import { TSizes } from '@qoretechnologies/reqore/dist/constants/sizes';
|
|
3
|
+
import { IReqoreIconName } from '@qoretechnologies/reqore/dist/types/icons';
|
|
4
|
+
import { defaultInterfaceIcon, IInterfaceReference } from './meta';
|
|
5
|
+
|
|
6
|
+
export interface IInterfaceReferenceTagsProps {
|
|
7
|
+
references?: IInterfaceReference[];
|
|
8
|
+
/** Optional leading label, e.g. "References" in a ticket header. Omitted (the
|
|
9
|
+
* default) inside the thread, where the chips sit under a message. */
|
|
10
|
+
label?: string;
|
|
11
|
+
/** Resolve a per-kind icon. Consumers with their own icon vocabulary (the IDE)
|
|
12
|
+
* pass one; when omitted the built-in per-kind default is used. */
|
|
13
|
+
resolveInterfaceIcon?: (kind: string) => IReqoreIconName;
|
|
14
|
+
/** Open a referenced interface; chips are static (informational) when omitted —
|
|
15
|
+
* e.g. the staff view, which can't reach the customer's instance. */
|
|
16
|
+
onInterfaceClick?: (reference: IInterfaceReference) => void;
|
|
17
|
+
size?: TSizes;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The chips for the Qorus interfaces a ticket or message references, as
|
|
22
|
+
* `{kind, name}` snapshots. The single renderer for interface references across
|
|
23
|
+
* every support surface — the ticket header (with a "References" label), the
|
|
24
|
+
* thread (per message, no label), and the Qonsole card — so a reference looks
|
|
25
|
+
* identical everywhere. Renders nothing when there are no references.
|
|
26
|
+
*/
|
|
27
|
+
export const InterfaceReferenceTags = ({
|
|
28
|
+
references,
|
|
29
|
+
label,
|
|
30
|
+
resolveInterfaceIcon,
|
|
31
|
+
onInterfaceClick,
|
|
32
|
+
size = 'small',
|
|
33
|
+
}: IInterfaceReferenceTagsProps) => {
|
|
34
|
+
if (!references?.length) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const resolveIcon = resolveInterfaceIcon ?? defaultInterfaceIcon;
|
|
38
|
+
return (
|
|
39
|
+
<ReqoreControlGroup verticalAlign='center' wrap gapSize='small'>
|
|
40
|
+
{label ? (
|
|
41
|
+
<ReqoreP size='small' effect={{ opacity: 0.6 }}>
|
|
42
|
+
{label}
|
|
43
|
+
</ReqoreP>
|
|
44
|
+
) : null}
|
|
45
|
+
{references.map((reference) => (
|
|
46
|
+
<ReqoreTag
|
|
47
|
+
key={reference.reference_id ?? `${reference.interface_kind}:${reference.interface_name}`}
|
|
48
|
+
icon={resolveIcon(reference.interface_kind)}
|
|
49
|
+
labelKey={reference.interface_kind}
|
|
50
|
+
label={reference.interface_name}
|
|
51
|
+
size={size}
|
|
52
|
+
tooltip={
|
|
53
|
+
onInterfaceClick
|
|
54
|
+
? `Open ${reference.interface_kind} ${reference.interface_name}`
|
|
55
|
+
: `${reference.interface_kind}: ${reference.interface_name}`
|
|
56
|
+
}
|
|
57
|
+
onClick={onInterfaceClick ? () => onInterfaceClick(reference) : undefined}
|
|
58
|
+
/>
|
|
59
|
+
))}
|
|
60
|
+
</ReqoreControlGroup>
|
|
61
|
+
);
|
|
62
|
+
};
|