@magic-xpa/engine 4.1200.0-ec.131.0 → 4.1200.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.
- package/fesm2022/magic-xpa-engine.mjs +133 -11
- package/fesm2022/magic-xpa-engine.mjs.map +1 -1
- package/package.json +4 -4
- package/src/ConstInterface.d.ts +1 -0
- package/src/commands/ClientToServer/CommandFactory.d.ts +2 -2
- package/src/commands/ClientToServer/ControlItemsRefreshCommand.d.ts +1 -0
- package/src/commands/ClientToServer/FetchDataControlValuesEventCommand.d.ts +1 -0
- package/src/event/EventHandler.d.ts +5 -0
- package/src/exp/ExpressionEvaluator.d.ts +5 -0
- package/src/remote/RemoteControlItemsRefreshCommand.d.ts +1 -0
- package/src/rt/Operation.d.ts +3 -1
@@ -3,6 +3,7 @@ import { XMLConstants, StorageAttribute, ViewRefreshMode, InternalInterface, Log
|
|
3
3
|
import { RecordUtils, GuiFieldBase, ExpVal, BlobType, FieldDef, GuiTaskBase, MgControlBase, PropInterface, GuiDataCollection, CommandType, Commands, HtmlProperties, ControlTable, Modifiers, KeyboardItem, TaskDefinitionIdTableSaxHandler, DisplayConvertor, VectorType, PIC, MgTimer, GuiConstants, RuntimeContextBase, UsernamePasswordCredentials, Styles, Manager, NUM_TYPE, GuiExpressionEvaluator, ExpressionInterface, DataModificationTypes, GuiDataViewBase, ObjectReferencesCollection, EMPTY_DCREF, ObjectReferenceBase, PropTable, FieldsTable as FieldsTable$1, DcValuesBuilderBase, MgFormBase, GuiEnvironment, TaskDefinitionId, Events, Helps, FocusManager, EventsProcessor, UIBridge } from '@magic-xpa/gui';
|
4
4
|
import { HttpHeaders, HttpErrorResponse } from '@angular/common/http';
|
5
5
|
import { timer, Subject } from 'rxjs';
|
6
|
+
import * as CryptoJS from 'crypto-js';
|
6
7
|
|
7
8
|
///
|
8
9
|
/// This class is used to hold references to global objects, using their interfaces/base classes. This allows other objects to access those global objects
|
@@ -315,6 +316,7 @@ class ConstInterface {
|
|
315
316
|
static MG_ATTR_HANDLER_ONFORM = "HandlerOnForm";
|
316
317
|
static MG_ATTR_DROP_USERFORMATS = "dropuserformats";
|
317
318
|
static MG_ATTR_CONTROL_NAME = "ControlName";
|
319
|
+
static MG_ATTR_SEARCH_STR = "searchStr";
|
318
320
|
static MG_TAG_HIDDEN_CONTOLS = "HiddenControls";
|
319
321
|
static MG_ATTR_ISNS = "Isns";
|
320
322
|
static MG_ATTR_SPECIAL_CANCEL_ON_CREATE = "SpecialCancelOnCreate";
|
@@ -9735,6 +9737,17 @@ class ExpressionDict {
|
|
9735
9737
|
new ExpDesc('B', 0, 1, 1, 'A', false), /* 703- Delete_Cookie */
|
9736
9738
|
null,
|
9737
9739
|
new ExpDesc('U', 0, 0, 0, '', false), /* 705- RouteGet */
|
9740
|
+
null,
|
9741
|
+
null,
|
9742
|
+
null,
|
9743
|
+
null,
|
9744
|
+
null,
|
9745
|
+
null,
|
9746
|
+
null,
|
9747
|
+
null,
|
9748
|
+
null,
|
9749
|
+
null,
|
9750
|
+
new ExpDesc('NO', 0, 2, 2, 'A', false), /* 716- Hash */
|
9738
9751
|
];
|
9739
9752
|
}
|
9740
9753
|
|
@@ -10101,6 +10114,7 @@ class RefreshEventCommand extends EventCommand {
|
|
10101
10114
|
/// </summary>
|
10102
10115
|
class FetchDataControlValuesEventCommand extends EventCommand {
|
10103
10116
|
ControlName = null;
|
10117
|
+
FilterData = null;
|
10104
10118
|
constructor() {
|
10105
10119
|
super(InternalInterface.MG_ACT_FETCH_DATA_CONTROL_VALUES);
|
10106
10120
|
}
|
@@ -10109,6 +10123,8 @@ class FetchDataControlValuesEventCommand extends EventCommand {
|
|
10109
10123
|
helper.SerializeTaskTag(this.TaskTag);
|
10110
10124
|
helper.SerializeMagicEvent(this.MagicEvent);
|
10111
10125
|
helper.SerializeAttribute(ConstInterface.MG_ATTR_CONTROL_NAME, this.ControlName);
|
10126
|
+
if (this.FilterData != null && this.FilterData != "")
|
10127
|
+
helper.SerializeAttribute(ConstInterface.MG_ATTR_SEARCH_STR, this.FilterData);
|
10112
10128
|
return helper.GetString();
|
10113
10129
|
}
|
10114
10130
|
getCommandInfo() {
|
@@ -10557,6 +10573,7 @@ class SelectProgramCommand extends ExecOperCommand {
|
|
10557
10573
|
/// </summary>
|
10558
10574
|
class ControlItemsRefreshCommand extends DataviewCommand {
|
10559
10575
|
Control = null;
|
10576
|
+
FilterData = null;
|
10560
10577
|
constructor() {
|
10561
10578
|
super();
|
10562
10579
|
}
|
@@ -10627,11 +10644,12 @@ class CommandFactory {
|
|
10627
10644
|
/// <param name="taskId"></param>
|
10628
10645
|
/// <param name="control"></param>
|
10629
10646
|
/// <returns></returns>
|
10630
|
-
static CreateControlItemsRefreshCommand(taskId, control) {
|
10647
|
+
static CreateControlItemsRefreshCommand(taskId, control, filterData) {
|
10631
10648
|
let command = new ControlItemsRefreshCommand();
|
10632
10649
|
command.CommandType = DataViewCommandType.ControlItemsRefresh;
|
10633
10650
|
command.TaskTag = taskId;
|
10634
10651
|
command.Control = control;
|
10652
|
+
command.FilterData = filterData;
|
10635
10653
|
return command;
|
10636
10654
|
}
|
10637
10655
|
/// <summary>
|
@@ -10736,10 +10754,11 @@ class CommandFactory {
|
|
10736
10754
|
/// <param name="controlName"></param>
|
10737
10755
|
/// <param name="generationParam"></param>
|
10738
10756
|
/// <returns></returns>
|
10739
|
-
static CreatecFetchDataControlValuesCommand(taskTag, controlName) {
|
10757
|
+
static CreatecFetchDataControlValuesCommand(taskTag, controlName, filterData) {
|
10740
10758
|
let fetchDataControlValuesEventCommand = new FetchDataControlValuesEventCommand();
|
10741
10759
|
fetchDataControlValuesEventCommand.TaskTag = taskTag;
|
10742
10760
|
fetchDataControlValuesEventCommand.ControlName = controlName;
|
10761
|
+
fetchDataControlValuesEventCommand.FilterData = filterData;
|
10743
10762
|
return fetchDataControlValuesEventCommand;
|
10744
10763
|
}
|
10745
10764
|
static CreateSubformRefreshCommand(taskTag, subformTaskTag, explicitSubformRefresh) {
|
@@ -12215,6 +12234,7 @@ class Operation {
|
|
12215
12234
|
_undo = true;
|
12216
12235
|
_isRoute = false;
|
12217
12236
|
_routerPath = null;
|
12237
|
+
_subformExp = null;
|
12218
12238
|
_originalRouterOutletName = null;
|
12219
12239
|
_routeParams = null;
|
12220
12240
|
constructor() {
|
@@ -12418,6 +12438,10 @@ class Operation {
|
|
12418
12438
|
case XMLConstants.MG_ATTR_ROUTER_PATH:
|
12419
12439
|
this._routerPath = XmlParser.unescape(valueStr);
|
12420
12440
|
break;
|
12441
|
+
case XMLConstants.MG_ATTR_SUBFORM_EXP:
|
12442
|
+
expId = XmlParser.getInt(valueStr);
|
12443
|
+
this._subformExp = taskRef.getExpById(expId);
|
12444
|
+
break;
|
12421
12445
|
default:
|
12422
12446
|
Logger.Instance.WriteExceptionToLogWithMsg("There is no such tag in Operation class. Insert case to Operation.initElements for " + attribute);
|
12423
12447
|
break;
|
@@ -12480,7 +12504,7 @@ class Operation {
|
|
12480
12504
|
/// </param>
|
12481
12505
|
/// <param name = "returnedFromServer">true if the server returned the execution to this operation</param>
|
12482
12506
|
/// <returns> boolean for verify and block operations</returns>
|
12483
|
-
async execute(returnedFromServer) {
|
12507
|
+
async execute(returnedFromServer, desiredRouteName = null) {
|
12484
12508
|
let lastRtEvent = AccessHelper.eventsManager.getLastRtEvent();
|
12485
12509
|
let mprgCreator = null;
|
12486
12510
|
let flowMonitor = FlowMonitorQueue.Instance;
|
@@ -12525,6 +12549,17 @@ class Operation {
|
|
12525
12549
|
await this.operServer(mprgCreator);
|
12526
12550
|
break;
|
12527
12551
|
case ConstInterface.MG_OPER_CALL:
|
12552
|
+
if (this._subformExp != null) {
|
12553
|
+
const subformName = await this._subformExp.evaluateWithResultTypeAndLength(StorageAttribute.ALPHA, 30);
|
12554
|
+
if (!subformName || subformName.length > 30) {
|
12555
|
+
const messageKey = !subformName ? MsgInterface.STR_ERR_BLANK_SUBFORM_NAME : MsgInterface.STR_ERR_SUBFORM_NAME_EXCEEDS_LIMIT;
|
12556
|
+
let message = LanguageData.Instance.getConstMessage(messageKey);
|
12557
|
+
message = LanguageData.Instance.translate(message);
|
12558
|
+
this._task.WriteToMessagePane(message);
|
12559
|
+
return false;
|
12560
|
+
}
|
12561
|
+
this._subformCtrlName = subformName;
|
12562
|
+
}
|
12528
12563
|
if (this._publicName != null) {
|
12529
12564
|
this.operCallParallel();
|
12530
12565
|
}
|
@@ -12554,8 +12589,16 @@ class Operation {
|
|
12554
12589
|
let canRoute = false;
|
12555
12590
|
let rtEvnt = AccessHelper.eventsManager.getLastRtEvent();
|
12556
12591
|
if (rtEvnt !== null) {
|
12557
|
-
|
12558
|
-
if (
|
12592
|
+
// If we are here for default route path, set the routeParams as null because those are relevant only for the original route.
|
12593
|
+
if (!this._evtHandler.isExecutingDefaultRoute()) {
|
12594
|
+
desiredRouteName = (await rtEvnt.getArgList().getArg(0).getValue(StorageAttribute.ALPHA, 0)).trim();
|
12595
|
+
this._routeParams = rtEvnt.getRouteParamList();
|
12596
|
+
}
|
12597
|
+
else {
|
12598
|
+
desiredRouteName = this._evtHandler.getDefaultRouteName();
|
12599
|
+
this._routeParams = null;
|
12600
|
+
}
|
12601
|
+
if (desiredRouteName === this._routerPath &&
|
12559
12602
|
((rtEvnt.getArgList().getArg(1).skipArg() && destSubForm === this._task.getForm().DefaultRouterOutlet) ||
|
12560
12603
|
(!rtEvnt.getArgList().getArg(1).skipArg() && (await rtEvnt.getArgList().getArg(1).getValue(StorageAttribute.ALPHA, 0)).trim() === this._originalRouterOutletName)))
|
12561
12604
|
canRoute = true;
|
@@ -13063,7 +13106,18 @@ class Operation {
|
|
13063
13106
|
/// </summary>
|
13064
13107
|
/// <returns></returns>
|
13065
13108
|
async canExecute() {
|
13066
|
-
return await this.getCondVal();
|
13109
|
+
return (this.isOperationAllowedWhileExecutingDefaultRoute() && await this.getCondVal());
|
13110
|
+
}
|
13111
|
+
isOperationAllowedWhileExecutingDefaultRoute() {
|
13112
|
+
let isAllowed = true;
|
13113
|
+
if (this._evtHandler.isExecutingDefaultRoute()) {
|
13114
|
+
if (this._type == ConstInterface.MG_OPER_BLOCK || this._type == ConstInterface.MG_OPER_ELSE ||
|
13115
|
+
(this._type == ConstInterface.MG_OPER_CALL && this._isRoute))
|
13116
|
+
return true;
|
13117
|
+
else
|
13118
|
+
return false;
|
13119
|
+
}
|
13120
|
+
return isAllowed;
|
13067
13121
|
}
|
13068
13122
|
/// <summary>
|
13069
13123
|
/// </summary>
|
@@ -13775,6 +13829,9 @@ class ExpressionEvaluator extends GuiExpressionEvaluator {
|
|
13775
13829
|
static PARENT_LEN = 2; // 2 bytes
|
13776
13830
|
static SHORT_OBJECT_LEN = 2; // 2 bytes
|
13777
13831
|
static LONG_OBJECT_LEN = 4; // 4 bytes
|
13832
|
+
static MD5_ALGO_NUM = 1;
|
13833
|
+
static SHA1_ALGO_NUM = 2;
|
13834
|
+
static SHA2_ALGO_NUM = 3;
|
13778
13835
|
static _recursiveExpCalcCount = 0;
|
13779
13836
|
_charsToTrim = [' ', '\0'];
|
13780
13837
|
_expressionLocalJpn = null;
|
@@ -15398,6 +15455,12 @@ class ExpressionEvaluator extends GuiExpressionEvaluator {
|
|
15398
15455
|
case ExpressionInterface.EXP_OP_ROUTEGET:
|
15399
15456
|
this.eval_op_route_get(resVal);
|
15400
15457
|
break;
|
15458
|
+
case ExpressionInterface.EXP_OP_HASH:
|
15459
|
+
val2 = valStack.pop();
|
15460
|
+
val1 = valStack.pop();
|
15461
|
+
this.eval_op_Hash(val1, val2, resVal);
|
15462
|
+
expStrTracker.resetNullResult();
|
15463
|
+
break;
|
15401
15464
|
default:
|
15402
15465
|
return;
|
15403
15466
|
}
|
@@ -16849,7 +16912,7 @@ class ExpressionEvaluator extends GuiExpressionEvaluator {
|
|
16849
16912
|
let control = tsk.getForm().GetCtrl(val1.StrVal);
|
16850
16913
|
//This function is applicable only for Combo box, List box etc. i.e. for choice controls. Also it will refresh items only if Source table is attached to the data control.
|
16851
16914
|
if (control != null && control.isChoiceControl() && control.isDataCtrl()) {
|
16852
|
-
let command = CommandFactory.CreateControlItemsRefreshCommand(tsk.getTaskTag(), control);
|
16915
|
+
let command = CommandFactory.CreateControlItemsRefreshCommand(tsk.getTaskTag(), control, "");
|
16853
16916
|
await tsk.DataviewManager.CurrentDataviewManager.Execute(command);
|
16854
16917
|
success = true;
|
16855
16918
|
}
|
@@ -18364,7 +18427,7 @@ class ExpressionEvaluator extends GuiExpressionEvaluator {
|
|
18364
18427
|
if (!isNullOrUndefined(args)) {
|
18365
18428
|
// TODO: This is a patch fix put for MXPA-30360. Problem is that the lazy loading components are not loaded in an async way.
|
18366
18429
|
// Hence for the first record cycle the CallJS operation was not working. So, async loading of lazy loaded comps should be
|
18367
|
-
// handled.
|
18430
|
+
// handled.
|
18368
18431
|
resVal.StrVal = Commands.addCallJS(form, form.UniqueName, methodName, args);
|
18369
18432
|
resVal.Attr = StorageAttribute.ALPHA;
|
18370
18433
|
}
|
@@ -18461,6 +18524,35 @@ class ExpressionEvaluator extends GuiExpressionEvaluator {
|
|
18461
18524
|
}
|
18462
18525
|
return attr;
|
18463
18526
|
}
|
18527
|
+
eval_op_Hash(val1, val2, resVal) {
|
18528
|
+
resVal.Attr = StorageAttribute.ALPHA;
|
18529
|
+
resVal.StrVal = '';
|
18530
|
+
if (val1.IsNull || val2.IsNull)
|
18531
|
+
return;
|
18532
|
+
let str = '';
|
18533
|
+
const byteArray = BlobType.getBytes(val2.StrVal);
|
18534
|
+
const wordArray = this.toWordArray(byteArray);
|
18535
|
+
if (val1.MgNumVal.NUM_2_LONG() === ExpressionEvaluator.MD5_ALGO_NUM)
|
18536
|
+
str = CryptoJS.MD5(wordArray).toString();
|
18537
|
+
else if (val1.MgNumVal.NUM_2_LONG() === ExpressionEvaluator.SHA1_ALGO_NUM)
|
18538
|
+
str = CryptoJS.SHA1(wordArray).toString();
|
18539
|
+
else if (val1.MgNumVal.NUM_2_LONG() === ExpressionEvaluator.SHA2_ALGO_NUM)
|
18540
|
+
str = CryptoJS.SHA256(wordArray).toString();
|
18541
|
+
else
|
18542
|
+
Logger.Instance.WriteErrorToLog(LanguageData.Instance.getConstMessage(MsgInterface.STR_ERR_INVALID_HASH_ALGO_NUMBER));
|
18543
|
+
resVal.StrVal = str;
|
18544
|
+
}
|
18545
|
+
// Convert Uint8Array to WordArray
|
18546
|
+
toWordArray(u8) {
|
18547
|
+
const words = [];
|
18548
|
+
for (let i = 0; i < u8.length; i += 4) {
|
18549
|
+
words.push(((u8[i] || 0) << 24) |
|
18550
|
+
((u8[i + 1] || 0) << 16) |
|
18551
|
+
((u8[i + 2] || 0) << 8) |
|
18552
|
+
(u8[i + 3] || 0));
|
18553
|
+
}
|
18554
|
+
return CryptoJS.lib.WordArray.create(words, u8.length);
|
18555
|
+
}
|
18464
18556
|
}
|
18465
18557
|
/// <summary>
|
18466
18558
|
/// This exception used when at least one of the operands is null
|
@@ -25147,13 +25239,15 @@ class ResultValue {
|
|
25147
25239
|
|
25148
25240
|
class RemoteControlItemsRefreshCommand extends RemoteDataViewCommandBase {
|
25149
25241
|
control = null;
|
25242
|
+
filterData = null;
|
25150
25243
|
constructor(command) {
|
25151
25244
|
super(command);
|
25152
25245
|
this.control = command.Control;
|
25246
|
+
this.filterData = command.FilterData;
|
25153
25247
|
}
|
25154
25248
|
async Execute() {
|
25155
25249
|
let res = new ResultValue();
|
25156
|
-
let cmd = CommandFactory.CreatecFetchDataControlValuesCommand(this.Task.getTaskTag(), this.control.getName());
|
25250
|
+
let cmd = CommandFactory.CreatecFetchDataControlValuesCommand(this.Task.getTaskTag(), this.control.getName(), this.filterData);
|
25157
25251
|
this.Task.getMGData().CmdsToServer.Add(cmd);
|
25158
25252
|
// Fetch data control values from server.
|
25159
25253
|
await RemoteCommandsProcessor.GetInstance().Execute_1(CommandsProcessorBase_SendingInstruction.TASKS_AND_COMMANDS, CommandsProcessorBase_SessionStage.NORMAL, res);
|
@@ -28037,6 +28131,8 @@ class EventHandler {
|
|
28037
28131
|
_scope = null; // Task|Subtask|Global
|
28038
28132
|
_task = null;
|
28039
28133
|
_taskMgdID = -1;
|
28134
|
+
_defRouteName = null;
|
28135
|
+
_isExecutingDefaultRoute = false;
|
28040
28136
|
/// <summary>
|
28041
28137
|
/// CTOR
|
28042
28138
|
/// </summary>
|
@@ -28165,6 +28261,9 @@ class EventHandler {
|
|
28165
28261
|
case ConstInterface.MG_ATTR_HANDLER_ONFORM:
|
28166
28262
|
this._isHandlerOnForm = XmlParser.getBoolean(valueStr);
|
28167
28263
|
break;
|
28264
|
+
case XMLConstants.MG_ATTR_DEF_ROUTER_NAME:
|
28265
|
+
this._defRouteName = XmlParser.unescape(valueStr);
|
28266
|
+
break;
|
28168
28267
|
default:
|
28169
28268
|
Logger.Instance.WriteExceptionToLogWithMsg("There is no such tag in EventHandler class. Insert case to EventHandler.initElements for " + attribute);
|
28170
28269
|
break;
|
@@ -28393,8 +28492,15 @@ class EventHandler {
|
|
28393
28492
|
await this.resetLocalVariables(args);
|
28394
28493
|
initialLoopStackSize = this._task.getLoopStackSize();
|
28395
28494
|
let retVals = null;
|
28396
|
-
if (this._operationTab.getSize() > 0)
|
28495
|
+
if (this._operationTab.getSize() > 0) {
|
28397
28496
|
retVals = await this.executeOperations(0, this._operationTab.getSize() - 1, taskEnd, mgdID, depth, isChangedCurrWndRef, false, false, -1);
|
28497
|
+
if (retVals == null && this.isRouteHandler() && this.getDefaultRouteName() != null) {
|
28498
|
+
this._isExecutingDefaultRoute = true;
|
28499
|
+
// call again with an additional param Default Route Name
|
28500
|
+
retVals = await this.executeOperations(0, this._operationTab.getSize() - 1, taskEnd, mgdID, depth, isChangedCurrWndRef, false, false, -1);
|
28501
|
+
this._isExecutingDefaultRoute = false;
|
28502
|
+
}
|
28503
|
+
}
|
28398
28504
|
isChangedCurrWnd = isChangedCurrWndRef.value;
|
28399
28505
|
if (retVals !== null)
|
28400
28506
|
return retVals;
|
@@ -28474,6 +28580,9 @@ class EventHandler {
|
|
28474
28580
|
}
|
28475
28581
|
return new RetVals(retVal, true);
|
28476
28582
|
}
|
28583
|
+
isExecutingDefaultRoute() {
|
28584
|
+
return this._isExecutingDefaultRoute;
|
28585
|
+
}
|
28477
28586
|
/// <summary>
|
28478
28587
|
/// execute the operations starting from fromIdx and ending at endIdx.
|
28479
28588
|
/// </summary>
|
@@ -28813,6 +28922,12 @@ class EventHandler {
|
|
28813
28922
|
getEvent() {
|
28814
28923
|
return this._evt;
|
28815
28924
|
}
|
28925
|
+
isRouteHandler() {
|
28926
|
+
return (this._evt.getType() == ConstInterface.EVENT_TYPE_INTERNAL && this._evt.getInternalCode() === InternalInterface.MG_ACT_WEBCLIENT_ROUTE);
|
28927
|
+
}
|
28928
|
+
getDefaultRouteName() {
|
28929
|
+
return this._defRouteName;
|
28930
|
+
}
|
28816
28931
|
/// <summary>
|
28817
28932
|
/// get the Id of the event handler
|
28818
28933
|
/// </summary>
|
@@ -37333,6 +37448,13 @@ class EventsManager {
|
|
37333
37448
|
case InternalInterface.MG_ACT_SET_EXTERNAL_VALUE:
|
37334
37449
|
let refreshDisplay = await evt.getArgList().getArgValue(1, StorageAttribute.BOOLEAN, 0) === '1' ? true : false;
|
37335
37450
|
await ctrl.validateAndSetValueIfAllowed(evt.getValue(), refreshDisplay);
|
37451
|
+
//We will be here if we type in character(s)
|
37452
|
+
//And if the control has Autocomplete Mode and On Demand property set to true, we need to display the autocomplete list
|
37453
|
+
//based on whatever value user has typed. So, excute ControlItemsRefresh command to fetch the data control's values.
|
37454
|
+
if (ctrl.isOnDemandSelectionList()) {
|
37455
|
+
let command = CommandFactory.CreateControlItemsRefreshCommand(task.getTaskTag(), ctrl, evt.getValue());
|
37456
|
+
await task.DataviewManager.CurrentDataviewManager.Execute(command);
|
37457
|
+
}
|
37336
37458
|
break;
|
37337
37459
|
}
|
37338
37460
|
}
|
@@ -39507,7 +39629,7 @@ class CommandsTable {
|
|
39507
39629
|
}
|
39508
39630
|
}
|
39509
39631
|
|
39510
|
-
let CurrentClientVersion = '4.1200.0
|
39632
|
+
let CurrentClientVersion = '4.1200.0';
|
39511
39633
|
|
39512
39634
|
// @dynamic
|
39513
39635
|
class ClientManager {
|