@blockrun/franklin 3.21.2 → 3.21.3
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/panel/html.js +25 -7
- package/dist/phone/call-log.js +8 -2
- package/dist/tools/voice.js +1 -1
- package/package.json +1 -1
package/dist/panel/html.js
CHANGED
|
@@ -1990,6 +1990,22 @@ function formatDuration(sec) {
|
|
|
1990
1990
|
return m > 0 ? m + 'm ' + s + 's' : s + 's';
|
|
1991
1991
|
}
|
|
1992
1992
|
|
|
1993
|
+
function escapeHtml(value) {
|
|
1994
|
+
return String(value == null ? '' : value).replace(/[&<>"']/g, ch => ({
|
|
1995
|
+
'&': '&', '<': '<', '>': '>', '"': '"', "'": '''
|
|
1996
|
+
}[ch]));
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
function safeHttpUrl(value) {
|
|
2000
|
+
if (typeof value !== 'string') return '';
|
|
2001
|
+
try {
|
|
2002
|
+
const u = new URL(value);
|
|
2003
|
+
return (u.protocol === 'http:' || u.protocol === 'https:') ? u.href : '';
|
|
2004
|
+
} catch (e) {
|
|
2005
|
+
return '';
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
|
|
1993
2009
|
function renderCallsList(calls) {
|
|
1994
2010
|
const list = document.getElementById('calls-list');
|
|
1995
2011
|
if (!list) return;
|
|
@@ -2007,13 +2023,14 @@ function renderCallsList(calls) {
|
|
|
2007
2023
|
const fromHuman = formatPhoneNumber(c.from);
|
|
2008
2024
|
const when = new Date(c.timestamp).toLocaleString();
|
|
2009
2025
|
const cost = c.paid_usd ? '$' + c.paid_usd.toFixed(2) : '—';
|
|
2010
|
-
const safeTask = (c.task || '')
|
|
2026
|
+
const safeTask = escapeHtml(c.task || '');
|
|
2027
|
+
const recordingUrl = safeHttpUrl(c.recording_url);
|
|
2011
2028
|
const transcriptHtml = c.transcript
|
|
2012
2029
|
? '<details style="margin-top:8px"><summary style="cursor:pointer;color:var(--text-dim);font-size:12px">Transcript</summary><pre style="white-space:pre-wrap;background:oklch(0 0 0 / 25%);padding:10px;border-radius:8px;font-size:12px;margin-top:6px;max-height:400px;overflow:auto">' +
|
|
2013
|
-
c.transcript
|
|
2030
|
+
escapeHtml(c.transcript) + '</pre></details>'
|
|
2014
2031
|
: '';
|
|
2015
|
-
const recordingHtml =
|
|
2016
|
-
? '<a href="' +
|
|
2032
|
+
const recordingHtml = recordingUrl
|
|
2033
|
+
? '<a href="' + escapeHtml(recordingUrl) + '" target="_blank" rel="noopener" style="font-size:11px;color:var(--brand);text-decoration:none;margin-left:8px">▶ recording</a>'
|
|
2017
2034
|
: '';
|
|
2018
2035
|
return ''
|
|
2019
2036
|
+ '<div class="phone-row" style="grid-template-columns:auto 1fr auto;align-items:start">'
|
|
@@ -2023,12 +2040,12 @@ function renderCallsList(calls) {
|
|
|
2023
2040
|
+ ' </svg>'
|
|
2024
2041
|
+ ' </div>'
|
|
2025
2042
|
+ ' <div class="phone-main">'
|
|
2026
|
-
+ ' <div class="phone-num">' + human + ' <span style="font-size:11px;color:var(--text-dim);font-weight:400">from ' + fromHuman + '</span></div>'
|
|
2043
|
+
+ ' <div class="phone-num">' + escapeHtml(human) + ' <span style="font-size:11px;color:var(--text-dim);font-weight:400">from ' + escapeHtml(fromHuman) + '</span></div>'
|
|
2027
2044
|
+ ' <div class="phone-meta">'
|
|
2028
|
-
+ ' <span class="chip ' + st.cls + '">' + st.label + '</span>'
|
|
2045
|
+
+ ' <span class="chip ' + st.cls + '">' + escapeHtml(st.label) + '</span>'
|
|
2029
2046
|
+ ' <span class="chip">' + formatDuration(c.duration_sec) + '</span>'
|
|
2030
2047
|
+ ' <span class="chip">' + cost + '</span>'
|
|
2031
|
-
+ ' <span style="font-size:11px;color:var(--text-dim)">' + when + '</span>'
|
|
2048
|
+
+ ' <span style="font-size:11px;color:var(--text-dim)">' + escapeHtml(when) + '</span>'
|
|
2032
2049
|
+ recordingHtml
|
|
2033
2050
|
+ ' </div>'
|
|
2034
2051
|
+ ' <div style="font-size:12px;color:var(--text-muted);margin-top:4px;line-height:1.5">' + (safeTask.slice(0, 200) + (safeTask.length > 200 ? '…' : '')) + '</div>'
|
|
@@ -2074,6 +2091,7 @@ document.querySelector('[data-tab="markets"]')?.addEventListener('click', loadMa
|
|
|
2074
2091
|
const initialHash = (location.hash || '').replace(/^#/, '');
|
|
2075
2092
|
if (initialHash && initialHash !== 'overview' && document.getElementById('tab-' + initialHash)) {
|
|
2076
2093
|
activateTab(initialHash);
|
|
2094
|
+
if (initialHash === 'calls') loadCalls();
|
|
2077
2095
|
}
|
|
2078
2096
|
}
|
|
2079
2097
|
|
package/dist/phone/call-log.js
CHANGED
|
@@ -100,24 +100,30 @@ export class CallLog {
|
|
|
100
100
|
summary(limit = 50) {
|
|
101
101
|
const all = this.all();
|
|
102
102
|
const latest = new Map();
|
|
103
|
+
const paidByCall = new Map();
|
|
103
104
|
for (const e of all) {
|
|
105
|
+
paidByCall.set(e.call_id, Math.max(paidByCall.get(e.call_id) ?? 0, e.paid_usd));
|
|
104
106
|
const cur = latest.get(e.call_id);
|
|
105
107
|
// Keep the row with the FRESHEST timestamp per call_id (status updates).
|
|
106
108
|
if (!cur || e.timestamp >= cur.timestamp)
|
|
107
109
|
latest.set(e.call_id, e);
|
|
108
110
|
}
|
|
109
111
|
// Sort newest-first by the latest-row timestamp.
|
|
110
|
-
const list = Array.from(latest.values())
|
|
112
|
+
const list = Array.from(latest.values())
|
|
113
|
+
.map(e => ({ ...e, paid_usd: paidByCall.get(e.call_id) ?? e.paid_usd }))
|
|
114
|
+
.sort((a, b) => b.timestamp - a.timestamp);
|
|
111
115
|
return list.slice(0, limit);
|
|
112
116
|
}
|
|
113
117
|
byCallId(callId) {
|
|
114
118
|
let best = null;
|
|
119
|
+
let paidUsd = 0;
|
|
115
120
|
for (const e of this.all()) {
|
|
116
121
|
if (e.call_id !== callId)
|
|
117
122
|
continue;
|
|
123
|
+
paidUsd = Math.max(paidUsd, e.paid_usd);
|
|
118
124
|
if (!best || e.timestamp >= best.timestamp)
|
|
119
125
|
best = e;
|
|
120
126
|
}
|
|
121
|
-
return best;
|
|
127
|
+
return best ? { ...best, paid_usd: paidUsd } : null;
|
|
122
128
|
}
|
|
123
129
|
}
|
package/dist/tools/voice.js
CHANGED
|
@@ -346,7 +346,7 @@ export const voiceStatusCapability = {
|
|
|
346
346
|
callLog().append({
|
|
347
347
|
...prior,
|
|
348
348
|
timestamp: Date.now(),
|
|
349
|
-
paid_usd:
|
|
349
|
+
paid_usd: prior.paid_usd, // status polls are free; preserve the per-call total
|
|
350
350
|
status: normalizeStatus(res.status ?? res.queue_status ?? res.disposition),
|
|
351
351
|
duration_sec: duration ?? prior.duration_sec,
|
|
352
352
|
transcript: transcript ?? prior.transcript,
|
package/package.json
CHANGED