@subiz/widget-v4 4.1.214 → 4.1.215

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.
Files changed (30) hide show
  1. package/api.md +20 -8
  2. package/compiled_src/lib.js +2 -15
  3. package/compiled_src/store/api.js +0 -1
  4. package/compiled_src/store/store.js +65 -1
  5. package/dist/.HASH +1 -1
  6. package/dist/{1a12a372880.app.js → 1a12a5ed6a9.app.js} +1 -1
  7. package/dist/{1a12a372880.chat.html → 1a12a5ed6a9.chat.html} +1 -1
  8. package/dist/{1a12a372880.chat.js → 1a12a5ed6a9.chat.js} +1 -1
  9. package/dist/{1a12a372880.form.html → 1a12a5ed6a9.form.html} +1 -1
  10. package/dist/1a12a5ed6a9.form.js +1 -0
  11. package/dist/{1a12a372880.index.html → 1a12a5ed6a9.index.html} +1 -1
  12. package/dist/{1a12a372880.library.html → 1a12a5ed6a9.library.html} +1 -1
  13. package/dist/{1a12a372880.library.js → 1a12a5ed6a9.library.js} +1 -1
  14. package/dist/{1a12a372880.preview.html → 1a12a5ed6a9.preview.html} +1 -1
  15. package/dist/{1a12a372880.preview.js → 1a12a5ed6a9.preview.js} +1 -1
  16. package/dist/{1a12a372880.webview.js → 1a12a5ed6a9.webview.js} +1 -1
  17. package/dist/screenshoot.js +66 -16
  18. package/package.json +1 -1
  19. package/src/lib.js +2 -18
  20. package/src/store/api.js +0 -3
  21. package/src/store/store.js +51 -0
  22. package/dist/1a12a372880.form.js +0 -1
  23. /package/dist/{1a12a372880.127.js → 1a12a5ed6a9.127.js} +0 -0
  24. /package/dist/{1a12a372880.132.js → 1a12a5ed6a9.132.js} +0 -0
  25. /package/dist/{1a12a372880.185.js → 1a12a5ed6a9.185.js} +0 -0
  26. /package/dist/{1a12a372880.27.js → 1a12a5ed6a9.27.js} +0 -0
  27. /package/dist/{1a12a372880.278.js → 1a12a5ed6a9.278.js} +0 -0
  28. /package/dist/{1a12a372880.339.js → 1a12a5ed6a9.339.js} +0 -0
  29. /package/dist/{1a12a372880.459.js → 1a12a5ed6a9.459.js} +0 -0
  30. /package/dist/{1a12a372880.490.js → 1a12a5ed6a9.490.js} +0 -0
package/api.md CHANGED
@@ -1271,11 +1271,23 @@ subiz('waitReady', async function () {
1271
1271
  })
1272
1272
  ```
1273
1273
 
1274
- `getFormStatus(formId)` trả `{submitted, status, conversation_id?}`, chỉ hỗ trợ ID
1275
- website không bắt đầu bằng `cp`. Cả hội thoại đã kết thúc cũng được tính.
1276
- `status: 'found'` nghĩa là tìm thấy lần gửi; `'not_found_in_available_history'`
1277
- không khẳng định khách chưa từng gửi. Service hiện chỉ đọc tối đa 200 dòng lịch sử
1278
- khách trước khi lọc theo form, sau đó trả tối đa 6 hội thoại; cache và việc xóa dữ
1279
- liệu cũng ảnh hưởng kết quả. Lần gửi theo luồng cũ dùng hostname làm nguồn hoặc
1280
- CF7 ticket chưa được tra cứu bằng API này. Khách cần được nhận diện lại bằng cùng
1281
- phiên widget; không đảm bảo khi xóa dữ liệu trình duyệt hoặc đổi thiết bị.
1274
+ `getFormStatus(formId)` đọc qua store KV/LSDB của widget, không gọi API trạng thái
1275
+ hay lấy hội thoại. Sau khi submit thành công, SDK lưu dấu đã gửi trong 7 ngày,
1276
+ tách theo account, ID khách và ID form. Chỉ lưu mã hội thoại và thời điểm hết hạn,
1277
+ không lưu các giá trị khách nhập. Đọc trạng thái không gia hạn thời gian lưu.
1278
+
1279
+ Kết quả: `{submitted: true, status: 'found', conversation_id}` nếu còn hạn;
1280
+ `{submitted: false, status: 'not_found'}` nếu chưa lưu; `status: 'expired'` khi
1281
+ hết hạn (đồng thời xóa bản ghi); `status: 'storage_unavailable'` khi trình duyệt
1282
+ không cho truy cập localStorage. Lỗi lưu localStorage không biến một submit đã
1283
+ thành công thành thất bại. Website nên ẩn form ngay sau khi submit thành công.
1284
+
1285
+ SDK bỏ qua sự kiện realtime của hội thoại kênh form trước khi lấy chi tiết hội
1286
+ thoại; không mở hội thoại form trong chat widget. Luồng chat thông thường giữ
1287
+ nguyên. Trạng thái chỉ có trên cùng website/trình duyệt và cùng ID khách, không
1288
+ đồng bộ thiết bị khác, mất khi xóa localStorage. Các lần gửi trước khi bổ sung
1289
+ cơ chế lưu này không được tự khôi phục từ server.
1290
+
1291
+ SDK không truy cập localStorage trực tiếp: store dùng `kv.put/match/del` và
1292
+ LSDB hiện có. Khi widget dùng chế độ in-memory hoặc trình duyệt chặn lưu trữ,
1293
+ trạng thái có thể chỉ giữ trong bộ nhớ của trang và mất khi tải lại.
@@ -233,12 +233,12 @@ class Widget {
233
233
  return this.store.sendConversion(formid, values, impressiontoken);
234
234
  }
235
235
  const payload = formRequest(formid, values, options);
236
- return formResult(await this.store.api.submitWebsiteForm(formid, payload), 'submit');
236
+ return this.store.submitWebsiteForm(formid, payload);
237
237
  }
238
238
  async getFormStatus(formid) {
239
239
  validateWebsiteFormId(formid);
240
240
  await this.store.readyGate.entry();
241
- return formResult(await this.store.api.getWebsiteFormStatus(formid), 'status');
241
+ return this.store.getFormStatus(formid);
242
242
  }
243
243
  startConvo(req) {
244
244
  req = _index.default.cloneDeep(req) || {};
@@ -378,17 +378,4 @@ function formRequest(formid, fields, options = {}) {
378
378
  };
379
379
  })
380
380
  };
381
- }
382
- function formResult(response, operation) {
383
- const body = response && response.body;
384
- const detail = response && response.error || body && body.error;
385
- const status = response && response.code;
386
- const valid = operation === 'submit' ? body && typeof body.conversation_id === 'string' && body.conversation_id && typeof body.submission_id === 'string' && body.submission_id : body && typeof body.submitted === 'boolean' && typeof body.status === 'string';
387
- if (detail || !(status >= 200 && status < 300) || !valid) {
388
- const error = new Error('Subiz form request failed');
389
- error.code = detail && detail.code || 'form_request_failed';
390
- error.status = status;
391
- throw error;
392
- }
393
- return body;
394
381
  }
@@ -65,7 +65,6 @@ class _default {
65
65
  _defineProperty(this, "sendEvent", data => this.apireq.addQuery('shorten', true).addQuery('x-referer', _index.default.get(location, 'origin', '')).post(`/accounts/${this.accid}/users/${this.uid}/events`, data));
66
66
  _defineProperty(this, "websiteFormRequest", () => this.apireq.setBaseUrl(this.ApiURL.replace(/\/4\.[01]\/?$/, '/4.1')));
67
67
  _defineProperty(this, "submitWebsiteForm", (formid, payload) => this.websiteFormRequest().post(`/accounts/${this.accid}/external-forms/${encodeURIComponent(formid)}/submissions`, payload));
68
- _defineProperty(this, "getWebsiteFormStatus", formid => this.websiteFormRequest().get(`/accounts/${this.accid}/external-forms/${encodeURIComponent(formid)}/status`));
69
68
  _defineProperty(this, "submitForm", (form_id, page_url, device, data, user) => this.apireq.addQuery('x-referer', _index.default.get(location, 'origin', '')).post(`/accounts/${this.accid}/users/${this.uid}/events`, {
70
69
  by: {
71
70
  id: this.uid,
@@ -881,6 +881,53 @@ class Store {
881
881
  this.reconnectGate.open();
882
882
  }
883
883
  }
884
+ async submitWebsiteForm(formid, payload) {
885
+ await this.readyGate.entry();
886
+ const key = websiteFormStorageKey(this.api, formid);
887
+ const kv = this.kv;
888
+ const result = formResult(await this.api.submitWebsiteForm(formid, payload));
889
+ try {
890
+ kv.put(key, {
891
+ conversation_id: result.conversation_id,
892
+ expires_at: _index.default.Date.now() + 7 * 24 * 60 * 60 * 1000
893
+ });
894
+ } catch (_) {}
895
+ return result;
896
+ }
897
+ getFormStatus(formid) {
898
+ const key = websiteFormStorageKey(this.api, formid);
899
+ try {
900
+ const receipt = this.kv.match(key);
901
+ if (!receipt) return {
902
+ submitted: false,
903
+ status: 'not_found'
904
+ };
905
+ if (!Number.isFinite(receipt.expires_at) || typeof receipt.conversation_id !== 'string' || !receipt.conversation_id) {
906
+ this.kv.del(key);
907
+ return {
908
+ submitted: false,
909
+ status: 'not_found'
910
+ };
911
+ }
912
+ if (receipt.expires_at <= _index.default.Date.now()) {
913
+ this.kv.del(key);
914
+ return {
915
+ submitted: false,
916
+ status: 'expired'
917
+ };
918
+ }
919
+ return {
920
+ submitted: true,
921
+ status: 'found',
922
+ conversation_id: receipt.conversation_id
923
+ };
924
+ } catch (_) {
925
+ return {
926
+ submitted: false,
927
+ status: 'storage_unavailable'
928
+ };
929
+ }
930
+ }
884
931
  async submitForm(formid, data, user) {
885
932
  await this.readyGate.entry();
886
933
  if (user) await this.setUser(user);
@@ -1008,6 +1055,7 @@ class Store {
1008
1055
  async _onWs(ev) {
1009
1056
  if (this._die) return;
1010
1057
  if (!ev || !ev.type) return;
1058
+ if (_index.default.get(ev, 'touchpoint.channel') === 'form' || _index.default.get(ev, 'data.conversation.touchpoint.channel') === 'form') return;
1011
1059
  ev.created = _index.default.getMs(ev.created);
1012
1060
  if (ev.type === 'user_info_updated') {
1013
1061
  return;
@@ -1757,4 +1805,20 @@ var xhrsend = function (method, url, body, cb) {
1757
1805
  if (body) request.setRequestHeader('content-type', 'text/plain');
1758
1806
  request.send(body);
1759
1807
  };
1760
- const dieErr = new Error('sdk unloaded');
1808
+ const dieErr = new Error('sdk unloaded');
1809
+ function websiteFormStorageKey(api, formid) {
1810
+ return 'sbz_form_submitted:' + _index.default.stringify([api.accid, api.uid, formid]);
1811
+ }
1812
+ function formResult(response) {
1813
+ const body = response && response.body;
1814
+ const detail = response && response.error || body && body.error;
1815
+ const status = response && response.code;
1816
+ const valid = body && typeof body.conversation_id === 'string' && body.conversation_id && typeof body.submission_id === 'string' && body.submission_id;
1817
+ if (detail || !(status >= 200 && status < 300) || !valid) {
1818
+ const error = new Error('Subiz form request failed');
1819
+ error.code = detail && detail.code || 'form_request_failed';
1820
+ error.status = status;
1821
+ throw error;
1822
+ }
1823
+ return body;
1824
+ }
package/dist/.HASH CHANGED
@@ -1 +1 @@
1
- 1a12a372880
1
+ 1a12a5ed6a9