callix-dialer-widget 2.8.0 → 2.8.2
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/WIDGET-README.md
CHANGED
|
@@ -141,6 +141,19 @@ Entrar, avisado de que encerra a sessão de lá. Se o Callix derrubar a sessão
|
|
|
141
141
|
Callix web, supervisor, bloqueio), o widget volta à tela de login com o motivo e não reentra
|
|
142
142
|
sozinho.
|
|
143
143
|
|
|
144
|
+
Pausas no modo motor (2.8.1): a lista de pausas é a do serviço no Callix, trazida pela vista
|
|
145
|
+
do motor; a pausa escolhida vai no comando `pause` e o discador mostra o nome dela. Com um
|
|
146
|
+
motor anterior ao 2.8.1 a lista cai numa pausa única ("Pausa") e o motor usa a configurada
|
|
147
|
+
nele. O widget também informa a própria versão ao host, que a registra no log: é o jeito de
|
|
148
|
+
achar navegadores com um build antigo em cache. No console da página, `CallixDialer.version`
|
|
149
|
+
diz qual build está carregado.
|
|
150
|
+
|
|
151
|
+
Comandos durante uma queda da conexão (2.8.2): um clique dado enquanto a conexão com o host
|
|
152
|
+
está caída ou reconectando (rede instável) não se perde mais em silêncio. O comando fica
|
|
153
|
+
guardado, a tela avisa que a conexão está voltando, e ele é enviado no reconectar, se ainda
|
|
154
|
+
tiver menos de 15 s; mais velho que isso é descartado, para não atingir outra chamada. Antes,
|
|
155
|
+
um "encerrar" dado nesse momento deixava a chamada ativa no motor.
|
|
156
|
+
|
|
144
157
|
Sem `engineUrl` nada muda: o SDK continua rodando no navegador como sempre.
|
|
145
158
|
|
|
146
159
|
## 🔐 Login e usuário conhecido
|
|
@@ -43754,6 +43754,8 @@ const INITIAL_TRANSCRIPT = { segments: [], status: null, insight: null, interims
|
|
|
43754
43754
|
const MAX_SEGMENTS = 300;
|
|
43755
43755
|
const RECONNECT_MIN_MS = 500;
|
|
43756
43756
|
const RECONNECT_MAX_MS = 5e3;
|
|
43757
|
+
const PENDING_COMMANDS_MAX = 10;
|
|
43758
|
+
const PENDING_COMMANDS_TTL_MS = 15e3;
|
|
43757
43759
|
function engineWsUrl(baseUrl) {
|
|
43758
43760
|
const url = new URL(baseUrl, typeof window !== "undefined" ? window.location.href : "http://localhost");
|
|
43759
43761
|
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
@@ -43771,6 +43773,7 @@ class EngineClient {
|
|
|
43771
43773
|
this.viewWaiters = [];
|
|
43772
43774
|
this.ws = null;
|
|
43773
43775
|
this.reconnectDelay = RECONNECT_MIN_MS;
|
|
43776
|
+
this.pendingCommands = [];
|
|
43774
43777
|
this.reconnectTimer = null;
|
|
43775
43778
|
this.closed = false;
|
|
43776
43779
|
this.iceServers = [{ urls: "stun:stun.l.google.com:19302" }];
|
|
@@ -43838,6 +43841,7 @@ class EngineClient {
|
|
|
43838
43841
|
role: "tab",
|
|
43839
43842
|
agentId: this.agentId,
|
|
43840
43843
|
...this.options.token ? { token: this.options.token } : {},
|
|
43844
|
+
...this.options.version ? { version: this.options.version } : {},
|
|
43841
43845
|
...sessionToken ? { sessionToken } : {},
|
|
43842
43846
|
label: this.options.label ?? "Discador",
|
|
43843
43847
|
...this.session ? { session: this.session } : {}
|
|
@@ -43920,6 +43924,7 @@ class EngineClient {
|
|
|
43920
43924
|
case "welcome": {
|
|
43921
43925
|
if (Array.isArray(message.iceServers) && message.iceServers.length > 0) this.iceServers = message.iceServers;
|
|
43922
43926
|
this.setState({ tabId: message.tabId, rejected: null });
|
|
43927
|
+
this.flushPendingCommands();
|
|
43923
43928
|
this.applyView(message.view);
|
|
43924
43929
|
this.log(`sou a aba ${message.tabId}`);
|
|
43925
43930
|
if (this.options.autoEngage !== false && message.view.engagedTabId !== message.tabId) this.engage();
|
|
@@ -44012,8 +44017,17 @@ class EngineClient {
|
|
|
44012
44017
|
this.session = session;
|
|
44013
44018
|
this.setState({ rejected: null, sessionLost: null });
|
|
44014
44019
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
44015
|
-
this.
|
|
44016
|
-
|
|
44020
|
+
if (this.state.tabId) {
|
|
44021
|
+
this.send({ type: "session", session });
|
|
44022
|
+
return;
|
|
44023
|
+
}
|
|
44024
|
+
const stale = this.ws;
|
|
44025
|
+
this.ws = null;
|
|
44026
|
+
stale.onopen = null;
|
|
44027
|
+
stale.onmessage = null;
|
|
44028
|
+
stale.onclose = null;
|
|
44029
|
+
stale.close();
|
|
44030
|
+
this.setState({ wsState: "closed" });
|
|
44017
44031
|
}
|
|
44018
44032
|
if (this.reconnectTimer) {
|
|
44019
44033
|
clearTimeout(this.reconnectTimer);
|
|
@@ -44029,8 +44043,29 @@ class EngineClient {
|
|
|
44029
44043
|
this.send({ type: "release" });
|
|
44030
44044
|
}
|
|
44031
44045
|
command(command) {
|
|
44032
|
-
this.
|
|
44033
|
-
|
|
44046
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN && this.state.tabId) {
|
|
44047
|
+
this.send({ type: "command", command });
|
|
44048
|
+
this.log(`comando: ${command.name}${command.phone ? ` ${command.phone}` : ""}`);
|
|
44049
|
+
return;
|
|
44050
|
+
}
|
|
44051
|
+
this.pendingCommands.push({ command, at: Date.now() });
|
|
44052
|
+
if (this.pendingCommands.length > PENDING_COMMANDS_MAX) this.pendingCommands.shift();
|
|
44053
|
+
this.log(`comando: ${command.name} guardado até a conexão com o motor voltar`);
|
|
44054
|
+
this.setState({ lastError: "Sem conexão com o motor neste momento; o comando será enviado assim que ela voltar." });
|
|
44055
|
+
this.connect();
|
|
44056
|
+
}
|
|
44057
|
+
/** manda os comandos guardados que ainda fazem sentido (os velhos poderiam atingir outra chamada) */
|
|
44058
|
+
flushPendingCommands() {
|
|
44059
|
+
const now = Date.now();
|
|
44060
|
+
const pending = this.pendingCommands.splice(0);
|
|
44061
|
+
for (const entry of pending) {
|
|
44062
|
+
if (now - entry.at > PENDING_COMMANDS_TTL_MS) {
|
|
44063
|
+
this.log(`comando ${entry.command.name} descartado: a conexão demorou demais para voltar`);
|
|
44064
|
+
continue;
|
|
44065
|
+
}
|
|
44066
|
+
this.send({ type: "command", command: entry.command });
|
|
44067
|
+
this.log(`comando: ${entry.command.name} (enviado depois da reconexão)`);
|
|
44068
|
+
}
|
|
44034
44069
|
}
|
|
44035
44070
|
// ------------------------------------------------------------------ áudio
|
|
44036
44071
|
setInputMuted(muted) {
|
|
@@ -44219,6 +44254,18 @@ function useEngineState(client2) {
|
|
|
44219
44254
|
return useSyncExternalStore(client2.subscribe.bind(client2), client2.getState.bind(client2), client2.getState.bind(client2));
|
|
44220
44255
|
}
|
|
44221
44256
|
const ENGINE_BREAKS = [{ id: 0, name: "Pausa" }];
|
|
44257
|
+
function breaksFromView(view) {
|
|
44258
|
+
var _a2;
|
|
44259
|
+
const breaks = (_a2 = view == null ? void 0 : view.snapshot) == null ? void 0 : _a2.leg.breaks;
|
|
44260
|
+
return breaks && breaks.length > 0 ? breaks.map((b) => ({ id: b.id, name: b.name })) : ENGINE_BREAKS;
|
|
44261
|
+
}
|
|
44262
|
+
function currentBreakFromView(view) {
|
|
44263
|
+
var _a2;
|
|
44264
|
+
return ((_a2 = view.snapshot) == null ? void 0 : _a2.leg.break) ?? breaksFromView(view)[0];
|
|
44265
|
+
}
|
|
44266
|
+
function pauseCommand(breakId) {
|
|
44267
|
+
return typeof breakId === "number" ? { name: "pause", breakId } : { name: "pause" };
|
|
44268
|
+
}
|
|
44222
44269
|
function toCallQualification(q) {
|
|
44223
44270
|
return { id: q.id, name: q.name, isSystemQualification: false, systemQualificationType: 0 };
|
|
44224
44271
|
}
|
|
@@ -44351,7 +44398,7 @@ function operatorStateFromView(view, call) {
|
|
|
44351
44398
|
case "afterCall":
|
|
44352
44399
|
return { state: "afterCall" };
|
|
44353
44400
|
case "onBreak":
|
|
44354
|
-
return { state: "onBreak", break:
|
|
44401
|
+
return { state: "onBreak", break: currentBreakFromView(view) };
|
|
44355
44402
|
case "offline":
|
|
44356
44403
|
return { state: "offline" };
|
|
44357
44404
|
case "error":
|
|
@@ -44434,7 +44481,7 @@ function useEngineControls(client2) {
|
|
|
44434
44481
|
if (status === "onBreak") client2.command({ name: "resume" });
|
|
44435
44482
|
},
|
|
44436
44483
|
goOffline: () => void 0,
|
|
44437
|
-
enterOnBreak: () => client2.command(
|
|
44484
|
+
enterOnBreak: (breakId) => client2.command(pauseCommand(breakId)),
|
|
44438
44485
|
makeManualCall: (phoneNumber) => client2.command({ name: "dial", phone: phoneNumber }),
|
|
44439
44486
|
finishAfterCall: (data) => {
|
|
44440
44487
|
if (typeof data.qualificationId === "number") client2.command({ name: "qualify", qualificationId: data.qualificationId, result: data.result === "failure" ? "discard" : "success" });
|
|
@@ -44488,7 +44535,8 @@ const operators = /* @__PURE__ */ new WeakMap();
|
|
|
44488
44535
|
function engineOperator(client2) {
|
|
44489
44536
|
let operator = operators.get(client2);
|
|
44490
44537
|
if (!operator) {
|
|
44491
|
-
const breaks = new EngineSignal(
|
|
44538
|
+
const breaks = new EngineSignal(breaksFromView(client2.getState().view));
|
|
44539
|
+
client2.subscribe(() => breaks.set(breaksFromView(client2.getState().view)));
|
|
44492
44540
|
operator = {
|
|
44493
44541
|
breaks,
|
|
44494
44542
|
user: client2.userSignal,
|
|
@@ -44503,7 +44551,7 @@ function engineOperator(client2) {
|
|
|
44503
44551
|
var _a2, _b;
|
|
44504
44552
|
if (((_b = (_a2 = client2.getState().view) == null ? void 0 : _a2.snapshot) == null ? void 0 : _b.leg.status) === "onBreak") client2.command({ name: "resume" });
|
|
44505
44553
|
},
|
|
44506
|
-
enterOnBreak: () => client2.command(
|
|
44554
|
+
enterOnBreak: (breakId) => client2.command(pauseCommand(breakId)),
|
|
44507
44555
|
makeManualCall: (phoneNumber) => client2.command({ name: "dial", phone: phoneNumber }),
|
|
44508
44556
|
finishAfterCall: (data) => {
|
|
44509
44557
|
if (typeof data.qualificationId === "number") client2.command({ name: "qualify", qualificationId: data.qualificationId, result: data.result === "failure" ? "discard" : "success" });
|
|
@@ -58687,7 +58735,7 @@ function AuthenticatedMobileDialer({
|
|
|
58687
58735
|
showClientInfoModal = false,
|
|
58688
58736
|
density
|
|
58689
58737
|
}) {
|
|
58690
|
-
var _a2, _b, _c, _d;
|
|
58738
|
+
var _a2, _b, _c, _d, _e;
|
|
58691
58739
|
const { skipManualQualification } = useDialerConfig();
|
|
58692
58740
|
const [dialValue, setDialValue] = useState("");
|
|
58693
58741
|
const [activeScreen, setActiveScreen] = useState("dialer");
|
|
@@ -59400,11 +59448,12 @@ function AuthenticatedMobileDialer({
|
|
|
59400
59448
|
if (isOnBreak) return "paused";
|
|
59401
59449
|
return "available";
|
|
59402
59450
|
}, [isError, isOnBreak]);
|
|
59451
|
+
const activeBreakName = (operatorState == null ? void 0 : operatorState.state) === "onBreak" ? (_a2 = operatorState.break) == null ? void 0 : _a2.name : void 0;
|
|
59403
59452
|
const statusBadgeText = useMemo(() => {
|
|
59404
59453
|
if (isError) return (dialerNotice == null ? void 0 : dialerNotice.source) === "device" ? dialerNotice.title : "Erro";
|
|
59405
|
-
if (isOnBreak) return currentBreakName || "Em pausa";
|
|
59454
|
+
if (isOnBreak) return currentBreakName || activeBreakName || "Em pausa";
|
|
59406
59455
|
return "Disponível";
|
|
59407
|
-
}, [dialerNotice, isError, isOnBreak, currentBreakName]);
|
|
59456
|
+
}, [dialerNotice, isError, isOnBreak, currentBreakName, activeBreakName]);
|
|
59408
59457
|
const pauseDurationLabel = useMemo(() => {
|
|
59409
59458
|
const hours = Math.floor(pauseDurationSeconds / 3600);
|
|
59410
59459
|
const minutes = Math.floor(pauseDurationSeconds % 3600 / 60).toString().padStart(2, "0");
|
|
@@ -59542,15 +59591,15 @@ function AuthenticatedMobileDialer({
|
|
|
59542
59591
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "client-card-header", children: [
|
|
59543
59592
|
/* @__PURE__ */ jsxRuntimeExports.jsx("i", { className: "fas fa-user-circle client-avatar" }),
|
|
59544
59593
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "client-main-info", children: [
|
|
59545
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-name", id: "clientName", children: findValue(contactData.finalData, ["DECISOR", "NOME", "CLIENTE", "PROSPECT"]) ?? ((
|
|
59546
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-company", id: "clientCompany", children: findValue(contactData.finalData, ["EMPRESA", "RAZAO SOCIAL", "RAZÃO SOCIAL", "RAZAO_SOCIAL"]) ?? ((
|
|
59594
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-name", id: "clientName", children: findValue(contactData.finalData, ["DECISOR", "NOME", "CLIENTE", "PROSPECT"]) ?? ((_b = callInfo.info.campaignContact) == null ? void 0 : _b.label) ?? "--" }),
|
|
59595
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-company", id: "clientCompany", children: findValue(contactData.finalData, ["EMPRESA", "RAZAO SOCIAL", "RAZÃO SOCIAL", "RAZAO_SOCIAL"]) ?? ((_c = callInfo.info.campaign) == null ? void 0 : _c.name) ?? "--" })
|
|
59547
59596
|
] })
|
|
59548
59597
|
] }),
|
|
59549
59598
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "client-card-divider" }),
|
|
59550
59599
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "client-info-list", children: [
|
|
59551
59600
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "client-info-row", children: [
|
|
59552
59601
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-info-label", children: "Socio" }),
|
|
59553
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-info-value", children: findValue(contactData.finalData, ["SOCIO", "PROSPECT", "DECISOR", "NOME", "CLIENTE"]) ?? ((
|
|
59602
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-info-value", children: findValue(contactData.finalData, ["SOCIO", "PROSPECT", "DECISOR", "NOME", "CLIENTE"]) ?? ((_d = callInfo.info.campaignContact) == null ? void 0 : _d.label) ?? "--" })
|
|
59554
59603
|
] }),
|
|
59555
59604
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "client-info-row", children: [
|
|
59556
59605
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "client-info-label", children: "Empresa" }),
|
|
@@ -59747,7 +59796,7 @@ function AuthenticatedMobileDialer({
|
|
|
59747
59796
|
{
|
|
59748
59797
|
isOpen: isClientInfoModalOpen,
|
|
59749
59798
|
campaignCallInfo,
|
|
59750
|
-
campaignContactPhoneId: ((
|
|
59799
|
+
campaignContactPhoneId: ((_e = currentCall == null ? void 0 : currentCall.data) == null ? void 0 : _e.campaignContactPhoneId) ?? null,
|
|
59751
59800
|
callDuration: callDurationSeconds,
|
|
59752
59801
|
isCallActive: isInCall || isConnecting,
|
|
59753
59802
|
onClose: () => setIsClientInfoModalOpen(false)
|
|
@@ -60731,7 +60780,7 @@ function ClickToCallAgent({ enabled = true, pollIntervalMs, sessionToken, onTask
|
|
|
60731
60780
|
}, [enabled, pollIntervalMs, sessionToken]);
|
|
60732
60781
|
return null;
|
|
60733
60782
|
}
|
|
60734
|
-
const WIDGET_VERSION = "2.8.
|
|
60783
|
+
const WIDGET_VERSION = "2.8.2";
|
|
60735
60784
|
let currentSipWebSocket = null;
|
|
60736
60785
|
function sendSipUnregisterIfPossible(ws) {
|
|
60737
60786
|
if (ws.readyState !== WebSocket.OPEN) return;
|
|
@@ -61131,6 +61180,7 @@ function DialerWrapper({ options, containerEl }) {
|
|
|
61131
61180
|
const client2 = new EngineClient({
|
|
61132
61181
|
url: options.engineUrl ?? "",
|
|
61133
61182
|
token: options.engineToken || void 0,
|
|
61183
|
+
version: WIDGET_VERSION,
|
|
61134
61184
|
// credencial da aba: o token da sessão do Callix guardado neste navegador (lido a cada
|
|
61135
61185
|
// hello, para a reconexão depois de uma troca de sessão pegar o token novo)
|
|
61136
61186
|
sessionToken: () => readStoredToken(user),
|