@fui-org/fui-cli 0.2.0 → 0.3.0

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 (212) hide show
  1. package/README.md +13 -1
  2. package/dist/fui.js +160 -43
  3. package/package.json +4 -2
  4. package/skills/fui/SKILL.md +131 -66
  5. package/skills/fui-skill/README.md +112 -0
  6. package/skills/fui-skill/SKILL.md +269 -0
  7. package/skills/fui-skill/assets/projectdefaultstyle.css +518 -0
  8. package/skills/fui-skill/design-md/airbnb/DESIGN.md +545 -0
  9. package/skills/fui-skill/design-md/airbnb/README.md +5 -0
  10. package/skills/fui-skill/design-md/airtable/DESIGN.md +554 -0
  11. package/skills/fui-skill/design-md/airtable/README.md +5 -0
  12. package/skills/fui-skill/design-md/apple/DESIGN.md +562 -0
  13. package/skills/fui-skill/design-md/apple/README.md +5 -0
  14. package/skills/fui-skill/design-md/asu/DESIGN.md +179 -0
  15. package/skills/fui-skill/design-md/asu/README.md +107 -0
  16. package/skills/fui-skill/design-md/binance/DESIGN.md +634 -0
  17. package/skills/fui-skill/design-md/binance/README.md +5 -0
  18. package/skills/fui-skill/design-md/bmw/DESIGN.md +544 -0
  19. package/skills/fui-skill/design-md/bmw/README.md +5 -0
  20. package/skills/fui-skill/design-md/bmw-m/DESIGN.md +503 -0
  21. package/skills/fui-skill/design-md/bmw-m/README.md +5 -0
  22. package/skills/fui-skill/design-md/bugatti/DESIGN.md +454 -0
  23. package/skills/fui-skill/design-md/bugatti/README.md +5 -0
  24. package/skills/fui-skill/design-md/cal/DESIGN.md +542 -0
  25. package/skills/fui-skill/design-md/cal/README.md +5 -0
  26. package/skills/fui-skill/design-md/claude/DESIGN.md +589 -0
  27. package/skills/fui-skill/design-md/claude/README.md +5 -0
  28. package/skills/fui-skill/design-md/clay/DESIGN.md +541 -0
  29. package/skills/fui-skill/design-md/clay/README.md +5 -0
  30. package/skills/fui-skill/design-md/clickhouse/DESIGN.md +544 -0
  31. package/skills/fui-skill/design-md/clickhouse/README.md +5 -0
  32. package/skills/fui-skill/design-md/cohere/DESIGN.md +451 -0
  33. package/skills/fui-skill/design-md/cohere/README.md +5 -0
  34. package/skills/fui-skill/design-md/coinbase/DESIGN.md +570 -0
  35. package/skills/fui-skill/design-md/coinbase/README.md +5 -0
  36. package/skills/fui-skill/design-md/composio/DESIGN.md +506 -0
  37. package/skills/fui-skill/design-md/composio/README.md +5 -0
  38. package/skills/fui-skill/design-md/cursor/DESIGN.md +537 -0
  39. package/skills/fui-skill/design-md/cursor/README.md +5 -0
  40. package/skills/fui-skill/design-md/elevenlabs/DESIGN.md +504 -0
  41. package/skills/fui-skill/design-md/elevenlabs/README.md +5 -0
  42. package/skills/fui-skill/design-md/expo/DESIGN.md +526 -0
  43. package/skills/fui-skill/design-md/expo/README.md +5 -0
  44. package/skills/fui-skill/design-md/ferrari/DESIGN.md +531 -0
  45. package/skills/fui-skill/design-md/ferrari/README.md +5 -0
  46. package/skills/fui-skill/design-md/figma/DESIGN.md +578 -0
  47. package/skills/fui-skill/design-md/figma/README.md +5 -0
  48. package/skills/fui-skill/design-md/framer/DESIGN.md +544 -0
  49. package/skills/fui-skill/design-md/framer/README.md +5 -0
  50. package/skills/fui-skill/design-md/fui/DESIGN.md +532 -0
  51. package/skills/fui-skill/design-md/hashicorp/DESIGN.md +575 -0
  52. package/skills/fui-skill/design-md/hashicorp/README.md +5 -0
  53. package/skills/fui-skill/design-md/ibm/DESIGN.md +550 -0
  54. package/skills/fui-skill/design-md/ibm/README.md +5 -0
  55. package/skills/fui-skill/design-md/intercom/DESIGN.md +546 -0
  56. package/skills/fui-skill/design-md/intercom/README.md +5 -0
  57. package/skills/fui-skill/design-md/kraken/DESIGN.md +125 -0
  58. package/skills/fui-skill/design-md/kraken/README.md +5 -0
  59. package/skills/fui-skill/design-md/lamborghini/DESIGN.md +288 -0
  60. package/skills/fui-skill/design-md/lamborghini/README.md +5 -0
  61. package/skills/fui-skill/design-md/linear.app/DESIGN.md +548 -0
  62. package/skills/fui-skill/design-md/linear.app/README.md +5 -0
  63. package/skills/fui-skill/design-md/lovable/DESIGN.md +298 -0
  64. package/skills/fui-skill/design-md/lovable/README.md +5 -0
  65. package/skills/fui-skill/design-md/mastercard/DESIGN.md +365 -0
  66. package/skills/fui-skill/design-md/mastercard/README.md +5 -0
  67. package/skills/fui-skill/design-md/meta/DESIGN.md +683 -0
  68. package/skills/fui-skill/design-md/meta/README.md +5 -0
  69. package/skills/fui-skill/design-md/minimax/DESIGN.md +746 -0
  70. package/skills/fui-skill/design-md/minimax/README.md +5 -0
  71. package/skills/fui-skill/design-md/mintlify/DESIGN.md +852 -0
  72. package/skills/fui-skill/design-md/mintlify/README.md +5 -0
  73. package/skills/fui-skill/design-md/miro/DESIGN.md +825 -0
  74. package/skills/fui-skill/design-md/miro/README.md +5 -0
  75. package/skills/fui-skill/design-md/mistral.ai/DESIGN.md +773 -0
  76. package/skills/fui-skill/design-md/mistral.ai/README.md +5 -0
  77. package/skills/fui-skill/design-md/mongodb/DESIGN.md +767 -0
  78. package/skills/fui-skill/design-md/mongodb/README.md +5 -0
  79. package/skills/fui-skill/design-md/nike/DESIGN.md +575 -0
  80. package/skills/fui-skill/design-md/nike/README.md +5 -0
  81. package/skills/fui-skill/design-md/notion/DESIGN.md +821 -0
  82. package/skills/fui-skill/design-md/notion/README.md +5 -0
  83. package/skills/fui-skill/design-md/nvidia/DESIGN.md +640 -0
  84. package/skills/fui-skill/design-md/nvidia/README.md +5 -0
  85. package/skills/fui-skill/design-md/ollama/DESIGN.md +539 -0
  86. package/skills/fui-skill/design-md/ollama/README.md +5 -0
  87. package/skills/fui-skill/design-md/opencode.ai/DESIGN.md +521 -0
  88. package/skills/fui-skill/design-md/opencode.ai/README.md +5 -0
  89. package/skills/fui-skill/design-md/pinterest/DESIGN.md +597 -0
  90. package/skills/fui-skill/design-md/pinterest/README.md +5 -0
  91. package/skills/fui-skill/design-md/playstation/DESIGN.md +661 -0
  92. package/skills/fui-skill/design-md/playstation/README.md +5 -0
  93. package/skills/fui-skill/design-md/posthog/DESIGN.md +690 -0
  94. package/skills/fui-skill/design-md/posthog/README.md +5 -0
  95. package/skills/fui-skill/design-md/raycast/DESIGN.md +669 -0
  96. package/skills/fui-skill/design-md/raycast/README.md +5 -0
  97. package/skills/fui-skill/design-md/renault/DESIGN.md +589 -0
  98. package/skills/fui-skill/design-md/renault/README.md +5 -0
  99. package/skills/fui-skill/design-md/replicate/DESIGN.md +616 -0
  100. package/skills/fui-skill/design-md/replicate/README.md +5 -0
  101. package/skills/fui-skill/design-md/resend/DESIGN.md +585 -0
  102. package/skills/fui-skill/design-md/resend/README.md +5 -0
  103. package/skills/fui-skill/design-md/revolut/DESIGN.md +636 -0
  104. package/skills/fui-skill/design-md/revolut/README.md +5 -0
  105. package/skills/fui-skill/design-md/runwayml/DESIGN.md +244 -0
  106. package/skills/fui-skill/design-md/runwayml/README.md +5 -0
  107. package/skills/fui-skill/design-md/sanity/DESIGN.md +357 -0
  108. package/skills/fui-skill/design-md/sanity/README.md +5 -0
  109. package/skills/fui-skill/design-md/sentry/DESIGN.md +551 -0
  110. package/skills/fui-skill/design-md/sentry/README.md +5 -0
  111. package/skills/fui-skill/design-md/shopify/DESIGN.md +516 -0
  112. package/skills/fui-skill/design-md/shopify/README.md +5 -0
  113. package/skills/fui-skill/design-md/slack/DESIGN.md +482 -0
  114. package/skills/fui-skill/design-md/spacex/DESIGN.md +363 -0
  115. package/skills/fui-skill/design-md/spacex/README.md +5 -0
  116. package/skills/fui-skill/design-md/spotify/DESIGN.md +246 -0
  117. package/skills/fui-skill/design-md/spotify/README.md +5 -0
  118. package/skills/fui-skill/design-md/starbucks/DESIGN.md +580 -0
  119. package/skills/fui-skill/design-md/starbucks/README.md +5 -0
  120. package/skills/fui-skill/design-md/stripe/DESIGN.md +487 -0
  121. package/skills/fui-skill/design-md/stripe/README.md +5 -0
  122. package/skills/fui-skill/design-md/supabase/DESIGN.md +462 -0
  123. package/skills/fui-skill/design-md/supabase/README.md +5 -0
  124. package/skills/fui-skill/design-md/superhuman/DESIGN.md +448 -0
  125. package/skills/fui-skill/design-md/superhuman/README.md +5 -0
  126. package/skills/fui-skill/design-md/tesla/DESIGN.md +286 -0
  127. package/skills/fui-skill/design-md/tesla/README.md +5 -0
  128. package/skills/fui-skill/design-md/theverge/DESIGN.md +339 -0
  129. package/skills/fui-skill/design-md/theverge/README.md +5 -0
  130. package/skills/fui-skill/design-md/together.ai/DESIGN.md +633 -0
  131. package/skills/fui-skill/design-md/together.ai/README.md +5 -0
  132. package/skills/fui-skill/design-md/uber/DESIGN.md +636 -0
  133. package/skills/fui-skill/design-md/uber/README.md +5 -0
  134. package/skills/fui-skill/design-md/vercel/DESIGN.md +736 -0
  135. package/skills/fui-skill/design-md/vercel/README.md +5 -0
  136. package/skills/fui-skill/design-md/vodafone/DESIGN.md +538 -0
  137. package/skills/fui-skill/design-md/vodafone/README.md +5 -0
  138. package/skills/fui-skill/design-md/voltagent/DESIGN.md +521 -0
  139. package/skills/fui-skill/design-md/voltagent/README.md +5 -0
  140. package/skills/fui-skill/design-md/warp/DESIGN.md +526 -0
  141. package/skills/fui-skill/design-md/warp/README.md +5 -0
  142. package/skills/fui-skill/design-md/webflow/DESIGN.md +588 -0
  143. package/skills/fui-skill/design-md/webflow/README.md +5 -0
  144. package/skills/fui-skill/design-md/wired/DESIGN.md +497 -0
  145. package/skills/fui-skill/design-md/wired/README.md +5 -0
  146. package/skills/fui-skill/design-md/wise/DESIGN.md +544 -0
  147. package/skills/fui-skill/design-md/wise/README.md +5 -0
  148. package/skills/fui-skill/design-md/x.ai/DESIGN.md +465 -0
  149. package/skills/fui-skill/design-md/x.ai/README.md +5 -0
  150. package/skills/fui-skill/design-md/zapier/DESIGN.md +537 -0
  151. package/skills/fui-skill/design-md/zapier/README.md +5 -0
  152. package/skills/fui-skill/examples/component.vue +162 -0
  153. package/skills/fui-skill/examples/f-table-patterns.json +331 -0
  154. package/skills/fui-skill/examples/module-patterns.json +973 -0
  155. package/skills/fui-skill/examples/project-patterns.json +222 -0
  156. package/skills/fui-skill/metadata.json +75 -0
  157. package/skills/fui-skill/references/INDEX.md +144 -0
  158. package/skills/fui-skill/references/advanced-techniques.md +160 -0
  159. package/skills/fui-skill/references/coding-standards.md +112 -0
  160. package/skills/fui-skill/references/component-design.md +455 -0
  161. package/skills/fui-skill/references/component-quickref.md +77 -0
  162. package/skills/fui-skill/references/component-table.md +276 -0
  163. package/skills/fui-skill/references/components-dialog.md +192 -0
  164. package/skills/fui-skill/references/components-display.md +147 -0
  165. package/skills/fui-skill/references/components-echart.md +391 -0
  166. package/skills/fui-skill/references/components-input.md +359 -0
  167. package/skills/fui-skill/references/controls-patterns.md +847 -0
  168. package/skills/fui-skill/references/controls-styling-vocabulary.md +140 -0
  169. package/skills/fui-skill/references/db-table-design.md +77 -0
  170. package/skills/fui-skill/references/db-workflow.md +504 -0
  171. package/skills/fui-skill/references/default-function.md +415 -0
  172. package/skills/fui-skill/references/design-modes.md +85 -0
  173. package/skills/fui-skill/references/echart-templates.md +481 -0
  174. package/skills/fui-skill/references/fastproject.md +97 -0
  175. package/skills/fui-skill/references/fsheet.md +218 -0
  176. package/skills/fui-skill/references/fullstack-workflow.md +351 -0
  177. package/skills/fui-skill/references/module-data-patterns.md +126 -0
  178. package/skills/fui-skill/references/module-json-anatomy.md +137 -0
  179. package/skills/fui-skill/references/module-structure.md +260 -0
  180. package/skills/fui-skill/references/new-session.md +108 -0
  181. package/skills/fui-skill/references/pdfmake.md +60 -0
  182. package/skills/fui-skill/references/permission-system.md +169 -0
  183. package/skills/fui-skill/references/platform-architecture.md +294 -0
  184. package/skills/fui-skill/references/project-config.md +335 -0
  185. package/skills/fui-skill/references/project-provisioning.md +383 -0
  186. package/skills/fui-skill/references/script-map.md +296 -0
  187. package/skills/fui-skill/references/sql-clr-functions.md +224 -0
  188. package/skills/fui-skill/references/system-design.md +116 -0
  189. package/skills/fui-skill/references/tapi-file-api.md +191 -0
  190. package/skills/fui-skill/references/tapi-permission-patterns.md +158 -0
  191. package/skills/fui-skill/references/tapi-reference.md +549 -0
  192. package/skills/fui-skill/references/tools-registry.md +460 -0
  193. package/skills/fui-skill/references/ui-crosswindow-patterns.md +317 -0
  194. package/skills/fui-skill/references/ui-dialog-patterns.md +229 -0
  195. package/skills/fui-skill/references/ui-layout-patterns.md +176 -0
  196. package/skills/fui-skill/references/ui-patterns.md +315 -0
  197. package/skills/fui-skill/references/ui-screenshot-review.md +94 -0
  198. package/skills/fui-skill/references/ui-table-cell-patterns.md +316 -0
  199. package/skills/fui-skill/references/ui-templates.md +29 -0
  200. package/skills/fui-skill/references/verification.md +246 -0
  201. package/skills/fui-skill/references/watcher-patterns.md +196 -0
  202. package/skills/fui-skill/references/websocket-realtime.md +254 -0
  203. package/skills/fui-skill/scripts/component-3.0.js +2549 -0
  204. package/skills/fui-skill/scripts/component.js +3142 -0
  205. package/skills/fui-skill/scripts/componentTable-3.0.js +909 -0
  206. package/skills/fui-skill/scripts/componentTable.js +769 -0
  207. package/skills/fui-skill/scripts/defaultfunction-3.0.js +781 -0
  208. package/skills/fui-skill/scripts/defaultfunction.js +966 -0
  209. package/skills/fui-skill/scripts/fastproject-3.0.js +870 -0
  210. package/skills/fui-skill/scripts/fastproject.js +828 -0
  211. package/skills/fui-skill/scripts/fechart.js +890 -0
  212. package/skills/fui-skill/scripts/fsheet.js +1330 -0
@@ -0,0 +1,781 @@
1
+ $isMobile = navigator.userAgent.match(/mobile|touch|android|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|ip(ad|hone|od)|iris|kindle|lge |maemo|meego.+mobile|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino|playbook|silk/i) != null;
2
+ $isPhone = navigator.userAgent.match(/mobile|touch|android|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|ip(hone|od)|iris|kindle|lge |maemo|meego.+mobile|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (phone)|xda|xiino|playbook|silk/i) != null;
3
+ $isApple = navigator.userAgent.match(/ip(ad|hone|od)/i) != null;
4
+ //===========================================================================
5
+ var Loader = function () { }
6
+ Loader.prototype = {
7
+ require: function (scripts, callback) {
8
+ this.loadCount = 0;
9
+ this.totalRequired = scripts.length;
10
+ this.callback = callback;
11
+
12
+ for (var i = 0; i < scripts.length; i++) {
13
+ this.writeScript(scripts[i]);
14
+ }
15
+ },
16
+ loaded: function (evt) {
17
+ this.loadCount++;
18
+
19
+ if (this.loadCount == this.totalRequired && typeof this.callback == 'function') this.callback.call();
20
+ },
21
+ writeScript: function (src) {
22
+ var self = this;
23
+ var s = document.createElement('script');
24
+ s.type = "text/javascript";
25
+ s.async = false;
26
+ s.src = src;
27
+ s.addEventListener('load', function (e) { self.loaded(e); }, false);
28
+ var head = document.getElementsByTagName('head')[0];
29
+ head.appendChild(s);
30
+ }
31
+ };
32
+ //===========================================================================================
33
+ function loadScripts(scriptsArray, callbackFunc) {
34
+ var scriptsArray = scriptsArray || new Array();
35
+ var callbackFunc = callbackFunc || function () { };
36
+
37
+ if (scriptsArray.length == 0) {
38
+ callbackFunc();
39
+ return;
40
+ }
41
+
42
+ var loadScript = new Loader();
43
+ loadScript.require(scriptsArray, callbackFunc);
44
+ }
45
+ //===================================================================================
46
+ //===================================================================================
47
+ //===========================================================================================
48
+ function extractHostname(url) {
49
+ var hostname;
50
+ //find & remove protocol (http, ftp, etc.) and get hostname
51
+
52
+ if (url.indexOf("//") > -1) {
53
+ hostname = url.split('/')[2];
54
+ } else {
55
+ hostname = url.split('/')[0];
56
+ }
57
+
58
+ //find & remove port number
59
+ hostname = hostname.split(':')[0];
60
+ //find & remove "?"
61
+ hostname = hostname.split('?')[0];
62
+
63
+ return hostname;
64
+ }
65
+ //===========================================================================================
66
+ const getDomainWithoutSubdomain = url => {
67
+ const urlParts = new URL(url).hostname.split('.')
68
+
69
+ return urlParts
70
+ .slice(0)
71
+ .slice(-(urlParts.length === 4 ? 3 : 2))
72
+ .join('.')
73
+ }
74
+ //===================================================================================
75
+ function pushRouter(router) {
76
+ var curPath = window.location.pathname;
77
+ if (curPath != router || curPath == '/') {
78
+ window.history.pushState({ id: router }, document.title, router);
79
+ }
80
+ }
81
+ //===================================================================================
82
+ function CALL(obj, includeData) {
83
+ runAction(obj, includeData);
84
+ }
85
+ //===================================================================================
86
+ function windowSendMessage(window, cmd, data) {
87
+ //console.log("windowSendMessage", cmd, data);
88
+ if (_.isObject(window)) {
89
+ window.postMessage({ cmd: cmd, value: JSON.parse(JSON.stringify(data)) }, '*');
90
+ } else
91
+ if (window == "#PARENT") {
92
+ parent.postMessage({ cmd: cmd, value: JSON.parse(JSON.stringify(data)) }, '*');
93
+ } else {
94
+ var win = document.getElementById(window.slice(1, window.length));
95
+ if (win) win.contentWindow.postMessage({ cmd: cmd, value: JSON.parse(JSON.stringify(data)) }, '*');
96
+ else console.log("send DATA: Window ID not found")
97
+ }
98
+ }
99
+ //===========================================================================================
100
+ function appCommand(cmdData) {
101
+ if (window.ReactNativeWebView) window.ReactNativeWebView.postMessage(cmdData);
102
+ else if (window.webkit) window.webkit.messageHandlers["scriptHandler"].postMessage(cmdData);
103
+ else if (window.scriptHandler) window.scriptHandler.postMessage(cmdData);
104
+ }
105
+ //===========================================================================================
106
+ function fillData(obj) {
107
+ if (!obj.key && !obj.src) { // FILL ALL DATA
108
+ var mapD = {};
109
+ _.forEach(obj.map, function (value, key) {
110
+ mapD[key] = bindData(value);
111
+ });
112
+
113
+ _.forEach(obj.des, function (desObj) {
114
+ _.forEach(mapD, function (value, key) {
115
+ desObj[key] = value;
116
+ });
117
+ });
118
+ return
119
+ }
120
+
121
+ var GroupKeySRC = _.groupBy(obj.src, obj.key);
122
+ _.forEach(obj.map, function (value, key) {
123
+ _.forEach(obj.des, function (desObj) {
124
+ var val = GroupKeySRC[desObj[obj.key]];
125
+ if (_.isString(value)) {
126
+ if (_.isArray(val)) val = val[0][value];
127
+ else val = null;
128
+ }
129
+ else if (_.isPlainObject(value)) {
130
+ if (_.isArray(val)) val = val[0];
131
+ else val = null;
132
+ }
133
+ desObj[key] = val;
134
+ });
135
+ });
136
+ }
137
+ //===========================================================================================
138
+ function groupBy(arrayObj, groupField, sumArr) { // vi du: groupBy(dsSinhVien, 'Khoa', ['SL Nghỉ Học','SL Tốt Nghiệp'])
139
+ var gArr = _.groupBy(arrayObj, groupField);
140
+ var returnArr = [];
141
+ var sumObj = {};
142
+ if (!_.isArray(sumArr)) sumArr = [sumArr];
143
+ //---------------------------------
144
+ _.forEach(gArr, function (fieldValue, fieldKey) {
145
+ var n = 0;
146
+ _.forEach(sumArr, function (v) {
147
+ sumObj[v] = 0;
148
+ });
149
+ _.forEach(fieldValue, function (value) {
150
+ n++;
151
+ _.forEach(sumArr, function (v) {
152
+ sumObj[v] = sumObj[v] + value[v];
153
+ });
154
+ });
155
+ var o = {};
156
+ o[groupField] = fieldKey;
157
+ o["count"] = n;
158
+ o = $.extend(o, sumObj);
159
+ returnArr.push(o);
160
+ });
161
+ return returnArr;
162
+ }
163
+ //===========================================================================================
164
+ function chartDataBuild(obj) {
165
+ if (obj.dataChart) {
166
+ var chartData = [];
167
+ var dataInput = obj.dataChart.data;
168
+
169
+ if (_.isUndefined(dataInput)) dataInput = obj.dataChart;
170
+
171
+ if (_.isArray(dataInput[0])) {
172
+ var chartName = JSON.parse(obj.dataChart.chartName);
173
+ _.forEach(dataInput, function (d, k) {
174
+ chartData.push({
175
+ name: chartName[k],
176
+ data: _.map(dataInput[k], function (n) {
177
+ return [n.label, n.value];
178
+ })
179
+ });
180
+ });
181
+ } else {
182
+ chartData.push({
183
+ name: (obj.dataChart.chartName ? obj.dataChart.chartName : null),
184
+ data: _.map(dataInput, function (n) {
185
+ return [n.label, n.value];
186
+ })
187
+ });
188
+ }
189
+ //---------------------
190
+ if (obj.allInOne) return [{ name: "", data: chartData }];
191
+ else return chartData;
192
+ }
193
+ }
194
+ //===========================================================================================
195
+ function chartQABuild(obj) {
196
+ if (obj.dataChart) {
197
+ var chartData = [];
198
+
199
+ _.forEach(obj.dataChart[0], function (v, i) { // Duyet tung cau hoi
200
+ if (v.QType == 'TextArea') {
201
+
202
+ } else {
203
+ chartData.push({
204
+ name: v.QText,
205
+ data: _.map(_.filter(obj.dataChart[1], ['QID', v.QID]), function (n) {
206
+ return [n.label, n.val];
207
+ })
208
+ });
209
+ }
210
+ });
211
+ return chartData;
212
+ }
213
+ }
214
+ //===========================================================================================
215
+ function confirm(obj) {
216
+ $.confirm({
217
+ icon: (obj.icon ? obj.icon : 'mdi mdi-help-circle-outline'),
218
+ title: obj.title,
219
+ content: (obj.message ? obj.message : ''),
220
+ type: (obj.type ? obj.type : 'blue'),
221
+ columnClass: 'v-col-xs-12 v-col-sm-8 v-col-md-6 v-col-lg-4',
222
+ animateFromElement: false,
223
+ buttons: {
224
+ ok: {
225
+ text: '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
226
+ btnClass: 'btn-blue',
227
+ keys: ['enter'],
228
+ action: obj.action
229
+ },
230
+ cancel: (obj.cancel ? obj.cancel : function () { })
231
+ }
232
+ });
233
+ }
234
+ //===========================================================================================
235
+ function showMessage(obj) {
236
+ $.dialog({
237
+ icon: (obj.icon ? obj.icon : 'mdi mdi-information-variant-circle-outline'),
238
+ title: (obj.title ? obj.title : ''),
239
+ backgroundDismiss: true,
240
+ content: (obj.message ? obj.message : ''),
241
+ type: (obj.type ? obj.type : 'blue'),
242
+ columnClass: 'v-col-xs-12 v-col-sm-8 v-col-md-6 v-col-lg-4',
243
+ animateFromElement: false,
244
+ closeIcon: true,
245
+ buttons: {
246
+ ok: {
247
+ text: '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Close&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
248
+ btnClass: 'btn-' + (obj.type ? obj.type : 'blue')
249
+ }
250
+ },
251
+ onClose: function () {
252
+ if (obj.onclose) {
253
+ runAction(obj.onclose, { item: obj.item });
254
+ }
255
+ },
256
+ });
257
+ }
258
+ //===========================================================================================
259
+ function rightTest(rightObject) {
260
+ var returnVal = true
261
+ _.forEach(rightObject, function (rV, rK) {
262
+ if (!returnVal) return;
263
+ var A1 = [];
264
+ var A2 = [];
265
+
266
+ if (_.isArray(rV)) A1 = rV;
267
+ else A1 = [rV];
268
+
269
+ if (_.isArray(vueData.user[rK])) A2 = vueData.user[rK];
270
+ else A2 = [vueData.user[rK]];
271
+
272
+ if (_.intersection(A1, A2).length <= 0) returnVal = false;
273
+ });
274
+ return returnVal;
275
+ }
276
+ //===========================================================================================
277
+ function openWindow(obj) {
278
+ if (window === top) {
279
+ setTimeout(function () {
280
+ if(obj.id != undefined && app.config.globalProperties.v_OpenWindowList.find(item => item.id === obj.id) != undefined){
281
+ console.log("Cửa sổ bị trùng tên: ", obj.id)
282
+ return;
283
+ }
284
+
285
+ if (_.isString(obj)) obj = { url: obj };
286
+ obj.uuid = "Window" + generateID();
287
+ app.config.globalProperties.v_OpenWindowList.push(obj);
288
+ }, 10);
289
+ }
290
+ else {
291
+ windowSendMessage('#PARENT', 'openWindow', obj);
292
+ }
293
+ }
294
+ //=========================================================================================
295
+ function redirect(obj, query) {
296
+ let Q = '';
297
+ if (obj && obj.url) Q = obj.url;
298
+ else Q = obj;
299
+
300
+ if ((query || (obj && obj.query)) && vueData.p_params != " ") {
301
+ if (Q.indexOf("?") < 0) Q = Q + vueData.p_params;
302
+ else Q = Q + vueData.p_params.replace("?", "");
303
+ }
304
+
305
+ location.assign(Q);
306
+ }
307
+ //===========================================================================================
308
+ function reload() {
309
+ location.assign(window.location.href);
310
+ }
311
+ //===========================================================================================
312
+ function findInArray(obj) {
313
+ if (_.isString(obj.value)) obj.value = JSON.parse(obj.value);
314
+ return _.find(obj.array, obj.value);
315
+ }
316
+ //===========================================================================================
317
+ function fixURL(url) {
318
+ if (url.indexOf('http') == 0) return url;
319
+ else return vueData.v_Set.apiDomain + url
320
+ }
321
+ //===========================================================================================
322
+ function stringAttrToJson(str, removeVueEvent) {
323
+ var jObj = {}
324
+
325
+ if (typeof str == 'undefined') str = "";
326
+
327
+ if (_.isPlainObject(str)) return str;
328
+
329
+ $(`<div ${str} >`).each(function () {
330
+ $.each(this.attributes, function (i, a) {
331
+ if (removeVueEvent && (typeof a.name == "string" && (a.name.substring(0, 1) == ":" || a.name.substring(0, 1) == "@" || a.name.substring(0, 2) == "v-"))) return;
332
+ jObj[a.name] = a.value;
333
+ })
334
+ })
335
+ return jObj
336
+ }
337
+ //===========================================================================================
338
+ function json_data_parse(obj, level) {
339
+ //--- convert to json data array --------
340
+ if (level > 3) return;
341
+
342
+ level++;
343
+ if (_.isArray(obj) && obj.length > 0) {
344
+ //console.log("json_data_parse", level)
345
+ if (_.isArray(obj[0])) {
346
+ _.forEach(obj, function (value) {
347
+ json_data_parse(value, level);
348
+ });
349
+ } else if (_.isPlainObject(obj[0])) {
350
+ var R = obj[0];
351
+ var nameOfJson = [];
352
+ _.forEach(R, function (value, key) {
353
+ if (key.substring(0, 10) == 'json_data:') nameOfJson.push(key);
354
+ });
355
+ _.forEach(obj, function (row) {
356
+ _.forEach(nameOfJson, function (key) {
357
+ row[key.replace('json_data:', '')] = JSON.parse(row[key]);
358
+ delete row[key];
359
+ });
360
+ });
361
+ }
362
+ } else if (_.isPlainObject(obj)) {
363
+ _.forEach(obj, function (value, key) {
364
+ if (key.substring(0, 10) == 'json_data:') {
365
+ obj[key.replace('json_data:', '')] = JSON.parse(value);
366
+ delete obj[key];
367
+ } else {
368
+ if (_.isObject(value)) json_data_parse(value, level);
369
+ }
370
+ });
371
+ }
372
+ }
373
+ //===========================================================================================
374
+ function ajaxCALL(URL, DATA, callBack, errorCallBack, header) {
375
+ let loadingID = generateID();
376
+ app.config.globalProperties.v_LoadingOverlay.push(loadingID);
377
+ app.config.globalProperties.v_Loading = true;
378
+
379
+ $.ajax({
380
+ type: "POST",
381
+ headers: (header ? header : {
382
+ authorization: $awt
383
+ }),
384
+ url: fixURL(URL),
385
+ contentType: "application/json; charset=utf-8",
386
+ dataType: "json",
387
+ crossDomain: true,
388
+ data: JSON.stringify(DATA),
389
+ success: function (d) {
390
+ json_data_parse(d, 0);
391
+ if (callBack) callBack(d);
392
+ },
393
+ error: function (xhr, ajaxOptions, thrownError) {
394
+ console.log("API:", URL, "IN:", DATA);
395
+ console.log("Error XHR:", xhr);
396
+
397
+ if (errorCallBack) {
398
+ errorCallBack(xhr);
399
+ return
400
+ }
401
+
402
+ showMessage({
403
+ icon: 'mdi mdi-alert-circle-outline',
404
+ title: '',
405
+ message: (xhr.responseJSON ? xhr.responseJSON.Message : (xhr.responseText ? xhr.responseText : "")),
406
+ type: 'red',
407
+ });
408
+ },
409
+ complete: function (data) {
410
+ app.config.globalProperties.v_LoadingOverlay = _.without(app.config.globalProperties.v_LoadingOverlay, loadingID);
411
+ if (app.config.globalProperties.v_LoadingOverlay.length == 0) app.config.globalProperties.v_Loading = false;
412
+ }
413
+ });
414
+ }
415
+ //===========================================================================================
416
+ function capacityText(numb) {
417
+ if (numb < 1048576) return Math.round(numb / 1024 * 100 / 100) + ' Kb';
418
+ else return Math.round(numb / 1048576 * 100) / 100 + ' Mb';
419
+ }
420
+ //===========================================================================================
421
+ function generateID() {
422
+ var d = new Date();
423
+ var k = d.getTime();
424
+ var str = k.toString(16).slice(1)
425
+ var UUID = 'idxxxxxxxx'.replace(/[xy]/g, function (c) {
426
+ var r = Math.random() * 16 | 0;
427
+ v = c == 'x' ? r : (r & 3 | 8);
428
+ return v.toString(16);
429
+ });
430
+ var newString = UUID.replace(/[z]/, str)
431
+ return newString;
432
+ }
433
+ //===========================================================================================
434
+ function printPDF(obj) {
435
+ pdfMake.fonts = {
436
+ Roboto: {
437
+ normal: 'Roboto-Regular.ttf',
438
+ bold: 'Roboto-Medium.ttf',
439
+ italics: 'Roboto-Italic.ttf',
440
+ bolditalics: 'Roboto-MediumItalic.ttf'
441
+ },
442
+ TimesNewRoman: {
443
+ normal: 'times.ttf',
444
+ bold: 'timesbd.ttf',
445
+ italics: 'timesi.ttf',
446
+ bolditalics: 'timesbi.ttf'
447
+ }
448
+ }
449
+
450
+ if (obj.download) {
451
+ pdfMake.createPdf(obj.data).download('fp_pdf_' + generateID() + '.pdf');
452
+ } else if (obj.viewer) {
453
+ pdfMake.createPdf(obj.data).getDataUrl(function (outDoc) {
454
+ $(obj.viewer).attr("src", outDoc);
455
+ });
456
+ } else {
457
+ pdfMake.createPdf(obj.data).getBase64(function (outDoc) {
458
+ printJS({ printable: outDoc, type: 'pdf', base64: true });
459
+ });
460
+ }
461
+ //-------------------------------------------------------
462
+ if (_.isFunction(obj.callBack)) obj.callBack();
463
+ }
464
+ //===========================================================================================
465
+ function jsonToExcel(Obj) {
466
+ if (typeof ExcelJS == 'undefined') {
467
+ var loadScript = new Loader();
468
+ loadScript.require(["/include/excel/exceljs.min.js"], function () {
469
+ writeExcelFile(Obj);
470
+ });
471
+ } else writeExcelFile(Obj);
472
+ function writeExcelFile(inputObj) {
473
+ var props = {
474
+ data: null, // Json to download (for single sheet - backward compatibility)
475
+ filename: "dataFP.xlsx", // filename to export
476
+ worksheet: "SheetFP", // sheet name for single sheet
477
+ sheets: null, // New property for multiple sheets
478
+ onProgress: null, // optional: function({percent, processedRows, totalRows, phase, sheetName}) - phase: 'building'|'finalizing'|'done'|'error'
479
+ showProgress: true // tự hiện thanh % cố định giữa màn hình khi xuất; truyền false để tắt UI này
480
+ }
481
+ Object.assign(props, inputObj);
482
+ // Gom về một danh sách sheet chung cho cả 2 chế độ cũ (single) và mới (multi) để dùng chung logic tiến trình/chunk
483
+ var sheetList;
484
+ if (props.sheets && Array.isArray(props.sheets)) {
485
+ if (!props.sheets.length) { showMessage({ title: "Sheets data is empty" }); return; }
486
+ sheetList = props.sheets.filter(function (s) { return s.data && s.data.length; });
487
+ if (!sheetList.length) { showMessage({ title: "Sheets data is empty" }); return; }
488
+ } else {
489
+ if (!props.data || !props.data.length) { showMessage({ title: "Data Null" }); return; }
490
+ sheetList = [{ name: props.worksheet, data: props.data }];
491
+ }
492
+
493
+ var totalRows = sheetList.reduce(function (sum, s) { return sum + s.data.length; }, 0);
494
+ var processedRows = 0;
495
+ // Chunk động: mỗi đợt ghi ~2% tổng số dòng, nên số lần nhường luồng UI luôn ~50 lần dù
496
+ // data ít hay nhiều (không còn đánh đổi mượt-vs-nhanh như chunk cố định) — data nhỏ thì
497
+ // chặn dưới 50 dòng/đợt để khỏi nhường luồng vô ích cho vài chục dòng.
498
+ var CHUNK_SIZE = Math.max(50, Math.ceil(totalRows * 0.02));
499
+ var progressUI = props.showProgress ? createProgressUI() : null;
500
+
501
+ function report(phase, sheetName) {
502
+ // Giai đoạn ghi dòng ("building") chiếm tối đa 95%; ExcelJS không có hook tiến trình cho bước
503
+ // nén file (writeBuffer) nên "finalizing" chỉ báo mốc cố định 98%, không nội suy %.
504
+ var percent = totalRows ? Math.min(95, Math.floor(processedRows / totalRows * 95)) : 0;
505
+ if (phase === 'finalizing') percent = 98;
506
+ if (phase === 'done') percent = 100;
507
+ if (typeof props.onProgress === 'function') {
508
+ try { props.onProgress({ percent: percent, processedRows: processedRows, totalRows: totalRows, phase: phase, sheetName: sheetName }); }
509
+ catch (e) { console.error('jsonToExcel onProgress error', e); }
510
+ }
511
+ if (progressUI) {
512
+ progressUI.update({ percent: percent, phase: phase });
513
+ if (phase === 'done' || phase === 'error') progressUI.destroy();
514
+ }
515
+ }
516
+
517
+ var workbook = new ExcelJS.Workbook();
518
+
519
+ function buildSheet(sheetIndex) {
520
+ if (sheetIndex >= sheetList.length) { finalize(); return; }
521
+ var sheetCfg = sheetList[sheetIndex];
522
+ var worksheet = workbook.addWorksheet(sheetCfg.name || 'Sheet');
523
+ // Create header (chỉ cần đọc key của dòng đầu, tương đương logic cũ nhưng không lặp check index===0 mỗi vòng)
524
+ worksheet.columns = Object.keys(sheetCfg.data[0]).map(function (k) { return { header: k, key: k }; });
525
+
526
+ var rows = sheetCfg.data;
527
+ var i = 0;
528
+ function nextChunk() {
529
+ try {
530
+ var end = Math.min(i + CHUNK_SIZE, rows.length);
531
+ for (var r = i; r < end; r++) { worksheet.addRow(rows[r]); }
532
+ processedRows += (end - i);
533
+ i = end;
534
+ report('building', sheetCfg.name);
535
+ } catch (err) {
536
+ console.error('jsonToExcel build error', err);
537
+ report('error', sheetCfg.name);
538
+ showMessage({ title: 'Xuất Excel thất bại' });
539
+ return;
540
+ }
541
+ if (i < rows.length) {
542
+ // Nhường luồng UI giữa các đợt (thay vì ghi hết trong 1 vòng lặp đồng bộ) để tránh
543
+ // trang bị "Not Responding" khi data lớn, đồng thời cho phép % cập nhật lên màn hình.
544
+ (window.requestAnimationFrame || function (cb) { setTimeout(cb, 0); })(nextChunk);
545
+ } else {
546
+ buildSheet(sheetIndex + 1);
547
+ }
548
+ }
549
+ nextChunk();
550
+ }
551
+
552
+ function finalize() {
553
+ report('finalizing');
554
+ workbook.xlsx.writeBuffer().then(function (data) {
555
+ var blobType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
556
+ var blob = new Blob([data], { type: blobType });
557
+ var a = document.createElement('a');
558
+ document.body.appendChild(a);
559
+ a.style = 'display: none';
560
+ var url = window.URL.createObjectURL(blob);
561
+ a.href = url;
562
+ a.download = props.filename;
563
+ a.click();
564
+ window.URL.revokeObjectURL(url);
565
+ a.remove();
566
+ report('done');
567
+ }).catch(function (err) {
568
+ console.error('jsonToExcel writeBuffer error', err);
569
+ report('error');
570
+ showMessage({ title: 'Xuất Excel thất bại' });
571
+ });
572
+ }
573
+
574
+ buildSheet(0);
575
+ }
576
+
577
+ // Thanh % mặc định, tự tạo/tự dọn bằng DOM thuần (CSS thủ công, không dùng v-dialog/framework nào)
578
+ // — fix cố định giữa màn hình, không phụ thuộc Vue nên dùng chung được cho cả V2 và V3.
579
+ function createProgressUI() {
580
+ var STYLE_ID = 'fui-json-to-excel-progress-style';
581
+ // Luôn ghi đè nội dung CSS mới nhất vào thẻ <style>, kể cả khi tag đã tồn tại từ lần
582
+ // export trước trong cùng phiên trang (SPA không reload) — nếu chỉ tạo-1-lần-rồi-bỏ-qua
583
+ // như trước, CSS cũ bị kẹt lại vĩnh viễn trong DOM, sửa file JS trên server sau đó
584
+ // không có tác dụng cho tới khi người dùng F5 lại cả trang.
585
+ var style = document.getElementById(STYLE_ID);
586
+ if (!style) {
587
+ style = document.createElement('style');
588
+ style.id = STYLE_ID;
589
+ document.head.appendChild(style);
590
+ }
591
+ style.innerHTML = '.fui-xlsx-progress{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:350px;' +
592
+ 'box-sizing:border-box;z-index:99999;background:#fff;border-radius:8px;box-shadow:0 12px 40px rgba(0,0,0,.35);' +
593
+ 'padding: 30px 30px 40px 30px;font:14px/1.4 inherit;transition:opacity .3s}' +
594
+ '.fui-xlsx-progress .fui-xlsx-label{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;color:#333}' +
595
+ '.fui-xlsx-progress .fui-xlsx-label span:first-child{font-size:15px;font-weight:600}' +
596
+ '.fui-xlsx-progress .fui-xlsx-percent{font-size:22px;font-weight:700;color:#1976d2}' +
597
+ '.fui-xlsx-progress .fui-xlsx-track{height:8px;border-radius:4px;background:#e0e0e0;overflow:hidden}' +
598
+ '.fui-xlsx-progress .fui-xlsx-bar{height:100%;width:0;background:#1976d2;transition:width .2s ease-out}';
599
+ var el = document.createElement('div');
600
+ el.className = 'fui-xlsx-progress';
601
+ el.innerHTML = '<div class="fui-xlsx-label"><span>Đang xuất Excel...</span><span class="fui-xlsx-percent">0%</span></div>' +
602
+ '<div class="fui-xlsx-track"><div class="fui-xlsx-bar"></div></div>';
603
+ document.body.appendChild(el);
604
+ var percentEl = el.querySelector('.fui-xlsx-percent');
605
+ var barEl = el.querySelector('.fui-xlsx-bar');
606
+ var labelEl = el.querySelector('.fui-xlsx-label span');
607
+ var destroyed = false;
608
+ return {
609
+ update: function (info) {
610
+ if (destroyed) return;
611
+ percentEl.textContent = info.percent + '%';
612
+ barEl.style.width = info.percent + '%';
613
+ if (info.phase === 'finalizing') labelEl.textContent = 'Đang tạo file...';
614
+ if (info.phase === 'done') labelEl.textContent = 'Hoàn tất';
615
+ if (info.phase === 'error') labelEl.textContent = 'Xuất thất bại';
616
+ },
617
+ destroy: function () {
618
+ if (destroyed) return;
619
+ destroyed = true;
620
+ el.style.opacity = '0';
621
+ setTimeout(function () { if (el.parentNode) el.parentNode.removeChild(el); }, 500);
622
+ }
623
+ };
624
+ }
625
+ }
626
+ //===========================================================================================
627
+ function copyToClipboard(textToCopy) {
628
+ if (navigator.clipboard && window.isSecureContext) {
629
+ console.log("Navigator copy: ", textToCopy);
630
+ return navigator.clipboard.writeText(textToCopy);
631
+ } else {
632
+ let textArea = document.createElement("div");
633
+ textArea.innerText = textToCopy;
634
+ textArea.style.position = "fixed";
635
+ textArea.style.left = "0px";
636
+ textArea.style.top = "-999999px";
637
+ document.body.appendChild(textArea);
638
+
639
+ var range = document.createRange();
640
+ range.selectNode(textArea);
641
+ window.getSelection().removeAllRanges();
642
+ window.getSelection().addRange(range);
643
+ return new Promise((res, rej) => {
644
+ document.execCommand('copy') ? res() : rej();
645
+ console.log("Command copy: ", textToCopy);
646
+ textArea.remove();
647
+ });
648
+ }
649
+ };
650
+ //===========================================================================================
651
+ function fileNameClear(fname) {
652
+ if (fname) return fname.replace(/[\!\@\#\$\^\&\%\*\(\)\+\=\-\[\]\\\/\{\}\|\:\<\>\?\,\.\`\"\'\~\;]/gi, '');
653
+ return fname;
654
+ }
655
+ //===========================================================================================
656
+ function hashCode(s) {
657
+ var h = 0,
658
+ l = s.length,
659
+ i = 0;
660
+ if (l > 0)
661
+ while (i < l)
662
+ h = (h << 5) - h + s.charCodeAt(i++) | 0;
663
+ return h;
664
+ };
665
+ //===========================================================================================
666
+ function getCookie(cname) {
667
+ var name = cname + "=";
668
+ var ca = document.cookie.split(';');
669
+ for (var i = 0; i < ca.length; i++) {
670
+ var c = ca[i];
671
+ while (c.charAt(0) == ' ') {
672
+ c = c.substring(1);
673
+ }
674
+ if (c.indexOf(name) == 0) {
675
+ return c.substring(name.length, c.length);
676
+ }
677
+ }
678
+ return "";
679
+ }
680
+
681
+ function setCookie(name, value, days, domain) {
682
+ var expires = "";
683
+ var domainString = "";
684
+ if (days) {
685
+ var date = new Date();
686
+ date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
687
+ expires = "; expires=" + date.toUTCString();
688
+ }
689
+ if (domain) {
690
+ domainString = "; domain=" + domain
691
+ }
692
+ document.cookie = name + "=" + (value || "") + expires + domainString + ";path=/";
693
+ }
694
+ //===================================================================================
695
+ function logout(cookiesName, domain, url) {
696
+ if (!cookiesName) cookiesName = 'awt';
697
+ if (typeof domain == "undefined" && vueData.v_Set.authDomain) domain = vueData.v_Set.authDomain;
698
+
699
+ setCookie(cookiesName, '', 0, domain);
700
+
701
+ if (!url) location.assign(location.href);
702
+ else location.assign(url);
703
+ }
704
+
705
+ //===========================================================================================
706
+ // WEBSOCKET
707
+ //===========================================================================================
708
+ function webSocketJoinGroup(groupObj, timeout, callBackFunc) {
709
+ groupObj = _.cloneDeep(groupObj)
710
+ _.forEach(groupObj, function (v, k) {
711
+ if (!vueData.webSocket.hasOwnProperty(k)) {
712
+ vueData.webSocket[k] = v;
713
+ }
714
+ });
715
+
716
+ setTimeout(function () {
717
+ try {
718
+ $.connection.hub.start().done(function () {
719
+ _.forEach(groupObj, function (v, k) {
720
+ $.connection.chatHub.server.joinGroup(k);
721
+ });
722
+ if (_.isFunction(callBackFunc)) callBackFunc();
723
+ }).fail(function (e) {
724
+ });
725
+ }
726
+ catch (err) {
727
+
728
+ }
729
+ }, (timeout ? timeout : 0));
730
+ }
731
+
732
+ function webSocketConnection(wsURL, WS, wsState) {
733
+ $.connection.hub.url = wsURL;
734
+
735
+ //=====================================================================
736
+ $.connection.hub.stateChanged(function (change) {
737
+ wsState.code = change.newState;
738
+ if (change.newState === $.signalR.connectionState.reconnecting) {
739
+ console.log("Websocket Reconnecting")
740
+ wsState.text = "Reconnecting";
741
+ }
742
+ else if (change.newState === $.signalR.connectionState.connected) {
743
+ console.log("Websocket Connected")
744
+ wsState.text = "Connected";
745
+ }
746
+ else if (change.newState === $.signalR.connectionState.disconnected) {
747
+ console.log("Websocket Disconnected")
748
+ wsState.text = "Disconnected";
749
+
750
+ webSocketJoinGroup(WS, 5000);
751
+ }
752
+ });
753
+
754
+ $.connection.chatHub.client.onError = function (Mess) {
755
+ console.log('Server error: ', Mess);
756
+ };
757
+
758
+ $.connection.chatHub.client.onJoinGroup = function (mess) {
759
+ console.log("Group", mess)
760
+ };
761
+
762
+ $.connection.chatHub.client.messageReceived = function (group, message) {
763
+ console.log("Message Received: ", group, message)
764
+ if (_.isArray(WS[group])) WS[group].push(message);
765
+ else WS[group] = message;
766
+ };
767
+
768
+ $.connection.chatHub.client.messageSendLog = function (group, message) {
769
+ console.log("Message Sent: ", group, message)
770
+ };
771
+ }
772
+
773
+ function webSocket_Send(obj) {
774
+ if (_.isPlainObject(obj.data)) $.connection.chatHub.server.messageSendObject(obj.group, obj.data);
775
+ else if (_.isArray(obj.data)) $.connection.chatHub.server.messageSendArray(obj.group, obj.data);
776
+ else $.connection.chatHub.server.messageSend(obj.group, obj.data);
777
+ }
778
+ //===========================================================================================
779
+ //===========================================================================================
780
+ //===========================================================================================
781
+ //===========================================================================================