tnx-shared 5.1.26 → 5.1.30

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 (120) hide show
  1. package/bundles/tnx-shared.umd.js +1999 -249
  2. package/bundles/tnx-shared.umd.js.map +1 -1
  3. package/bundles/tnx-shared.umd.min.js +1 -1
  4. package/bundles/tnx-shared.umd.min.js.map +1 -1
  5. package/classes/base/data-list-base.d.ts +2 -0
  6. package/classes/base/data-list-base.d.ts.map +1 -1
  7. package/classes/form-schema.d.ts +3 -0
  8. package/classes/form-schema.d.ts.map +1 -1
  9. package/components/chat/chat-box/chat-box.component.d.ts +102 -0
  10. package/components/chat/chat-box/chat-box.component.d.ts.map +1 -0
  11. package/components/chat/chat-box/chat-box.component.ngfactory.d.ts.map +1 -0
  12. package/components/chat/chat-box/chat-box.component.scss.shim.ngstyle.d.ts.map +1 -0
  13. package/components/chat/chat-send-message-box/chat-send-message-box.component.d.ts +37 -0
  14. package/components/chat/chat-send-message-box/chat-send-message-box.component.d.ts.map +1 -0
  15. package/components/chat/chat-send-message-box/chat-send-message-box.component.ngfactory.d.ts.map +1 -0
  16. package/components/chat/chat-send-message-box/chat-send-message-box.component.scss.shim.ngstyle.d.ts.map +1 -0
  17. package/components/chat/common-style.scss.shim.ngstyle.d.ts.map +1 -0
  18. package/components/chat/models/enums.d.ts +11 -0
  19. package/components/chat/models/enums.d.ts.map +1 -0
  20. package/components/chat/models/models.d.ts +10 -0
  21. package/components/chat/models/models.d.ts.map +1 -0
  22. package/components/chat/services/chat.service.d.ts +34 -0
  23. package/components/chat/services/chat.service.d.ts.map +1 -0
  24. package/components/chat/services/chat.service.ngfactory.d.ts.map +1 -0
  25. package/components/chat/services/content.service.d.ts +20 -0
  26. package/components/chat/services/content.service.d.ts.map +1 -0
  27. package/components/chat/services/content.service.ngfactory.d.ts.map +1 -0
  28. package/components/chat/services/message-board.service.d.ts +15 -0
  29. package/components/chat/services/message-board.service.d.ts.map +1 -0
  30. package/components/chat/services/message-board.service.ngfactory.d.ts.map +1 -0
  31. package/components/chat/services/status.service.d.ts +14 -0
  32. package/components/chat/services/status.service.d.ts.map +1 -0
  33. package/components/chat/services/status.service.ngfactory.d.ts.map +1 -0
  34. package/components/crud/crud-list/crud-list.component.d.ts +6 -0
  35. package/components/crud/crud-list/crud-list.component.d.ts.map +1 -1
  36. package/components/file-explorer/file-manager/file-manager.component.d.ts +6 -0
  37. package/components/file-explorer/file-manager/file-manager.component.d.ts.map +1 -1
  38. package/components/file-explorer/models/service-request-model.d.ts +1 -0
  39. package/components/file-explorer/models/service-request-model.d.ts.map +1 -1
  40. package/components/statemachines/models/enums.d.ts +4 -0
  41. package/components/statemachines/models/enums.d.ts.map +1 -1
  42. package/components/statemachines/statemachines-designer/statemachines-designer.component.d.ts +1 -1
  43. package/components/statemachines/statemachines-designer/statemachines-designer.component.d.ts.map +1 -1
  44. package/components/tn-custom-scrollbar/tn-custom-scrollbar.component.d.ts +1 -0
  45. package/components/tn-custom-scrollbar/tn-custom-scrollbar.component.d.ts.map +1 -1
  46. package/components/tn-dialog/tn-dialog.component.d.ts +1 -0
  47. package/components/tn-dialog/tn-dialog.component.d.ts.map +1 -1
  48. package/components/user-picker/user-picker-dialog/user-picker-dialog.component.d.ts +23 -0
  49. package/components/user-picker/user-picker-dialog/user-picker-dialog.component.d.ts.map +1 -0
  50. package/components/user-picker/user-picker-dialog/user-picker-dialog.component.ngfactory.d.ts.map +1 -0
  51. package/components/user-picker/user-picker-dialog/user-picker-dialog.component.scss.shim.ngstyle.d.ts.map +1 -0
  52. package/components/workflow/permission-sharing/permission-sharing.component.d.ts +21 -0
  53. package/components/workflow/permission-sharing/permission-sharing.component.d.ts.map +1 -0
  54. package/components/workflow/permission-sharing/permission-sharing.component.ngfactory.d.ts.map +1 -0
  55. package/components/workflow/permission-sharing/permission-sharing.component.scss.shim.ngstyle.d.ts.map +1 -0
  56. package/components/workflow/services/workflow-permission.service.d.ts +10 -0
  57. package/components/workflow/services/workflow-permission.service.d.ts.map +1 -0
  58. package/components/workflow/services/workflow-permission.service.ngfactory.d.ts.map +1 -0
  59. package/components/workflow/workflow-history-new/workflow-history-new.component.d.ts.map +1 -1
  60. package/congviec/congviec/congviec-dinhkem/congviec-dinhkem.component.d.ts +6 -2
  61. package/congviec/congviec/congviec-dinhkem/congviec-dinhkem.component.d.ts.map +1 -1
  62. package/congviec/congviec/congviec-form/congviec-form.component.d.ts +9 -1
  63. package/congviec/congviec/congviec-form/congviec-form.component.d.ts.map +1 -1
  64. package/esm2015/classes/base/data-form-base.js +3 -3
  65. package/esm2015/classes/base/data-list-base.js +41 -6
  66. package/esm2015/classes/form-schema.js +1 -1
  67. package/esm2015/components/chat/chat-box/chat-box.component.js +626 -0
  68. package/esm2015/components/chat/chat-send-message-box/chat-send-message-box.component.js +245 -0
  69. package/esm2015/components/chat/models/enums.js +13 -0
  70. package/esm2015/components/chat/models/models.js +12 -0
  71. package/esm2015/components/chat/services/chat.service.js +113 -0
  72. package/esm2015/components/chat/services/content.service.js +57 -0
  73. package/esm2015/components/chat/services/message-board.service.js +40 -0
  74. package/esm2015/components/chat/services/status.service.js +36 -0
  75. package/esm2015/components/crud/crud-list/crud-list.component.js +55 -4
  76. package/esm2015/components/file-explorer/file-manager/file-manager.component.js +69 -16
  77. package/esm2015/components/file-explorer/file-viewer/file-viewer.component.js +2 -2
  78. package/esm2015/components/file-explorer/models/service-request-model.js +5 -2
  79. package/esm2015/components/statemachines/models/enums.js +6 -1
  80. package/esm2015/components/tn-custom-scrollbar/tn-custom-scrollbar.component.js +26 -11
  81. package/esm2015/components/tn-dialog/tn-dialog.component.js +4 -2
  82. package/esm2015/components/user-picker/user-picker-dialog/user-picker-dialog.component.js +52 -0
  83. package/esm2015/components/workflow/permission-sharing/permission-sharing.component.js +123 -0
  84. package/esm2015/components/workflow/services/workflow-permission.service.js +27 -0
  85. package/esm2015/components/workflow/workflow-history-new/workflow-history-new.component.js +4 -1
  86. package/esm2015/congviec/cauhinh-workflow/cauhinh-workflow-detail/cauhinh-workflow-detail.component.js +2 -2
  87. package/esm2015/congviec/congviec/congviec-dinhkem/congviec-dinhkem.component.js +38 -14
  88. package/esm2015/congviec/congviec/congviec-form/congviec-form.component.js +25 -4
  89. package/esm2015/congviec/congviec/congviec.component.js +3 -3
  90. package/esm2015/models/basic-user-info.js +6 -1
  91. package/esm2015/public-api.js +4 -1
  92. package/esm2015/services/base.service.js +33 -9
  93. package/esm2015/services/common.service.js +3 -18
  94. package/esm2015/services/crud.service.js +56 -41
  95. package/esm2015/services/notifier.service.js +2 -2
  96. package/esm2015/services/user.service.js +37 -23
  97. package/esm2015/tnx-shared.js +49 -43
  98. package/esm2015/tnx-shared.module.js +10 -2
  99. package/fesm2015/tnx-shared.js +1705 -202
  100. package/fesm2015/tnx-shared.js.map +1 -1
  101. package/models/basic-user-info.d.ts +2 -3
  102. package/models/basic-user-info.d.ts.map +1 -1
  103. package/package.json +2 -2
  104. package/public-api.d.ts +3 -0
  105. package/public-api.d.ts.map +1 -1
  106. package/services/base.service.d.ts +5 -1
  107. package/services/base.service.d.ts.map +1 -1
  108. package/services/common.service.d.ts +3 -3
  109. package/services/common.service.d.ts.map +1 -1
  110. package/services/crud.service.d.ts.map +1 -1
  111. package/services/notifier.service.d.ts +1 -1
  112. package/services/notifier.service.d.ts.map +1 -1
  113. package/services/user.service.d.ts +14 -2
  114. package/services/user.service.d.ts.map +1 -1
  115. package/tnx-shared.d.ts +48 -42
  116. package/tnx-shared.d.ts.map +1 -1
  117. package/tnx-shared.metadata.json +1 -1
  118. package/tnx-shared.module.d.ts +5 -1
  119. package/tnx-shared.module.d.ts.map +1 -1
  120. package/tnx-shared.module.ngfactory.d.ts.map +1 -1
@@ -55,6 +55,7 @@ import { ActivatedRoute, Router, NavigationEnd, NavigationStart } from '@angular
55
55
  import { Subject, ReplaySubject, combineLatest, forkJoin, from } from 'rxjs';
56
56
  import { takeUntil, catchError, shareReplay, retry, map, filter, debounceTime, distinctUntilChanged, mergeMap } from 'rxjs/operators';
57
57
  import { __awaiter } from 'tslib';
58
+ import { v4 } from 'uuid';
58
59
  import stringify from 'fast-safe-stringify';
59
60
  import * as moment_ from 'moment';
60
61
  import { isObject, sortBy, groupBy } from 'underscore';
@@ -605,7 +606,7 @@ class NotifierService {
605
606
  life
606
607
  });
607
608
  }
608
- showWarningByReponse(res) {
609
+ showWarningByResponse(res) {
609
610
  let message = res.message;
610
611
  if (!message)
611
612
  message = res.error;
@@ -883,23 +884,7 @@ class CommonService {
883
884
  this.STORAGE_KEY = 'CLIPBOARD_CONTENT';
884
885
  }
885
886
  guid() {
886
- function s4() {
887
- return Math.floor((1 + Math.random()) * 0x10000)
888
- .toString(16)
889
- .substring(1);
890
- }
891
- return (s4() +
892
- s4() +
893
- '-' +
894
- s4() +
895
- '-' +
896
- s4() +
897
- '-' +
898
- s4() +
899
- '-' +
900
- s4() +
901
- s4() +
902
- s4());
887
+ return v4();
903
888
  }
904
889
  randomString() {
905
890
  return this.guid();
@@ -4641,16 +4626,16 @@ class CrudService {
4641
4626
  return Math.ceil(milisecond / 3600000) + ' giờ trước';
4642
4627
  }
4643
4628
  else {
4644
- return ('Hôm qua lúc ' +
4645
- this.datePipe.transform(datetime, 'HH:mm'));
4629
+ return ('Hôm qua lúc '
4630
+ + this.datePipe.transform(datetime, 'HH:mm'));
4646
4631
  }
4647
4632
  }
4648
4633
  if (milisecond >= 86400000) {
4649
- if (datetime.getDate() == now.getDate() - 1 &&
4650
- datetime.getMonth() == now.getMonth() &&
4651
- datetime.getYear() == now.getYear()) {
4652
- return ('Hôm qua lúc ' +
4653
- this.datePipe.transform(datetime, 'HH:mm'));
4634
+ if (datetime.getDate() == now.getDate() - 1
4635
+ && datetime.getMonth() == now.getMonth()
4636
+ && datetime.getYear() == now.getYear()) {
4637
+ return ('Hôm qua lúc '
4638
+ + this.datePipe.transform(datetime, 'HH:mm'));
4654
4639
  }
4655
4640
  else {
4656
4641
  return this.datePipe.transform(datetime, 'dd/MM/yyyy HH:mm');
@@ -4685,25 +4670,25 @@ class CrudService {
4685
4670
  return Math.ceil(milisecond / 3600000) + ' giờ nữa';
4686
4671
  }
4687
4672
  else {
4688
- return ('Ngày mai lúc ' +
4689
- this.datePipe.transform(datetime, 'HH:mm'));
4673
+ return ('Ngày mai lúc '
4674
+ + this.datePipe.transform(datetime, 'HH:mm'));
4690
4675
  }
4691
4676
  }
4692
4677
  if (milisecond >= 86400000) {
4693
- if (datetime.getDate() == now.getDate() - 1 &&
4694
- datetime.getMonth() == now.getMonth() &&
4695
- datetime.getYear() == now.getYear()) {
4696
- return ('Ngày mai lúc ' +
4697
- this.datePipe.transform(datetime, 'HH:mm'));
4698
- }
4699
- if (datetime.getDate() == now.getDate() - 2 &&
4700
- datetime.getMonth() == now.getMonth() &&
4701
- datetime.getYear() == now.getYear()) {
4678
+ if (datetime.getDate() == now.getDate() - 1
4679
+ && datetime.getMonth() == now.getMonth()
4680
+ && datetime.getYear() == now.getYear()) {
4681
+ return ('Ngày mai lúc '
4682
+ + this.datePipe.transform(datetime, 'HH:mm'));
4683
+ }
4684
+ if (datetime.getDate() == now.getDate() - 2
4685
+ && datetime.getMonth() == now.getMonth()
4686
+ && datetime.getYear() == now.getYear()) {
4702
4687
  return 'Hai ngày nữa';
4703
4688
  }
4704
- else if (datetime.getDate() == now.getDate() - 3 &&
4705
- datetime.getMonth() == now.getMonth() &&
4706
- datetime.getYear() == now.getYear()) {
4689
+ else if (datetime.getDate() == now.getDate() - 3
4690
+ && datetime.getMonth() == now.getMonth()
4691
+ && datetime.getYear() == now.getYear()) {
4707
4692
  return 'Ba ngày nữa';
4708
4693
  }
4709
4694
  else {
@@ -4723,8 +4708,8 @@ class CrudService {
4723
4708
  return this.datePipe.transform(datetime, 'dd/MM/yyyy');
4724
4709
  }
4725
4710
  const now = new Date();
4726
- if (datetime.getMonth() == now.getMonth() &&
4727
- datetime.getYear() == now.getYear()) {
4711
+ if (datetime.getMonth() == now.getMonth()
4712
+ && datetime.getYear() == now.getYear()) {
4728
4713
  const days = datetime.getDate() - now.getDate();
4729
4714
  if (days == 0) {
4730
4715
  return 'Hôm nay';
@@ -4755,7 +4740,8 @@ class CrudService {
4755
4740
  return this.datePipe.transform(datetime, 'dd/MM/yyyy');
4756
4741
  }
4757
4742
  }
4758
- hideControlAndLabel() { }
4743
+ hideControlAndLabel() {
4744
+ }
4759
4745
  buildFilter(field, operator, value) {
4760
4746
  return new Filter({ field, operator, value });
4761
4747
  }
@@ -4858,7 +4844,8 @@ class CrudService {
4858
4844
  this.createDropdownOptions(schema));
4859
4845
  }
4860
4846
  promise.then(res => {
4861
- let funcSetValueRow = (rowItem, data) => { };
4847
+ let funcSetValueRow = (rowItem, data) => {
4848
+ };
4862
4849
  if (schema.funcSetValueRow) {
4863
4850
  funcSetValueRow = schema.funcSetValueRow;
4864
4851
  }
@@ -5164,19 +5151,24 @@ class CrudService {
5164
5151
  this._injector.get(NotifierService).showWarning('Có lỗi xảy ra. Liên hệ quản trị viên để biết thêm chi tiết.');
5165
5152
  }
5166
5153
  else {
5167
- if (res.message != null && res.message != '')
5154
+ if (res.message != null && res.message != '') {
5168
5155
  this._injector.get(NotifierService).showWarning(res.message);
5169
- else
5156
+ }
5157
+ else {
5170
5158
  this._injector.get(NotifierService).showWarning(res.error);
5159
+ }
5171
5160
  }
5172
- if (callBackError)
5161
+ if (callBackError) {
5173
5162
  callBackError(res);
5163
+ }
5174
5164
  return;
5175
5165
  }
5176
- if (message)
5166
+ if (message) {
5177
5167
  this._injector.get(NotifierService).showSuccess(message);
5178
- if (callBack)
5168
+ }
5169
+ if (callBack) {
5179
5170
  callBack(res);
5171
+ }
5180
5172
  }
5181
5173
  handleReponsePromise(res, messageSuccess) {
5182
5174
  return new Promise((resolve, reject) => {
@@ -5214,8 +5206,8 @@ class CrudService {
5214
5206
  }
5215
5207
  deQuyReplaceValue(filters, filter, model, rootModel) {
5216
5208
  let valueFilter = null;
5217
- var sourceField = filter.sourceField;
5218
- var subField = filter.subField;
5209
+ const sourceField = filter.sourceField;
5210
+ const subField = filter.subField;
5219
5211
  const canAccessSubField = (value) => {
5220
5212
  return subField != null
5221
5213
  && subField !== ''
@@ -5223,14 +5215,16 @@ class CrudService {
5223
5215
  };
5224
5216
  if (model.hasOwnProperty(sourceField)) {
5225
5217
  valueFilter = model[sourceField];
5226
- if (canAccessSubField(valueFilter))
5218
+ if (canAccessSubField(valueFilter)) {
5227
5219
  valueFilter = valueFilter[subField];
5220
+ }
5228
5221
  }
5229
5222
  else if (rootModel) {
5230
5223
  if (rootModel.hasOwnProperty(sourceField)) {
5231
5224
  valueFilter = rootModel[sourceField];
5232
- if (canAccessSubField(valueFilter))
5225
+ if (canAccessSubField(valueFilter)) {
5233
5226
  valueFilter = valueFilter[subField];
5227
+ }
5234
5228
  }
5235
5229
  else {
5236
5230
  const fields = sourceField.split('.');
@@ -5244,25 +5238,30 @@ class CrudService {
5244
5238
  break;
5245
5239
  }
5246
5240
  }
5247
- if (canAccessSubField(temp))
5241
+ if (canAccessSubField(temp)) {
5248
5242
  valueFilter = temp[subField];
5243
+ }
5249
5244
  }
5250
5245
  }
5251
- if (filter.logic == null && (valueFilter == null || valueFilter === '' || valueFilter.length == 0))
5246
+ if (filter.logic == null && (valueFilter == null || valueFilter === '' || valueFilter.length == 0)) {
5252
5247
  return;
5248
+ }
5253
5249
  const tmpFilter = new Filter(filter);
5254
5250
  delete tmpFilter.sourceField;
5255
- if (tmpFilter.funcGetValue)
5251
+ if (tmpFilter.funcGetValue) {
5256
5252
  valueFilter = tmpFilter.funcGetValue(valueFilter);
5253
+ }
5257
5254
  tmpFilter.value = JSON.stringify(valueFilter);
5258
5255
  tmpFilter.filters = [];
5259
5256
  if (filter.logic && filter.filters) {
5260
5257
  filter.filters.forEach(f => this.deQuyReplaceValue(tmpFilter.filters, f, model, rootModel));
5261
- if (tmpFilter.filters.length > 0)
5258
+ if (tmpFilter.filters.length > 0) {
5262
5259
  filters.push(tmpFilter);
5260
+ }
5263
5261
  }
5264
- else
5262
+ else {
5265
5263
  filters.push(tmpFilter);
5264
+ }
5266
5265
  }
5267
5266
  getWorkflowCoreStatusText(workflowCoreStatusValue) {
5268
5267
  const item = DataSourceWorkflowCoreStatus.find(x => x.id == workflowCoreStatusValue);
@@ -5362,7 +5361,8 @@ class CrudService {
5362
5361
  if (schema.funcGetLabel) {
5363
5362
  funcGetLabel = schema.funcGetLabel;
5364
5363
  }
5365
- let funcSetValueRow = (rowItem, data) => { };
5364
+ let funcSetValueRow = (rowItem, data) => {
5365
+ };
5366
5366
  let funcGetRefDataRow = (refItems) => {
5367
5367
  return refItems.map(item => funcGetLabel(item)).join(`${schema.separator} `);
5368
5368
  };
@@ -5513,14 +5513,17 @@ class BaseService {
5513
5513
  }
5514
5514
  }
5515
5515
  });
5516
- if (apiUrl.indexOf('?') == -1)
5516
+ if (apiUrl.indexOf('?') == -1) {
5517
5517
  apiUrl += `?`;
5518
- else
5518
+ }
5519
+ else {
5519
5520
  apiUrl += `&`;
5521
+ }
5520
5522
  apiUrl += `_keySignalr=${topic}`;
5521
5523
  this._http.get(apiUrl)
5522
5524
  .pipe(shareReplay(this.REPLAY_COUNT), retry(this.RETRY_COUNT), catchError((err) => this.handleError(err, this._injector))).toPromise()
5523
- .then(res => { })
5525
+ .then(res => {
5526
+ })
5524
5527
  .catch(err => {
5525
5528
  this.unSubscribeSignalR(topic);
5526
5529
  reject(err);
@@ -5541,14 +5544,17 @@ class BaseService {
5541
5544
  }
5542
5545
  }
5543
5546
  });
5544
- if (apiUrl.indexOf('?') == -1)
5547
+ if (apiUrl.indexOf('?') == -1) {
5545
5548
  apiUrl += `?`;
5546
- else
5549
+ }
5550
+ else {
5547
5551
  apiUrl += `&`;
5552
+ }
5548
5553
  apiUrl += `_keySignalr=${topic}`;
5549
5554
  this._http.post(apiUrl, data)
5550
5555
  .pipe(shareReplay(this.REPLAY_COUNT), retry(this.RETRY_COUNT), catchError((err) => this.handleError(err, this._injector))).toPromise()
5551
- .then(res => { })
5556
+ .then(res => {
5557
+ })
5552
5558
  .catch(err => {
5553
5559
  this.unSubscribeSignalR(topic);
5554
5560
  reject(err);
@@ -5801,8 +5807,12 @@ class BaseService {
5801
5807
  const url = `${this.serviceUri}/${id}`;
5802
5808
  return this.defaultGet(url);
5803
5809
  }
5804
- getDetailWithPermission(id) {
5805
- const url = `${this.serviceUri}/DetailWithPermission/${id}`;
5810
+ getDetailWithPermission(id, pid = null) {
5811
+ const url = `${this.serviceUri}/DetailWithPermission/${id}?pid=${pid}`;
5812
+ return this.defaultGet(url);
5813
+ }
5814
+ getDetailByPid(pid) {
5815
+ const url = `${this.serviceUri}/DetailWithByPid/${pid}`;
5806
5816
  return this.defaultGet(url);
5807
5817
  }
5808
5818
  getByInstanceId(instanceId) {
@@ -5855,6 +5865,10 @@ class BaseService {
5855
5865
  const url = `${this.serviceUri}/${id}`;
5856
5866
  return this._http.delete(url).toPromise();
5857
5867
  }
5868
+ deleteById(id) {
5869
+ const url = `${this.serviceUri}/${id}`;
5870
+ return this._http.delete(url).pipe(catchError((err) => this.handleError(err, this._injector))).toPromise();
5871
+ }
5858
5872
  deleteMany(lstId) {
5859
5873
  const url = `${this.serviceUri}/DeleteManyAsync/${lstId}`;
5860
5874
  return this._http.delete(url).toPromise();
@@ -6028,6 +6042,16 @@ class BaseService {
6028
6042
  choYKien(itemWorkflowHistory) {
6029
6043
  return this.defaultPost(`${this.serviceUri}/ChoYKienBase`, itemWorkflowHistory);
6030
6044
  }
6045
+ getSharedKey(ids) {
6046
+ return this.defaultPost(`${this.serviceUri}/GetSharedKeyItemBase`, {
6047
+ listGuidValue: ids
6048
+ });
6049
+ }
6050
+ deleteLinkSharing(ids) {
6051
+ return this.defaultPost(`${this.serviceUri}/DeleteLinkSharing`, {
6052
+ listGuidValue: ids
6053
+ });
6054
+ }
6031
6055
  rollback(rowData, lstObjectName) {
6032
6056
  return this.defaultPost(`${this.serviceUri}/RollbackBase/${rowData.__workflowCode}/${rowData.id}`, {
6033
6057
  ListStringValue: lstObjectName
@@ -7835,6 +7859,12 @@ class UserService extends BaseService {
7835
7859
  });
7836
7860
  }
7837
7861
  }
7862
+ /**
7863
+ * Hàm dùng để lấy thông tin cơ bản nhiều người dùng dựa vào userName,
7864
+ * hiện tại chưa có thông tin về đơn vị và chức vụ người dùng để giảm load và vì chưa dùng đến
7865
+ * @param {string} userName
7866
+ * @return {Promise<BasicUserInfo[]>
7867
+ */
7838
7868
  getBasicUserInfoByUserName(userName) {
7839
7869
  const storageItem = localStorage.getItem(this.USER_INFO_KEY + '_' + userName);
7840
7870
  const user = JSON.parse(storageItem);
@@ -7863,23 +7893,31 @@ class UserService extends BaseService {
7863
7893
  }));
7864
7894
  }
7865
7895
  }
7866
- getBasicUsersInfoByUserName(userNames) {
7867
- const storageItem = localStorage.getItem(this.USER_INFO_KEY);
7868
- const userInfos = JSON.parse(storageItem);
7869
- const check = userInfos ? userNames.indexOf(userInfos['userName']) > -1 : null;
7870
- if (check) {
7871
- return new Promise((resolve, reject) => resolve(userInfos));
7872
- }
7873
- else {
7874
- return new Promise((resolve, reject) => {
7875
- const svUrl = `${this.serviceUri}/GetBasicUsersInfoByUserName?userNames=${userNames}`;
7876
- this._http.get(svUrl).pipe(shareReplay(this.REPLAY_COUNT), retry(this.RETRY_COUNT), catchError((err) => this.handleError(err, this._injector)), map(repsonse => repsonse.data)).toPromise().then(success => {
7877
- resolve(success);
7878
- }).catch(err => {
7879
- resolve([]);
7880
- });
7881
- });
7882
- }
7896
+ /**
7897
+ * Hàm dùng để lấy thông tin cơ bản nhiều người dùng dựa vào userName,
7898
+ * hiện tại chưa có thông tin về đơn vị và chức vụ người dùng để giảm load và vì chưa dùng đến
7899
+ * @param {string} userNames
7900
+ * @return {Promise<BasicUserInfo[]>
7901
+ */
7902
+ getBasicUsersInfoByUserNames(userNames) {
7903
+ return __awaiter(this, void 0, void 0, function* () {
7904
+ const storageItem = localStorage.getItem(this.USER_INFO_KEY);
7905
+ const userInfos = JSON.parse(storageItem);
7906
+ const check = userInfos ? userNames.indexOf(userInfos['userName']) > -1 : null;
7907
+ if (check) {
7908
+ return userInfos;
7909
+ }
7910
+ else {
7911
+ const svUrl = `${this.serviceUri}/GetBasicUsersInfoByUserNames?userNames=${userNames}`;
7912
+ return yield this._http.get(svUrl).pipe(shareReplay(this.REPLAY_COUNT), retry(this.RETRY_COUNT), catchError((err) => this.handleError(err, this._injector)), map(repsonse => {
7913
+ localStorage.setItem(this.USER_INFO_KEY + '_' + repsonse.data.map(x => {
7914
+ if (x.userName)
7915
+ return x.userName;
7916
+ }), JSON.stringify(repsonse.data));
7917
+ return repsonse.data;
7918
+ })).toPromise().catch(err => []);
7919
+ }
7920
+ });
7883
7921
  }
7884
7922
  convertListUserIdToString(userIds) {
7885
7923
  if (userIds.length > 0) {
@@ -7887,14 +7925,14 @@ class UserService extends BaseService {
7887
7925
  }
7888
7926
  return ',';
7889
7927
  }
7890
- fillBasicUserInfo(dataSource, propertyName, users) {
7928
+ fillBasicUserInfo(dataSource, propertyName) {
7891
7929
  dataSource.forEach(item => {
7892
7930
  const userId = item[propertyName].id ? item[propertyName].id : item[propertyName];
7893
7931
  // tslint:disable-next-line:no-shadowed-variable
7894
- const user = users.find(user => user.id === userId);
7895
- if (user) {
7896
- item[propertyName] = user;
7897
- }
7932
+ // const user = users.find(user => user.id === userId);
7933
+ // if (user) {
7934
+ // item[propertyName] = user;
7935
+ // }
7898
7936
  });
7899
7937
  return dataSource;
7900
7938
  }
@@ -9306,23 +9344,38 @@ class TnCustomScrollbarComponent {
9306
9344
  const divs = this.elementRef.getElementsByClassName('ps-content');
9307
9345
  if (divs && divs.length > 0) {
9308
9346
  const contentDiv = divs[0];
9309
- const scrollYs = contentDiv.parentElement.getElementsByClassName('ps__thumb-y');
9310
- if (scrollYs && scrollYs.length > 0) {
9311
- setTimeout(() => {
9312
- this.checkScrollBar(contentDiv, scrollYs[0]);
9313
- }, this._intervalTime);
9347
+ const scrollYHolder = this.findNext(contentDiv, 'ps__rail-y');
9348
+ if (scrollYHolder) {
9349
+ const scrollYs = scrollYHolder.getElementsByClassName('ps__thumb-y');
9350
+ if (scrollYs && scrollYs.length > 0) {
9351
+ setTimeout(() => {
9352
+ this.checkScrollBar(contentDiv, scrollYs[0]);
9353
+ }, this._intervalTime);
9354
+ }
9314
9355
  }
9315
9356
  }
9316
9357
  }
9358
+ findNext(curentNode, className) {
9359
+ let nextSibling = curentNode.nextSibling;
9360
+ while (nextSibling) {
9361
+ if (nextSibling.classList && nextSibling.classList.contains(className)) {
9362
+ return nextSibling;
9363
+ }
9364
+ nextSibling = nextSibling.nextSibling;
9365
+ }
9366
+ return null;
9367
+ }
9317
9368
  checkScrollBar(contentDiv, scrollY) {
9318
9369
  try {
9319
9370
  const contentHeight = contentDiv.clientHeight;
9320
9371
  const holderHeight = contentDiv.parentElement.clientHeight;
9321
- if (holderHeight >= contentHeight) {
9322
- scrollY.style.display = 'none';
9323
- }
9324
- else {
9325
- scrollY.style.display = '';
9372
+ if (holderHeight > 0) {
9373
+ if (holderHeight >= contentHeight) {
9374
+ scrollY.style.display = 'none';
9375
+ }
9376
+ else {
9377
+ scrollY.style.display = '';
9378
+ }
9326
9379
  }
9327
9380
  if (this._checkScrollBar) {
9328
9381
  setTimeout(() => {
@@ -14206,7 +14259,7 @@ class DataFormBase extends ComponentBase {
14206
14259
  }
14207
14260
  getObjectDetail() {
14208
14261
  return __awaiter(this, void 0, void 0, function* () {
14209
- return yield this.setting.baseService.getDetailWithPermission(this.model.data.id);
14262
+ return yield this.setting.baseService.getDetailWithPermission(this.model.data.id, this.model.data.pid);
14210
14263
  });
14211
14264
  }
14212
14265
  getDetailCustom() {
@@ -14293,7 +14346,7 @@ class DataFormBase extends ComponentBase {
14293
14346
  this.model.data = data;
14294
14347
  this.checkPermission(data.basePermission);
14295
14348
  if (this.crudForm) {
14296
- this.crudForm.switchViewMode(true);
14349
+ this.crudForm.switchViewMode(this.__isFormView);
14297
14350
  this.crudForm.data = data;
14298
14351
  this.crudForm.setIsLoadedDataEdit(true);
14299
14352
  }
@@ -15851,6 +15904,7 @@ class CrudListComponent extends ComponentBase {
15851
15904
  this.escape = true;
15852
15905
  this.config = new CrudListConfig();
15853
15906
  this.enableReorderRow = false;
15907
+ this.disableShare = false;
15854
15908
  this.fieldOrder = '_index';
15855
15909
  this._style = {};
15856
15910
  this._dataSource = [];
@@ -15928,6 +15982,10 @@ class CrudListComponent extends ComponentBase {
15928
15982
  this.workflowHistoryModel = new DialogModel({
15929
15983
  header: 'Xem lịch sử'
15930
15984
  });
15985
+ this.permissionSharingModel = new DialogModel({
15986
+ header: 'Xem danh sách link chia sẻ',
15987
+ popupSize: new PopupSize({ width: 1100, height: 650 }),
15988
+ });
15931
15989
  this.congViecModel = new DialogModel({
15932
15990
  header: 'Chạy quy trình công việc',
15933
15991
  popupSize: new PopupSize({ width: 1100, height: 650 }),
@@ -16175,8 +16233,10 @@ class CrudListComponent extends ComponentBase {
16175
16233
  }
16176
16234
  this.initColumnSchema(this.setting.cols);
16177
16235
  this.createSearchSchema();
16178
- if (!this.setting.hiddenTrinhKy && !this.menuButtons) {
16179
- this.menuButtons = () => [];
16236
+ if (!this.setting.hiddenTrinhKy || !this.disableShare) {
16237
+ if (!this.menuButtons) {
16238
+ this.menuButtons = () => [];
16239
+ }
16180
16240
  }
16181
16241
  // Nếu mà ẩn advancesearch => sẽ không có trigger load data từ advance search => phải tự gọi getData ở OnInit
16182
16242
  if (this.setting.hiddenAdvanceSearch) {
@@ -17207,6 +17267,43 @@ class CrudListComponent extends ComponentBase {
17207
17267
  .catch(err => this.hideWaitBox());
17208
17268
  }
17209
17269
  }
17270
+ createShareLink() {
17271
+ return __awaiter(this, void 0, void 0, function* () {
17272
+ const rowData = this.rowDataCurrent;
17273
+ const dicPermissionId = (yield this.setting.baseService.getSharedKey([rowData.id])).data;
17274
+ if (!dicPermissionId) {
17275
+ this._notifierService.showWarning('Bạn không có quyền chia sẻ bản ghi');
17276
+ }
17277
+ const dicState = yield this.setting.getItemState([rowData]);
17278
+ const shareLink = this.generateShareLink(rowData.id, dicPermissionId[rowData.id], dicState[rowData.id]);
17279
+ this.copyToClipboard(shareLink);
17280
+ this._notifierService.showSuccess('Copy đường dẫn chia sẻ vào clipboard thành công');
17281
+ });
17282
+ }
17283
+ createShareLinkMultiple() {
17284
+ return __awaiter(this, void 0, void 0, function* () {
17285
+ const ids = this.model.selectedItems.map(q => q.id);
17286
+ const dicPermissionId = (yield this.setting.baseService.getSharedKey(ids)).data;
17287
+ if (!dicPermissionId) {
17288
+ this._notifierService.showWarning('Bạn không có quyền chia sẻ bản ghi');
17289
+ }
17290
+ const dicState = yield this.setting.getItemState(this.model.selectedItems);
17291
+ let content = '';
17292
+ ids.forEach(id => {
17293
+ content += `${this.generateShareLink(id, dicPermissionId[id], dicState[id])}\n`;
17294
+ });
17295
+ this.copyToClipboard(content);
17296
+ this._notifierService.showSuccess('Copy đường dẫn chia sẻ vào clipboard thành công');
17297
+ });
17298
+ }
17299
+ generateShareLink(id, pid, state) {
17300
+ let result = `${top.location.origin}${top.location.pathname}?pid=${pid}`;
17301
+ result += `serviceCode=${this.setting.baseService.serviceCode}`;
17302
+ result += `&entity=${this.setting.baseService.entityName}`;
17303
+ result += `&entityKey=${id}`;
17304
+ result += `&state=${encodeURIComponent(JSON.stringify(state))}`;
17305
+ return result;
17306
+ }
17210
17307
  checkHasPermissionInLastStatus(rowData) {
17211
17308
  return __awaiter(this, void 0, void 0, function* () {
17212
17309
  const statusKetThuc = this.setting.workflowSetting.statuses.find(q => q.type == EnumWFNhomTrangThai.KET_THUC);
@@ -17233,6 +17330,9 @@ class CrudListComponent extends ComponentBase {
17233
17330
  this.buttonContexts.unshift({ label: this.setting.getLabelButtonTrinhKy(rowData), icon: 'pi pi-send', command: this.trinhKy.bind(this) });
17234
17331
  }
17235
17332
  }
17333
+ if (!this.disableShare) {
17334
+ this.buttonContexts.push({ label: 'Chia sẻ', icon: 'pi pi-link', command: this.createShareLink.bind(this) }, { label: 'Danh sách chia sẻ', icon: 'pi pi-list', command: this.showLinkSharing.bind(this) });
17335
+ }
17236
17336
  if (this.buttonContexts.length > 0) {
17237
17337
  this._showContextMenu(evt);
17238
17338
  }
@@ -18288,6 +18388,9 @@ class CrudListComponent extends ComponentBase {
18288
18388
  showSettingsWorkflowNew() {
18289
18389
  this.workflowSettingModel.showEditForm = true;
18290
18390
  }
18391
+ showLinkSharing() {
18392
+ this.permissionSharingModel.showEditForm = true;
18393
+ }
18291
18394
  onSaveWorkflowSettings(event) {
18292
18395
  this.setting.workflowSetting = event;
18293
18396
  this._commonService.reloadPage();
@@ -18342,7 +18445,7 @@ CrudListComponent.decorators = [
18342
18445
  { type: Component, args: [{
18343
18446
  // tslint:disable-next-line: component-selector
18344
18447
  selector: 'crud-list',
18345
- template: "<div #container class=\"custom-card card card-w-title flex-container-fit-child\" [attr.height-type]=\"setting.heightType\"\r\n [ngStyle]=\"_style\">\r\n <div class=\"ui-helper-clearfix crud-list-header-area\">\r\n <div *ngIf=\"searchCustom\" class=\"p-grid ui-fluid custom-p-col custom-search-area\">\r\n <div class=\"p-col-12 main-container-search\">\r\n <div class=\"p-grid main-container-search-inner\">\r\n <ng-container>\r\n <ng-container *ngTemplateOutlet=\"searchCustom; context: {$implicit: this}\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n <div *ngIf=\"!setting.hiddenHeader\" class=\"p-grid ui-fluid custom-p-col page-title-area\">\r\n <div *ngIf=\"!setting.hiddenPageTitle\" class=\"main-title\">\r\n <h1 *ngIf=\"!hasTemplate('customTitle')\">\r\n {{setting.title != null ? setting.title : 'Danh s\u00E1ch ' + setting.objectName}}\r\n </h1>\r\n\r\n <ng-container *ngIf=\"hasTemplate('customTitle')\" [ngTemplateOutlet]=\"getTemplate('customTitle')\"\r\n [ngTemplateOutletContext]=\"{crudList: this}\">\r\n </ng-container>\r\n </div>\r\n\r\n <div *ngIf=\"!setting.hiddenPageSetting\" class=\"paginator-table\">\r\n <paging-next-back-only [model]=\"model\" [setting]=\"setting\" (onOldest)=\"onOldest($event)\"\r\n (onNext)=\"onNext($event)\" (onPrev)=\"onPrev($event)\" (onLatest)=\"onLatest($event)\"\r\n (onChangeLimitPage)=\"savePageSize()\">\r\n </paging-next-back-only>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"fit-content crud-list-body-area\">\r\n <div class=\"crud-list-body-area-inner\" style=\"overflow: unset;\">\r\n <div class=\"flex-container-fit-child\" style=\"overflow: unset;\">\r\n <div *ngIf=\"!setting.hiddenToolbar\" class=\"p-grid crudListToolbar\">\r\n <ng-container>\r\n <div *ngIf=\"!setting.hiddenButtons && hasTemplate('toolbar')\"\r\n [ngClass]=\"setting.hiddenAdvanceSearch ? 'p-md-12 p-lg-12' : 'p-md-7 p-lg-8'\"\r\n class=\"p-col-12 button-group function-topbar custom-toolbar\">\r\n <ng-container\r\n [ngTemplateOutletContext]=\"{selectedItems: model.selectedItems, crudList: this}\"\r\n [ngTemplateOutlet]=\"getTemplate('toolbar')\"></ng-container>\r\n </div>\r\n <div *ngIf=\"!setting.hiddenButtons && !hasTemplate('toolbar')\"\r\n [ngClass]=\"setting.hiddenAdvanceSearch ? 'p-md-12 p-lg-12' : 'p-md-7 p-lg-8'\"\r\n class=\"p-col-12 button-group function-topbar\">\r\n <button *ngIf=\"!hiddenAdd\" type=\"button\" pButton pRipple label=\"Th\u00EAm m\u1EDBi\" icon=\"pi pi-plus\"\r\n class=\"p-button-text\" [disabled]=\"!model.baseReady\" (click)=\"add()\"></button>\r\n <button *ngIf=\"setting.showExportSelectedItems && model.selectedItems.length > 0\"\r\n type=\"button\" pButton pRipple\r\n label=\"Xu\u1EA5t c\u00E1c m\u1EE5c \u0111\u00E3 ch\u1ECDn ({{model.selectedItems.length}})\" icon=\"fas fa-file-excel\"\r\n class=\"p-button-text p-button-success\" (click)=\"xuatCacMucDaChon()\"></button>\r\n <button *ngIf=\"!hiddenDelete && model.selectedItems.length > 0 && !disableMultipleDelete()\"\r\n type=\"button\" pButton pRipple\r\n label=\"{{ 'X\u00F3a' | translate }} ({{model.selectedItems.length}})\" icon=\"pi pi-trash\"\r\n class=\"p-button-text p-button-danger\" (click)=\"deleteMutiple()\"></button>\r\n <button\r\n *ngIf=\"!hiddenCopyLink && model.selectedItems.length > 0 && !disableMultipleCopyLink()\"\r\n label=\"Sao ch\u00E9p li\u00EAn k\u1EBFt\" type=\"button\" pButton pRipple\r\n pTooltip=\"{{'Sao ch\u00E9p li\u00EAn k\u1EBFt' | translate}}\" tooltipPosition=\"top\"\r\n class=\"p-button-rounded p-button-text p-button-info link-or-action\" icon=\"pi pi-link\"\r\n (click)=\"copyLinkMultiple()\"></button>\r\n <ng-container [ngTemplateOutlet]=\"getTemplate('buttonAfterToolbar')\"\r\n [ngTemplateOutletContext]=\"{crudList: this}\"></ng-container>\r\n </div>\r\n </ng-container>\r\n <div *ngIf=\"!setting.hiddenAdvanceSearch\" class=\"p-col-12 advance-search-container\"\r\n [ngClass]=\"setting.hiddenButtons ? 'p-md-12 p-lg-12' : 'p-md-5 p-lg-4'\">\r\n <advance-search #advanceSearch [parentSetting]=\"setting\" [searchInfo]=\"searchInfo\"\r\n [loading]=\"model.loading\" (onSearch)=\"handleSearchAdvs($event)\"\r\n (onInit)=\"handleInitAdvanceSearch($event)\">\r\n </advance-search>\r\n </div>\r\n </div>\r\n <div *ngIf=\"hasTemplate('topGrid')\" class=\"extend-content-top-grid\">\r\n <ng-container [ngTemplateOutletContext]=\"{selectedItems: model.selectedItems, crudList: this}\"\r\n [ngTemplateOutlet]=\"getTemplate('topGrid')\"></ng-container>\r\n </div>\r\n <div class=\"container-table fit-content\" [class.--table-responsive]=\"responsive\">\r\n <div class=\"container-table-inner\">\r\n <ng-container *ngIf=\"!_groupField\">\r\n <tn-custom-scrollbar *ngIf=\"showScrollBar\" #scrollbar [config]=\"configScrollBar\"\r\n [showScrollHorizontal]=\"showScrollHorizontal\">\r\n <ng-container *ngTemplateOutlet=\"tableGetGroupFieldFalse\">\r\n </ng-container>\r\n <ng-container *ngIf=\"hasTemplate('afterCrudList')\">\r\n <ng-container [ngTemplateOutlet]=\"hasTemplate('afterCrudList')\"></ng-container>\r\n </ng-container>\r\n </tn-custom-scrollbar>\r\n <div *ngIf=\"!showScrollBar\">\r\n <ng-container *ngTemplateOutlet=\"tableGetGroupFieldFalse\">\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"_groupField\">\r\n <tn-custom-scrollbar *ngIf=\"showScrollBar\" #scrollbar [config]=\"configScrollBar\"\r\n [showScrollHorizontal]=\"showScrollHorizontal\">\r\n <ng-container *ngTemplateOutlet=\"tableGetGroupFieldTrue\">\r\n </ng-container>\r\n <ng-container *ngIf=\"hasTemplate('afterCrudList')\">\r\n <ng-container [ngTemplateOutlet]=\"getTemplate('afterCrudList')\"></ng-container>\r\n </ng-container>\r\n </tn-custom-scrollbar>\r\n <div *ngIf=\"!showScrollBar\">\r\n <ng-container *ngTemplateOutlet=\"tableGetGroupFieldTrue\">\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n\r\n <div class=\"table-border-line --top\"></div>\r\n <div class=\"table-border-line --right\"></div>\r\n <div class=\"table-border-line --bottom\"></div>\r\n <div class=\"table-border-line --left\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n<after-view-checked (loaded)=\"handleReady()\"></after-view-checked>\r\n<settings *ngIf=\"_showSettings && !setting.hiddenSetting\" [entityMetadataService]=\"entityMetadataService\"\r\n [parentContext]=\"context\" [parentSetting]=\"setting\" [parentModel]=\"model\" (onSave)=\"onSaveSettings($event)\"\r\n (onCancel)=\"_showSettings = false\">\r\n</settings>\r\n<settings-row *ngIf=\"_showSettingsRowColor && !setting.hiddenSetting\" [entityMetadataService]=\"entityMetadataService\"\r\n [parentContext]=\"context\" [parentSetting]=\"setting\" [parentModel]=\"model\" (onSave)=\"onSaveColorSettings($event)\"\r\n (onCancel)=\"_showSettingsRowColor = false\">\r\n</settings-row>\r\n<workflow-setting-dialog *ngIf=\"_showSettingsWorkflow && !setting.hiddenSettingWorkflow\" [parentSetting]=\"setting\"\r\n [parentContext]=\"context\" [parentModel]=\"model\" (onSaved)=\"onSaveWorkflowSettings($event)\"\r\n (onRemoved)=\"onRemoveWorkflowSettings($event)\" (onCancel)=\"_showSettingsWorkflow = false\"></workflow-setting-dialog>\r\n<tn-dialog *ngIf=\"workflowSettingModel.showEditForm\" [header]=\"'C\u1EA5u h\u00ECnh quy tr\u00ECnh nghi\u1EC7p v\u1EE5' | translate\"\r\n [popupSize]=\"workflowSettingModel.popupSize\" (onHide)=\"workflowSettingModel.showEditForm = false\">\r\n <workflow-setting-new #formBase [parentSetting]=\"setting\" (onSaved)=\"onSaveWorkflowSettingsNew($event)\"\r\n (onCancel)=\"workflowSettingModel.showEditForm = false\"></workflow-setting-new>\r\n</tn-dialog>\r\n<entity-permission *ngIf=\"_showSettingsPermission && !setting.hiddenSettingPermission\" [parentSetting]=\"setting\"\r\n [parentContext]=\"context\" [parentModel]=\"model\" [searchInfo]=\"searchInfo\"\r\n (onCancel)=\"_showSettingsPermission = false\">\r\n</entity-permission>\r\n<p-contextMenu #contextMenu [appendTo]=\"'body'\" [model]=\"buttonContexts\">\r\n</p-contextMenu>\r\n<tn-dialog *ngIf=\"showFormWorkflow\" #dialog [header]=\"headerWorkflow | translate\" [popupSize]=\"popupSizeWorkflow\"\r\n [scrollBarStyleClass]=\"'fit-content'\" (onHide)=\"showFormWorkflow = false\">\r\n <div style=\"height: 100%\">\r\n <simple-workflow-form #formBase [baseService]=\"setting.baseService\" [item]=\"currentItem\"\r\n [action]=\"actionWorkflow\" (onInvalidWorkflow)=\"handleInvalidWF($event)\" (onSaved)=\"handleProcessedWorflow()\"\r\n (onCancel)=\"showFormWorkflow = false\">\r\n </simple-workflow-form>\r\n </div>\r\n</tn-dialog>\r\n<tn-dialog *ngIf=\"processWorkflowModel.showEditForm\" #dialog [header]=\"processWorkflowModel.header | translate\"\r\n [popupSize]=\"processWorkflowModel.popupSize\" [scrollBarStyleClass]=\"'fit-content'\"\r\n (onHide)=\"processWorkflowModel.showEditForm = false\">\r\n <div style=\"height: 100%\">\r\n <process-workflow-form #formBase [businessSetting]=\"setting\" [item]=\"currentItem\"\r\n [workflow]=\"processWorkflowModel.data.workflow\" [action]=\"processWorkflowModel.data.action\"\r\n (onSaved)=\"handleProcessedWorkflowBase()\" (onCancel)=\"processWorkflowModel.showEditForm = false\">\r\n </process-workflow-form>\r\n </div>\r\n</tn-dialog>\r\n<tn-dialog *ngIf=\"choYKienModel.showEditForm\" #dialog [header]=\"choYKienModel.header | translate\"\r\n [popupSize]=\"choYKienModel.popupSize\" [scrollBarStyleClass]=\"'fit-content'\"\r\n (onHide)=\"choYKienModel.showEditForm = false\">\r\n <div style=\"height: 100%\">\r\n <cho-y-kien-form #formBase [bussinessSetting]=\"setting\" [rowItem]=\"choYKienModel.data.rowData\"\r\n (onSaved)=\"choYKienModel.showEditForm = false\" (onCancel)=\"choYKienModel.showEditForm = false\">\r\n </cho-y-kien-form>\r\n </div>\r\n</tn-dialog>\r\n<tn-dialog *ngIf=\"workflowHistoryModel.showEditForm\" #dialog [header]=\"workflowHistoryModel.header | translate\"\r\n [popupSize]=\"workflowHistoryModel.popupSize\" [scrollBarStyleClass]=\"'fit-content'\"\r\n (onHide)=\"workflowHistoryModel.showEditForm = false\">\r\n <div style=\"height: 100%\">\r\n <workflow-history-new #formBase [businessSetting]=\"setting\" [item]=\"currentItem\"\r\n [workflowSetting]=\"workflowHistoryModel.data.workflowSetting\"\r\n (onCancel)=\"workflowHistoryModel.showEditForm = false\">\r\n </workflow-history-new>\r\n </div>\r\n</tn-dialog>\r\n<workflow-history-dialog *ngIf=\"showHistoryWorkflow\" [baseService]=\"setting.baseService\" [item]=\"currentItem\"\r\n [workflowSetting]=\"setting.workflowSetting\" (onHide)=\"handleHideHistoryWorkflow()\">\r\n</workflow-history-dialog>\r\n<tn-dialog *ngIf=\"startWorkflowModel.showEditForm\" #dialog [header]=\"startWorkflowModel.header | translate\"\r\n [popupSize]=\"startWorkflowModel.popupSize\" [scrollBarStyleClass]=\"'fit-content'\"\r\n (onHide)=\"startWorkflowModel.showEditForm = false\">\r\n <div style=\"height: 100%\">\r\n <start-workflow #formBase [workflows]=\"startWorkflowModel.data.workflows\"\r\n [defaultWorkflow]=\"startWorkflowModel.data.defaultWorkflow\"\r\n (onCancel)=\"startWorkflowModel.showEditForm = false\" (onSaved)=\"handleStartWorkflowFromDialog($event)\">\r\n </start-workflow>\r\n </div>\r\n</tn-dialog>\r\n<tn-dialog *ngIf=\"congViecModel.showEditForm\" #dialog [styleClass]=\"'congviec-form tn-form-dialog'\"\r\n [header]=\"congViecModel.header | translate\" [popupSize]=\"congViecModel.popupSize\"\r\n (onHide)=\"congViecModel.showEditForm = false\">\r\n <base-congviec-form #formBase [parentSetting]=\"congViecModel.data.congViecSetting\"\r\n [model]=\"congViecModel.data.model\" (onSaved)=\"congViecModel.showEditForm = false;getData()\"\r\n (onCancel)=\"congViecModel.showEditForm = false\">\r\n </base-congviec-form>\r\n</tn-dialog>\r\n<ng-template #tableGetGroupFieldFalse>\r\n <p-table #table [dataKey]=\"'id'\" [scrollable]=\"pTableScrollable\" [scrollHeight]=\"pTableScrollHeight\"\r\n [columns]=\"setting.cols\" [paginator]=\"false\" [value]=\"_dataSource\" (onSort)=\"onSort($event, table)\"\r\n [class]=\"_tableClass\" [responsive]=\"responsive\" [lazy]=\"lazy\" [loading]=\"model.loading\"\r\n [(selection)]=\"model.selectedItems\" (onRowReorder)=\"handleRowOrdered($event)\">\r\n <ng-template *ngIf=\"header\" pTemplate=\"header\" let-columns>\r\n <ng-container\r\n *ngTemplateOutlet=\"header, context: {$implicit: columns, crudList: this, rowHeaderFilter: rowHeaderFilter, contentTh: contentTh, containerSticky: containerSticky, funcCheckAll: handleCheckAll}\">\r\n </ng-container>\r\n </ng-template>\r\n <ng-template *ngIf=\"!header\" pTemplate=\"header\" let-columns>\r\n <ng-container *ngTemplateOutlet=\"trHeader; context: {$implicit: columns, funcCheckAll: handleCheckAll}\">\r\n </ng-container>\r\n </ng-template>\r\n <ng-template pTemplate=\"body\" let-rowData let-columns=\"columns\" let-index=\"rowIndex\" let-expanded=\"expanded\">\r\n <ng-container\r\n *ngTemplateOutlet=\"trBody; context: {$implicit: rowData, columns: columns, index: index, expanded: expanded, eventSelectRow: handleSelectRow, eventChecked: handleCheckRowData}\">\r\n </ng-container>\r\n <after-view-checked *ngIf=\"index == _dataSource.length - 1\" style=\"display: none;\" [renderKey]=\"_dataSource\"\r\n (loaded)=\"handleTableRendered()\">\r\n </after-view-checked>\r\n </ng-template>\r\n <ng-template *ngIf=\"rowExpansion\" pTemplate=\"rowexpansion\" let-rowData let-expanded=\"expanded\">\r\n <ng-container\r\n *ngTemplateOutlet=\"rowExpansion; context: {rowData: rowData, expanded: expanded, getColSpanGroup: getColSpanGroup}\">\r\n </ng-container>\r\n </ng-template>\r\n <ng-template *ngIf=\"summary\" pTemplate=\"summary\">\r\n <ng-container *ngTemplateOutlet=\"summary\"></ng-container>\r\n </ng-template>\r\n <ng-template *ngIf=\"footer\" pTemplate=\"footer\" let-columns>\r\n <ng-container *ngTemplateOutlet=\"footer; context: {$implicit: columns}\"></ng-container>\r\n </ng-template>\r\n <ng-template *ngIf=\"colgroup\" pTemplate=\"colgroup\" let-columns>\r\n <ng-container *ngTemplateOutlet=\"colgroup; context: {$implicit: columns}\"></ng-container>\r\n </ng-template>\r\n </p-table>\r\n</ng-template>\r\n<ng-template #tableGetGroupFieldTrue>\r\n <p-table #tableGroup [scrollable]=\"pTableScrollable\" [scrollHeight]=\"pTableScrollHeight\" [columns]=\"setting.cols\"\r\n [paginator]=\"false\" [value]=\"_dataSource\" [metaKeySelection]=\"false\" (onSort)=\"onSort($event, tableGroup)\"\r\n [class]=\"_tableClass\" [customSort]=\"true\" [responsive]=\"responsive\" [lazy]=\"true\" [loading]=\"model.loading\"\r\n [(selection)]=\"model.selectedItems\" [expandedRowKeys]=\"model.expandedRowKeys\" [dataKey]=\"_groupField\">\r\n <ng-template *ngIf=\"header\" pTemplate=\"header\" let-columns>\r\n <ng-container\r\n *ngTemplateOutlet=\"header, context: {$implicit: columns, crudList: this, rowHeaderFilter: rowHeaderFilter, contentTh: contentTh, containerSticky: containerSticky, funcCheckAll: handleCheckAll_Group}\">\r\n </ng-container>\r\n </ng-template>\r\n <ng-template *ngIf=\"!header\" pTemplate=\"header\" let-columns>\r\n <ng-container\r\n *ngTemplateOutlet=\"trHeader; context: {$implicit: columns, funcCheckAll: handleCheckAll_Group}\">\r\n </ng-container>\r\n </ng-template>\r\n <ng-template pTemplate=\"body\" let-rowData let-rowIndex=\"rowIndex\" let-expanded=\"expanded\" let-columns=\"columns\">\r\n <tr *ngIf=\"rowGroupMetadata[rowData[_groupField]] && rowGroupMetadata[rowData[_groupField]].index == rowIndex\"\r\n class=\"p-widget-header group-row\" style=\"border: 0px; border-bottom: 1px solid #eee\">\r\n <td *ngIf=\"!setting.hiddenCheckbox\" class=\"center chkbox\" [class.sticky]=\"setting.stickyColumn\">\r\n <p-checkbox [(ngModel)]=\"rowGroupChecked[rowData[_groupField]]\" binary=\"true\"\r\n (onChange)=\"handleCheckRowGroup(rowData)\">\r\n </p-checkbox>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </td>\r\n <ng-container *ngIf=\"!rowGroup\">\r\n <td [colSpan]=\"getColSpanGroup()\" [class]=\"_classRowGroup\">\r\n <div class=\"container-row-group\">\r\n <a href=\"javascript:;\" [pRowToggler]=\"rowData\" class=\"container-row-group-toggle\"\r\n [class.sticky]=\"setting.stickyColumn\">\r\n <i style=\"margin-right:5px\"\r\n [ngClass]=\"expanded ? 'fas fa-fw fa-caret-down' : 'fas fa-fw fa-caret-right'\"></i>\r\n <span class=\"content-row-group\">\r\n <ng-container *ngIf=\"!contentRowGroup\">\r\n <ng-container [ngTemplateOutlet]=\"_contentRowGroup\"\r\n [ngTemplateOutletContext]=\"getContextRowGroup(rowData)\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"contentRowGroup\">\r\n <ng-container [ngTemplateOutlet]=\"contentRowGroup\"\r\n [ngTemplateOutletContext]=\"getContextRowGroup(rowData)\">\r\n </ng-container>\r\n </ng-container>\r\n </span>\r\n </a>\r\n </div>\r\n </td>\r\n </ng-container>\r\n <ng-container *ngIf=\"rowGroup\">\r\n <ng-container [ngTemplateOutlet]=\"rowGroup\"\r\n [ngTemplateOutletContext]=\"getContextRowGroupRoot(rowData, expanded)\">\r\n </ng-container>\r\n </ng-container>\r\n </tr>\r\n </ng-template>\r\n <ng-template pTemplate=\"rowexpansion\" let-columns=\"columns\" let-rowData let-index=\"rowIndex\">\r\n <ng-container\r\n *ngTemplateOutlet=\"trBody; context: {$implicit: rowData, columns: columns, index: index, expanded: false, eventSelectRow: handleSelectRowGroup, eventChecked: handleCheckRowData_Group}\">\r\n </ng-container>\r\n <after-view-checked *ngIf=\"index == _dataSource.length - 1\" style=\"display: none;\" [renderKey]=\"_dataSource\"\r\n (loaded)=\"handleTableRendered()\">\r\n </after-view-checked>\r\n </ng-template>\r\n <ng-template *ngIf=\"summary\" pTemplate=\"summary\">\r\n <ng-container *ngTemplateOutlet=\"summary\"></ng-container>\r\n </ng-template>\r\n <ng-template *ngIf=\"footer\" pTemplate=\"footer\" let-columns>\r\n <ng-container *ngTemplateOutlet=\"footer; context: {$implicit: columns}\"></ng-container>\r\n </ng-template>\r\n <ng-template *ngIf=\"colgroup\" pTemplate=\"colgroup\" let-columns>\r\n <ng-container *ngTemplateOutlet=\"colgroup; context: {$implicit: columns}\"></ng-container>\r\n </ng-template>\r\n </p-table>\r\n <after-view-checked></after-view-checked>\r\n</ng-template>\r\n<ng-template #trHeader let-columns let-funcCheckAll=\"funcCheckAll\">\r\n <tr class=\"title-row\">\r\n <ng-container *ngIf=\"!setting.hiddenCheckbox\">\r\n <th [style.width]=\"widthCheckbox\" class=\"chkbox link-or-action cell-checkbox\"\r\n [class.sticky]=\"setting.stickyColumn\">\r\n <button *ngIf=\"!hasTemplate('headerCheckbox')\" type=\"button\" pButton pRipple icon=\"pi pi-refresh\"\r\n class=\"p-button-rounded p-button-text btnReload\" pTooltip=\"L\u00E0m m\u1EDBi d\u1EEF li\u1EC7u\" tooltipPosition=\"top\"\r\n [disabled]=\"model.loading\" (click)=\"reload()\"></button>\r\n <ng-container *ngIf=\"hasTemplate('headerCheckbox')\">\r\n <ng-container [ngTemplateOutletContext]=\"{crudList: this}\"\r\n [ngTemplateOutlet]=\"getTemplate('headerCheckbox')\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n </ng-container>\r\n <th *ngIf=\"!setting.hiddenOrderColumn\" [style.width]=\"widthOrderColumn\" class=\"stt nopad center\"\r\n [class.sticky]=\"setting.stickyColumn\">\r\n {{ 'TT' |translate}}\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n <th *ngIf=\"rowExpansion\" class=\"nopad row-expansion-toggle center\" style=\"width: 2.5rem\"\r\n [class.sticky]=\"setting.stickyColumn\">\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n <ng-container *ngFor=\"let col of columns; let i = index\">\r\n <th *ngIf=\"col && col.visible && col.field!='function'\" [ngStyle]=\"col.extendData.headerStyle\"\r\n [pTooltip]=\"col.fullLabel\" tooltipStyleClass=\"unset-width\" [class]=\"col.extendData.headerClass\"\r\n [class.first-th]=\"i==0\" [escape]=\"false\" tooltipPosition=\"top\" [tnSortableColumn]=\"col.field\">\r\n <ng-container *ngTemplateOutlet=\"contentTh; context: {$implicit: col}\"></ng-container>\r\n <ng-container *ngIf=\"col.sort || col.sortClient\">\r\n <ng-container *ngTemplateOutlet=\"sortIcon; context: {field: col.field}\"></ng-container>\r\n </ng-container>\r\n </th>\r\n </ng-container>\r\n <th *ngIf=\"enableReorderRow\" style=\"width: 30px\">\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n <ng-container *ngTemplateOutlet=\"colFunctionHeader\"></ng-container>\r\n </tr>\r\n <ng-container *ngTemplateOutlet=\"rowHeaderFilter; context: {columns: columns, funcCheckAll: funcCheckAll}\">\r\n </ng-container>\r\n</ng-template>\r\n<ng-template #rowHeaderFilter let-columns=\"columns\" let-funcCheckAll=\"funcCheckAll\">\r\n <tr class=\"filter-row\" *ngIf=\"!setting.hiddenFilterRow\">\r\n <th *ngIf=\"!setting.hiddenCheckbox\" class=\"chkbox nopad center\" [class.sticky]=\"setting.stickyColumn\"\r\n [class.tricheckbox-custom-false]=\"checkedAll === false\" [style.width]=\"widthCheckbox\">\r\n <p-triStateCheckbox [(ngModel)]=\"checkedAll\" binary=\"true\" (onChange)=\"funcCheckAll()\">\r\n </p-triStateCheckbox>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n <th *ngIf=\"!setting.hiddenOrderColumn\" class=\"stt center v-top\" [class.sticky]=\"setting.stickyColumn\">\r\n <div *ngIf=\"!setting.hiddenSetting\" class=\"pick-color-row\" pTooltip=\"C\u1EA5u h\u00ECnh hi\u1EC3n th\u1ECB m\u00E0u\"\r\n tooltipPosition=\"top\" (click)=\"showSettingRowColor()\">\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n </div>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n <th *ngIf=\"rowExpansion\" class=\"nopad center row-expansion-toggle\" [class.sticky]=\"setting.stickyColumn\">\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n <ng-container *ngFor=\"let col of columns; let i = index\">\r\n <th *ngIf=\"col.visible && col.field != 'function'\" class=\"cell-header-filter center\">\r\n <ng-container *ngIf=\"col.allowFilter\">\r\n <ng-container *ngIf=\"col.templateFilter\">\r\n <ng-container [ngTemplateOutlet]=\"col.templateFilter\"\r\n [ngTemplateOutletContext]=\"{col: col, filterData: filterData, onSearch: onSearch, onShowFilterDropdownPanel: onShowFilterDropdownPanel, onHideFilterDropdownPanel: onHideFilterDropdownPanel}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!col.templateFilter\" [ngSwitch]=\"col.controlType\">\r\n <ng-container *ngSwitchCase=\"'dropdown'\">\r\n <ng-container [ngTemplateOutlet]=\"filterDropdown\"\r\n [ngTemplateOutletContext]=\"{col: col.rawColumn}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'number'\">\r\n <ng-container [ngTemplateOutlet]=\"filterNumber\" [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'date'\">\r\n <ng-container [ngTemplateOutlet]=\"filterDate\" [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'datetime'\">\r\n <ng-container [ngTemplateOutlet]=\"filterDate\" [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchDefault>\r\n <ng-container [ngSwitch]=\"col.dataType\">\r\n <ng-container *ngSwitchCase=\"'int'\">\r\n <ng-container [ngTemplateOutlet]=\"filterNumber\"\r\n [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'decimal'\">\r\n <ng-container [ngTemplateOutlet]=\"filterNumber\"\r\n [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'date'\">\r\n <ng-container [ngTemplateOutlet]=\"filterDate\"\r\n [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'datetime'\">\r\n <ng-container [ngTemplateOutlet]=\"filterDate\"\r\n [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'boolean'\">\r\n <ng-container [ngTemplateOutlet]=\"filterBoolean\"\r\n [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchDefault>\r\n <ng-container [ngTemplateOutlet]=\"filterText\"\r\n [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n </ng-container>\r\n <th *ngIf=\"enableReorderRow\" style=\"width: 30px\">\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n <th *ngIf=\"!setting.hiddenFunctionColumn\" class=\"center setting-cell column-function\"\r\n [class.sticky]=\"setting.stickyColumn\">\r\n <button *ngIf=\"!setting.hiddenSetting\" type=\"button\" pButton pRipple icon=\"pi pi-cog\"\r\n class=\"p-button-rounded p-button-text\" pTooltip=\"C\u1EA5u h\u00ECnh hi\u1EC3n th\u1ECB\" tooltipPosition=\"top\"\r\n (click)=\"showSettings()\"></button>\r\n <button *ngIf=\"!setting.hiddenSettingPermission\" type=\"button\" pButton pRipple icon=\"pi pi-users\"\r\n class=\"p-button-rounded p-button-text\" pTooltip=\"Ph\u00E2n quy\u1EC1n d\u1EEF li\u1EC7u\" tooltipPosition=\"left\"\r\n (click)=\"showSettingsPermission()\"></button>\r\n <button *ngIf=\"!setting.hiddenSettingWorkflow\" type=\"button\" pButton pRipple icon=\"pi pi-sitemap\"\r\n class=\"p-button-rounded p-button-text\" pTooltip=\"C\u1EA5u h\u00ECnh quy tr\u00ECnh\" tooltipPosition=\"left\"\r\n (click)=\"showSettingsWorkflow()\"></button>\r\n <button *ngIf=\"!setting.hiddenSettingWorkflowNew\" type=\"button\" pButton pRipple icon=\"pi pi-sitemap\"\r\n class=\"p-button-rounded p-button-text\" pTooltip=\"C\u1EA5u h\u00ECnh quy tr\u00ECnh\" tooltipPosition=\"left\"\r\n (click)=\"showSettingsWorkflowNew()\"></button>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n </tr>\r\n</ng-template>\r\n<ng-template #colFunctionHeader>\r\n <ng-container *ngIf=\"!setting.hiddenFunctionColumn\">\r\n <th class=\"column-function\" [class.sticky]=\"setting.stickyColumn\"\r\n [style.width]=\"widthFunctionColumn || _widthFunctionColumn\">\r\n <div class=\"cell-header-function\">\r\n <span>{{'GRID.FUNCTION'| translate}}</span>\r\n </div>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n </ng-container>\r\n</ng-template>\r\n<ng-template #contentTh let-col>\r\n <ng-container *ngIf=\"templateHeaderContent[col.field]\">\r\n <ng-container *ngTemplateOutlet=\"templateHeaderContent[col.field]\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!templateHeaderContent[col.field]\">\r\n {{col.label}}\r\n </ng-container>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n</ng-template>\r\n<ng-template #trBody let-rowData let-columns=\"columns\" let-index=\"index\" let-expanded=\"expanded\"\r\n let-eventSelectRow=\"eventSelectRow\" let-eventChecked=\"eventChecked\">\r\n <tr [tnReorderableRow]=\"index\" [attr.rowIndex]=\"index\"\r\n [ngClass]=\"mergeClassObj(rowData, { 'ui-state-highlight': rowData._checked })\" [pTooltip]=\"rowData.tooltip\"\r\n tooltipPosition=\"top\" [tooltipStyleClass]=\"rowData.tooltipClass\" [escape]=\"escape\"\r\n (click)=\"eventSelectRow($event, rowData)\">\r\n <ng-container *ngIf=\"!setting.hiddenCheckbox\">\r\n <td [style.width]=\"widthCheckbox\" class=\"chkbox link-or-action cell-checkbox\"\r\n [class.sticky]=\"setting.stickyColumn\">\r\n <ng-container *ngIf=\"!hasTemplate('checkbox')\">\r\n <p-checkbox [(ngModel)]=\"rowData._checked\" binary=\"true\" (onChange)=\"eventChecked(rowData)\">\r\n </p-checkbox>\r\n </ng-container>\r\n <ng-container *ngIf=\"hasTemplate('checkbox')\">\r\n <ng-container [ngTemplateOutlet]=\"getTemplate('checkbox')\"\r\n [ngTemplateOutletContext]=\"{rowData: rowData, rowIndex: index}\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </td>\r\n </ng-container>\r\n <td *ngIf=\"!setting.hiddenOrderColumn && (!rowData.hidden || !rowData.hidden[fieldOrder])\"\r\n [style.width]=\"widthOrderColumn\" class=\"stt\" style=\"text-align: center;\"\r\n [class.sticky]=\"setting.stickyColumn\" [attr.colSpan]=\"rowData.colSpan && rowData.colSpan[fieldOrder]\"\r\n [attr.rowSpan]=\"rowData.rowSpan && rowData.rowSpan[fieldOrder]\">\r\n <span class=\"row-card\" [ngStyle]=\"getBookmarkColor(rowData, columns)\"></span>\r\n {{rowData[fieldOrder]}}\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </td>\r\n <td *ngIf=\"rowExpansion\" class=\"no-padding center row-expansion-toggle\" [class.sticky]=\"setting.stickyColumn\">\r\n <ng-container *ngTemplateOutlet=\"iconToggleRowData; context: {rowData: rowData, expanded: expanded}\">\r\n </ng-container>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </td>\r\n <ng-container\r\n *ngTemplateOutlet=\"dynamicColBodys; context: {$implicit: columns, rowData: rowData, index: index, expanded: expanded}\">\r\n </ng-container>\r\n <td *ngIf=\"enableReorderRow\" class=\"no-padding center\">\r\n <i class=\"fas fa-arrows-alt\" style=\"cursor:pointer; padding: 8px; color: #555;\" pReorderableRowHandle></i>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </td>\r\n <ng-container *ngIf=\"!setting.hiddenFunctionColumn\">\r\n <td class=\"text-center column-function\" style=\"text-align: center;\" [class.sticky]=\"setting.stickyColumn\">\r\n <div *ngIf=\"hasTemplate('function')\" class=\"p-toolbar-group-center button-group\">\r\n <ng-container [ngTemplateOutlet]=\"getTemplate('function')\"\r\n [ngTemplateOutletContext]=\"{rowData: rowData, rowIndex: index}\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </div>\r\n <div *ngIf=\"!hasTemplate('function')\" class=\"p-toolbar-group-center button-group\">\r\n <ng-container [ngTemplateOutletContext]=\"{rowData: rowData, rowIndex: index}\"\r\n [ngTemplateOutlet]=\"getTemplate('buttonBefore')\"></ng-container>\r\n <button *ngIf=\"setting.showVersionButton\" type=\"button\" pButton pRipple icon=\"pi pi-calendar\"\r\n class=\"p-button-rounded p-button-success link-or-action\" pTooltip=\"Xem l\u1ECBch s\u1EED phi\u00EAn b\u1EA3n\"\r\n tooltipPosition=\"top\" (click)=\"showListVersion(rowData)\"></button>\r\n <button *ngIf=\"!rowData.hiddenEdit\" type=\"button\" pButton pRipple [disabled]=\"disableEdit(rowData)\"\r\n pTooltip=\"{{'FORM.EDIT' | translate}}\" tooltipPosition=\"top\"\r\n class=\"p-button-rounded p-button-text p-button-info link-or-action\" icon=\"pi pi-pencil\"\r\n (click)=\"edit(rowData)\"></button>\r\n <button *ngIf=\"!rowData.hiddenDelete\" type=\"button\" pButton pRipple\r\n [disabled]=\"disableDelete(rowData)\" pTooltip=\"{{'FORM.DELETE' | translate}}\"\r\n tooltipPosition=\"top\" class=\"p-button-rounded p-button-text p-button-danger link-or-action\"\r\n icon=\"pi pi-trash\" (click)=\"delete(rowData)\"></button>\r\n <button *ngIf=\"!rowData.hiddenCopyLink\" type=\"button\" pButton pRipple\r\n [disabled]=\"disableCopyLink(rowData)\" pTooltip=\"{{'Sao ch\u00E9p li\u00EAn k\u1EBFt' | translate}}\"\r\n tooltipPosition=\"top\" class=\"p-button-rounded p-button-text p-button-info link-or-action\"\r\n icon=\"pi pi-link\" (click)=\"copyLink(rowData)\"></button>\r\n <button *ngIf=\"this.menuButtons\" type=\"button\" pButton icon=\"pi pi-ellipsis-v\"\r\n class=\"link-or-action p-button-text p-button-info p-button-rounded\" pTooltip=\"Ch\u1EE9c n\u0103ng kh\u00E1c\"\r\n tooltipPosition=\"top\" (click)=\"showContextMenu($event, rowData)\"></button>\r\n </div>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </td>\r\n </ng-container>\r\n </tr>\r\n</ng-template>\r\n<ng-template #dynamicColBodys let-columns let-rowData=\"rowData\" let-index=\"index\" let-expanded=\"expanded\">\r\n <ng-container *ngFor=\"let col of columns; let i = index\">\r\n <ng-container\r\n *ngTemplateOutlet=\"contentTd; context: {$implicit: rowData, col: col, index: index, i: i, expanded: expanded}\">\r\n </ng-container>\r\n </ng-container>\r\n</ng-template>\r\n<ng-template #contentTd let-rowData let-col=\"col\" let-index=\"index\" let-expanded=\"expanded\" let-i=\"i\">\r\n <td *ngIf=\"col && col.visible && col.field != 'function' && (!rowData.hidden || !rowData.hidden[col.field])\"\r\n [attr.colSpan]=\"rowData.colSpan && rowData.colSpan[col.field]\"\r\n [attr.rowSpan]=\"rowData.rowSpan && rowData.rowSpan[col.field]\" [ngStyle]=\"col.extendData.style\"\r\n [class]=\"col.cellClass\" [class.first-td]=\"i == 0\">\r\n <span *ngIf=\"col.pipe\">\r\n <span class=\"p-column-title\" [pTooltip]=\"col.fullLabel\" [escape]=\"false\"\r\n tooltipPosition=\"top\">{{col.label}}</span>\r\n {{rowData['pipe__' + col.field]}}\r\n </span>\r\n <span *ngIf=\"!col.pipe\">\r\n <span class=\"p-column-title\" [pTooltip]=\"col.fullLabel\" [escape]=\"false\"\r\n tooltipPosition=\"top\">{{col.label}}</span>\r\n <span *ngIf=\"setting.showEditLink && col.showEditLink\" [pTooltip]=\"config.tooltipView\" tooltipPosition=\"top\"\r\n class=\"link-or-action\">\r\n <a href=\"javascript:;\" (click)=\"view(rowData)\" [pTooltip]=\"config.tooltipView\" tooltipPosition=\"top\">\r\n <ng-container [ngTemplateOutlet]=\"contentCell\"\r\n [ngTemplateOutletContext]=\"getContextCell(rowData, index, col, expanded, this)\">\r\n </ng-container>\r\n </a>\r\n </span>\r\n <span *ngIf=\"!setting.showEditLink || !col.showEditLink\">\r\n <ng-container [ngTemplateOutlet]=\"contentCell\"\r\n [ngTemplateOutletContext]=\"getContextCell(rowData, index, col, expanded, this)\">\r\n </ng-container>\r\n </span>\r\n </span>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </td>\r\n</ng-template>\r\n<ng-template #contentCell let-col=\"col\" let-rowData=\"rowData\" let-rowIndex=\"rowIndex\" let-field=\"field\"\r\n let-expanded=\"expanded\">\r\n <ng-container *ngIf=\"col.template\">\r\n <ng-container [ngTemplateOutlet]=\"col.template\"\r\n [ngTemplateOutletContext]=\"getContextCell(rowData, rowIndex, col, expanded,this)\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!col.template\">\r\n <ng-container [ngSwitch]=\"col.dataType\">\r\n <span *ngSwitchCase=\"'color'\" style=\"display:block;text-align:center;\">\r\n <div pTooltip=\"{{rowData[field]}}\" tooltipPosition=\"top\" [ngStyle]=\"{'background-color':rowData[field]}\"\r\n style=\"width:30px;height:30px;margin:0 auto;\"></div>\r\n </span>\r\n <span *ngSwitchCase=\"'icon'\" style=\"display:block;text-align:center;\">\r\n <i pTooltip=\"{{rowData[field]}}\" tooltipPosition=\"top\" style=\"text-align: center;\"\r\n [ngClass]=\"rowData[field]\"></i>\r\n </span>\r\n <span *ngSwitchCase=\"'date'\" pTooltip=\"{{rowData[field] | date:'dd/MM/yyyy'}}\" tooltipPosition=\"top\">\r\n {{_crudService.renderDate(rowData[field], col.format)}}\r\n </span>\r\n <span *ngSwitchCase=\"'datetime'\" pTooltip=\"{{rowData[field] | date:'dd/MM/yyyy HH:mm'}}\"\r\n tooltipPosition=\"top\">\r\n {{_crudService.renderDateTime(rowData[field], col.format)}}\r\n </span>\r\n <span *ngSwitchCase=\"'user'\" class=\"user\">\r\n {{rowData[field] | userFormat | async}}\r\n </span>\r\n <div *ngSwitchCase=\"'users'\" [innerHTML]=\"rowData[field] | usersFormat | async\">\r\n </div>\r\n <span *ngSwitchCase=\"'int'\">\r\n {{rowData[field]}}\r\n </span>\r\n <span *ngSwitchCase=\"'decimal'\">\r\n {{rowData[field]}}\r\n </span>\r\n <span *ngSwitchCase=\"'boolean'\">\r\n <p-checkbox class=\"boolean-data-type\" [(ngModel)]=\"rowData[field]\" binary=\"true\"\r\n [disabled]=\"col.disableCheckBox\">\r\n </p-checkbox>\r\n </span>\r\n <span *ngSwitchCase=\"'html'\">\r\n <div *ngIf=\"rowData[field]==null?'':rowData[field]\" [innerHTML]=\"rowData[field] | safeHtml\"></div>\r\n </span>\r\n <span *ngSwitchCase=\"'metadataStatus'\">\r\n <span *ngIf=\"rowData['rejectReason']\" class=\"label-danger\" [pTooltip]=\"rowData['rejectReason']\"\r\n tooltipStyleClass=\"unset-width\" [escape]=\"false\" tooltipPosition=\"top\">T\u1EEB ch\u1ED1i</span>\r\n <span *ngIf=\"rowData[field] == '0' && !rowData['rejectReason']\" class=\"label-secondary\">Ch\u01B0a\r\n duy\u1EC7t</span>\r\n <span *ngIf=\"rowData[field] == '1' && !rowData['rejectReason']\" class=\"label-warning\">Ch\u1EDD duy\u1EC7t</span>\r\n <span *ngIf=\"rowData[field] == '2'\" class=\"label-primary\">\u0110\u00E3 duy\u1EC7t</span>\r\n </span>\r\n <ng-container *ngSwitchCase=\"'string'\">\r\n <ng-container *ngTemplateOutlet=\"contentCellString; context: {$implicit: rowData, field: col.field}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"null\">\r\n <ng-container *ngTemplateOutlet=\"contentCellString; context: {$implicit: rowData, field: col.field}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchDefault>\r\n <ng-container [ngTemplateOutlet]=\"getComponentByType(col.dataType)\"\r\n [ngTemplateOutletContext]=\"getContextCell(rowData, rowIndex, col, expanded, this)\">\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</ng-template>\r\n<ng-template #contentCellString let-rowData let-field=\"field\">\r\n <span>\r\n <!-- __sv: Short Value -->\r\n <ng-container *ngIf=\"rowData[field + '__sv']\">\r\n <ng-container *ngIf=\"!rowData[field + '__showFull']\">\r\n {{rowData[field + '__sv']}}\r\n <span class=\"toggle-showfull\" (click)=\"toggleShowFull(rowData, field)\" pTooltip=\"B\u1EA5m \u0111\u1EC3 xem th\u00EAm\"\r\n tooltipPosition=\"top\">[...]</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rowData[field + '__showFull']\">\r\n {{rowData[field]}}\r\n <span class=\"toggle-showfull\" (click)=\"toggleShowFull(rowData, field)\">Thu g\u1ECDn</span>\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!rowData[field + '__sv']\">\r\n {{rowData[field]}}\r\n </ng-container>\r\n </span>\r\n</ng-template>\r\n<ng-template #iconToggleRowGroup let-rowData=\"rowData\" let-expanded=\"expanded\">\r\n <a href=\"javascript:;\" (click)=\"handleToggleRow(rowData, $event)\">\r\n <i style=\"margin-right:5px\" [ngClass]=\"expanded ? 'fas fa-fw fa-caret-down' : 'fas fa-fw fa-caret-right'\"></i>\r\n </a>\r\n</ng-template>\r\n<ng-template #iconToggleRowData let-rowData=\"rowData\" let-expanded=\"expanded\">\r\n <button type=\"button\" pButton pRipple class=\"link-or-action p-button-text p-button-rounded p-button-plain\"\r\n [icon]=\"expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'\"\r\n (click)=\"handleToggleRow(rowData, $event)\"></button>\r\n</ng-template>\r\n<ng-template #_contentRowGroup let-rowData=\"rowData\" let-groupCol=\"groupCol\" let-groupField=\"_groupField\">\r\n <ng-container [ngTemplateOutlet]=\"contentCell\"\r\n [ngTemplateOutletContext]=\"{rowData: rowData, col: groupCol, field: _groupField}\">\r\n </ng-container>\r\n <span> ({{rowGroupMetadata[rowData[_groupField]].size}})</span>\r\n</ng-template>\r\n<ng-template #entityWorkflowStatus let-rowData=\"rowData\">\r\n <div class=\"container-text-workflow\">\r\n <span class=\"content\">{{rowData.statusString ? rowData.statusString : rowData.strcurrentStateCode}}</span>\r\n <button *ngIf=\"!rowData.hiddenWorkflowAction\" type=\"button\" pButton icon=\"pi pi-ellipsis-v\"\r\n class=\"link-or-action p-button-text p-button-rounded\" pTooltip=\"H\u00E0nh \u0111\u1ED9ng\" tooltipPosition=\"top\"\r\n (click)=\"showActionWorkflow($event, rowData)\"></button>\r\n </div>\r\n</ng-template>\r\n<ng-template #trangThaiV5 let-rowData=\"rowData\">\r\n <div class=\"container-text-workflow\">\r\n <button *ngIf=\"!rowData.__workflowCode\" pButton class=\"p-button-text link-or-action\" label=\"B\u1EAFt \u0111\u1EA7u\"\r\n style=\"border: 1px solid #7ca9cd;\" pTooltip=\"B\u1EAFt \u0111\u1EA7u ch\u1EA1y quy tr\u00ECnh\" tooltipPosition=\"top\"\r\n (click)=\"showFormStartWorkflow(rowData)\"></button>\r\n <ng-container *ngIf=\"rowData.__workflowCode\">\r\n <span class=\"content\">{{rowData.__textTrangThai}}</span>\r\n <button *ngIf=\"!rowData.hiddenWorkflowAction\" type=\"button\" pButton icon=\"pi pi-ellipsis-v\"\r\n class=\"link-or-action p-button-text p-button-rounded\" pTooltip=\"H\u00E0nh \u0111\u1ED9ng\" tooltipPosition=\"top\"\r\n [disabled]=\"showingActionWorkflow\" (click)=\"showActionWorkflowNew($event, rowData)\"></button>\r\n </ng-container>\r\n </div>\r\n</ng-template>\r\n<ng-template #viewHistory let-rowData=\"rowData\">\r\n <button pButton icon=\"pi pi-calendar\" class=\"p-button-text p-button-rounded link-or-action\" pTooltip=\"Xem l\u1ECBch s\u1EED\"\r\n tooltipPosition=\"top\" (click)=\"viewHistoryWorkflowNew(rowData)\"></button>\r\n</ng-template>\r\n<ng-template #workflowCoreStatus let-rowData=\"rowData\">\r\n <div class=\"container-text-workflow\">\r\n <a class=\"content\" (click)=\"goToTask($event)\" href=\"javascript:;\">{{rowData.strworkflowCoreStatus}}</a>\r\n </div>\r\n</ng-template>\r\n<ng-template #containerSticky>\r\n <span class=\"fix-sticky top\"></span>\r\n <span class=\"fix-sticky right\"></span>\r\n <!-- <span class=\"fix-sticky bottom\"></span> -->\r\n <span class=\"fix-sticky left\"></span>\r\n</ng-template>\r\n<ng-template #sortIcon let-field=\"field\">\r\n <i class=\"p-sortable-column-icon pi\" style=\"font-size: 0.8em;\"\r\n [ngClass]=\"{'pi-sort-amount-up-alt': field == _sortField && _sortDir === 1, 'pi-sort-amount-down': field == _sortField && _sortDir === -1, 'pi-sort-alt': field != _sortField || _sortDir === 0}\"></i>\r\n</ng-template>\r\n<ng-template #filterDropdown let-col=\"col\">\r\n <div #filterBox style=\"width: 100%; border-radius: 4px;\">\r\n <dropdown *ngIf=\"col && filterSchema.dropdown[col.field]\" [control]=\"filterSchema.dropdown[col.field]\"\r\n [dataSource]=\"filterSchema.dropdown[col.field].dataSource\" [(value)]=\"filterData[col.field]\"\r\n (onHideSmartEvent)=\"onSearch()\" (onShow)=\"onShowFilterDropdownPanel($event)\"\r\n (onHide)=\"onHideFilterDropdownPanel($event)\" (mousedown)=\"initFilterBoxFocus(filterBox)\"></dropdown>\r\n </div>\r\n</ng-template>\r\n<ng-template #filterText let-col=\"col\">\r\n <div #filterBox class=\"text-filter filter-box\" tabindex=\"-1\" (mousedown)=\"initFilterBoxFocus(filterBox)\">\r\n <div tabindex=\"-1\">\r\n <input pInputText type=\"text\" class=\"input-search\" [placeholder]=\"col.label\"\r\n [(ngModel)]=\"filterData[col.field]\" (change)=\"onSearch()\"\r\n (keyup.esc)=\"onClearSearch(filterBox, col.field)\">\r\n </div>\r\n <span [ngClass]=\"{'action-clear': true, 'dirty': filterData[col.field] != null && filterData[col.field] !== ''}\"\r\n [pTooltip]=\"'B\u1ECF filter'\" tooltipPosition=\"top\" (mousedown)=\"onClearSearch(filterBox, col.field)\"\r\n tabindex=\"-1\"><i class=\"pi pi-filter-slash\"></i></span>\r\n <after-view-checked style=\"display: none;\" (loaded)=\"initFilterBoxFocus(filterBox)\">\r\n </after-view-checked>\r\n </div>\r\n</ng-template>\r\n<ng-template #filterNumber let-col=\"col\">\r\n <div #filterBox class=\"number-picker-range filter-box\" tabindex=\"-1\" (mousedown)=\"initFilterBoxFocus(filterBox)\">\r\n <div tabindex=\"-1\">\r\n <tn-number-picker-range #numberRange [maskType]=\"col.dataType\" [(ngModel)]=\"filterData[col.field]\"\r\n [min]=\"col.min\" [max]=\"col.max\" (change)=\"onSearch()\">\r\n </tn-number-picker-range>\r\n </div>\r\n <span\r\n [ngClass]=\"{'action-clear': true, 'dirty': filterData[col.field] && ((filterData[col.field][0] != null && filterData[col.field][0] !== '') || (filterData[col.field][1] != null && filterData[col.field][1] !== ''))}\"\r\n [pTooltip]=\"'B\u1ECF filter'\" tooltipPosition=\"top\" (mousedown)=\"onClearNumberSearch(filterBox, numberRange)\"\r\n tabindex=\"-1\">\r\n <i class=\"pi pi-filter-slash\"></i></span>\r\n <after-view-checked style=\"display: none;\" (loaded)=\"initFilterBoxFocus(filterBox)\">\r\n </after-view-checked>\r\n </div>\r\n</ng-template>\r\n<ng-template #filterDate let-col=\"col\">\r\n <div #filterBox class=\"date-picker-range filter-box\" tabindex=\"-1\" (mousedown)=\"initFilterBoxFocus(filterBox)\">\r\n <div tabindex=\"-1\">\r\n <tn-datetime-picker-range #dateRange [control]=\"filterSchema.dateRange\"\r\n (onChanged)=\"onChangeDateTime($event, col.field)\">\r\n </tn-datetime-picker-range>\r\n </div>\r\n <span\r\n [ngClass]=\"{'action-clear': true, 'dirty': filterData[col.field] && ((filterData[col.field][0] != null && filterData[col.field][0] !== '') || (filterData[col.field][1] != null && filterData[col.field][1] !== ''))}\"\r\n [pTooltip]=\"'B\u1ECF filter'\" tooltipPosition=\"top\"\r\n (mousedown)=\"onClearDateSearch(filterBox, dateRange, col.field)\" tabindex=\"-1\"><i\r\n class=\"pi pi-filter-slash\"></i></span>\r\n <after-view-checked style=\"display: none;\" (loaded)=\"initFilterBoxFocus(filterBox)\">\r\n </after-view-checked>\r\n </div>\r\n</ng-template>\r\n<ng-template #filterBoolean let-col=\"col\">\r\n <div class=\"filter-boolean-box\">\r\n <p-selectButton\r\n [options]=\"[{value: true, label: 'C\u00F3', icon: 'pi pi-check'}, {value: false, label: 'Kh\u00F4ng', icon: 'pi pi-times'}]\"\r\n [multiple]=\"true\" [(ngModel)]=\"filterData[col.field]\" (onChange)=\"onChangeBoolean($event, col.field)\">\r\n <ng-template let-item>\r\n <i style=\"padding: 3px 0;\" [class]=\"item.icon\"></i>\r\n </ng-template>\r\n </p-selectButton>\r\n </div>\r\n</ng-template>",
18448
+ template: "<div #container class=\"custom-card card card-w-title flex-container-fit-child\" [attr.height-type]=\"setting.heightType\"\r\n [ngStyle]=\"_style\">\r\n <div class=\"ui-helper-clearfix crud-list-header-area\">\r\n <div *ngIf=\"searchCustom\" class=\"p-grid ui-fluid custom-p-col custom-search-area\">\r\n <div class=\"p-col-12 main-container-search\">\r\n <div class=\"p-grid main-container-search-inner\">\r\n <ng-container>\r\n <ng-container *ngTemplateOutlet=\"searchCustom; context: {$implicit: this}\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n <div *ngIf=\"!setting.hiddenHeader\" class=\"p-grid ui-fluid custom-p-col page-title-area\">\r\n <div *ngIf=\"!setting.hiddenPageTitle\" class=\"main-title\">\r\n <h1 *ngIf=\"!hasTemplate('customTitle')\">\r\n {{setting.title != null ? setting.title : 'Danh s\u00E1ch ' + setting.objectName}}\r\n </h1>\r\n\r\n <ng-container *ngIf=\"hasTemplate('customTitle')\" [ngTemplateOutlet]=\"getTemplate('customTitle')\"\r\n [ngTemplateOutletContext]=\"{crudList: this}\">\r\n </ng-container>\r\n </div>\r\n\r\n <div *ngIf=\"!setting.hiddenPageSetting\" class=\"paginator-table\">\r\n <paging-next-back-only [model]=\"model\" [setting]=\"setting\" (onOldest)=\"onOldest($event)\"\r\n (onNext)=\"onNext($event)\" (onPrev)=\"onPrev($event)\" (onLatest)=\"onLatest($event)\"\r\n (onChangeLimitPage)=\"savePageSize()\">\r\n </paging-next-back-only>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"fit-content crud-list-body-area\">\r\n <div class=\"crud-list-body-area-inner\" style=\"overflow: unset;\">\r\n <div class=\"flex-container-fit-child\" style=\"overflow: unset;\">\r\n <div *ngIf=\"!setting.hiddenToolbar\" class=\"p-grid crudListToolbar\">\r\n <ng-container>\r\n <div *ngIf=\"!setting.hiddenButtons && hasTemplate('toolbar')\"\r\n [ngClass]=\"setting.hiddenAdvanceSearch ? 'p-md-12 p-lg-12' : 'p-md-7 p-lg-8'\"\r\n class=\"p-col-12 button-group function-topbar custom-toolbar\">\r\n <ng-container\r\n [ngTemplateOutletContext]=\"{selectedItems: model.selectedItems, crudList: this}\"\r\n [ngTemplateOutlet]=\"getTemplate('toolbar')\"></ng-container>\r\n </div>\r\n <div *ngIf=\"!setting.hiddenButtons && !hasTemplate('toolbar')\"\r\n [ngClass]=\"setting.hiddenAdvanceSearch ? 'p-md-12 p-lg-12' : 'p-md-7 p-lg-8'\"\r\n class=\"p-col-12 button-group function-topbar\">\r\n <button *ngIf=\"!hiddenAdd\" type=\"button\" pButton pRipple label=\"Th\u00EAm m\u1EDBi\" icon=\"pi pi-plus\"\r\n class=\"p-button-text\" [disabled]=\"!model.baseReady\" (click)=\"add()\"></button>\r\n <button *ngIf=\"setting.showExportSelectedItems && model.selectedItems.length > 0\"\r\n type=\"button\" pButton pRipple\r\n label=\"Xu\u1EA5t c\u00E1c m\u1EE5c \u0111\u00E3 ch\u1ECDn ({{model.selectedItems.length}})\" icon=\"fas fa-file-excel\"\r\n class=\"p-button-text p-button-success\" (click)=\"xuatCacMucDaChon()\"></button>\r\n <button *ngIf=\"!hiddenDelete && model.selectedItems.length > 0 && !disableMultipleDelete()\"\r\n type=\"button\" pButton pRipple\r\n label=\"{{ 'X\u00F3a' | translate }} ({{model.selectedItems.length}})\" icon=\"pi pi-trash\"\r\n class=\"p-button-text p-button-danger\" (click)=\"deleteMutiple()\"></button>\r\n <button\r\n *ngIf=\"!hiddenCopyLink && model.selectedItems.length > 0 && !disableMultipleCopyLink()\"\r\n label=\"Sao ch\u00E9p li\u00EAn k\u1EBFt\" type=\"button\" pButton pRipple\r\n pTooltip=\"{{'Sao ch\u00E9p li\u00EAn k\u1EBFt' | translate}}\" tooltipPosition=\"top\"\r\n class=\"p-button-rounded p-button-text p-button-info link-or-action\" icon=\"pi pi-link\"\r\n (click)=\"copyLinkMultiple()\"></button>\r\n <button *ngIf=\"!disableShare && model.selectedItems.length > 0\" label=\"Chia s\u1EBB li\u00EAn k\u1EBFt\"\r\n type=\"button\" pButton pRipple [pTooltip]=\"'Chia s\u1EBB li\u00EAn k\u1EBFt' | translate\"\r\n tooltipPosition=\"top\"\r\n class=\"p-button-rounded p-button-text p-button-info link-or-action\" icon=\"pi pi-link\"\r\n (click)=\"createShareLinkMultiple()\"></button>\r\n <ng-container [ngTemplateOutlet]=\"getTemplate('buttonAfterToolbar')\"\r\n [ngTemplateOutletContext]=\"{crudList: this}\"></ng-container>\r\n </div>\r\n </ng-container>\r\n <div *ngIf=\"!setting.hiddenAdvanceSearch\" class=\"p-col-12 advance-search-container\"\r\n [ngClass]=\"setting.hiddenButtons ? 'p-md-12 p-lg-12' : 'p-md-5 p-lg-4'\">\r\n <advance-search #advanceSearch [parentSetting]=\"setting\" [searchInfo]=\"searchInfo\"\r\n [loading]=\"model.loading\" (onSearch)=\"handleSearchAdvs($event)\"\r\n (onInit)=\"handleInitAdvanceSearch($event)\">\r\n </advance-search>\r\n </div>\r\n </div>\r\n <div *ngIf=\"hasTemplate('topGrid')\" class=\"extend-content-top-grid\">\r\n <ng-container [ngTemplateOutletContext]=\"{selectedItems: model.selectedItems, crudList: this}\"\r\n [ngTemplateOutlet]=\"getTemplate('topGrid')\"></ng-container>\r\n </div>\r\n <div class=\"container-table fit-content\" [class.--table-responsive]=\"responsive\">\r\n <div class=\"container-table-inner\">\r\n <ng-container *ngIf=\"!_groupField\">\r\n <tn-custom-scrollbar *ngIf=\"showScrollBar\" #scrollbar [config]=\"configScrollBar\"\r\n [showScrollHorizontal]=\"showScrollHorizontal\">\r\n <ng-container *ngTemplateOutlet=\"tableGetGroupFieldFalse\">\r\n </ng-container>\r\n <ng-container *ngIf=\"hasTemplate('afterCrudList')\">\r\n <ng-container [ngTemplateOutlet]=\"hasTemplate('afterCrudList')\"></ng-container>\r\n </ng-container>\r\n </tn-custom-scrollbar>\r\n <div *ngIf=\"!showScrollBar\">\r\n <ng-container *ngTemplateOutlet=\"tableGetGroupFieldFalse\">\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"_groupField\">\r\n <tn-custom-scrollbar *ngIf=\"showScrollBar\" #scrollbar [config]=\"configScrollBar\"\r\n [showScrollHorizontal]=\"showScrollHorizontal\">\r\n <ng-container *ngTemplateOutlet=\"tableGetGroupFieldTrue\">\r\n </ng-container>\r\n <ng-container *ngIf=\"hasTemplate('afterCrudList')\">\r\n <ng-container [ngTemplateOutlet]=\"getTemplate('afterCrudList')\"></ng-container>\r\n </ng-container>\r\n </tn-custom-scrollbar>\r\n <div *ngIf=\"!showScrollBar\">\r\n <ng-container *ngTemplateOutlet=\"tableGetGroupFieldTrue\">\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n\r\n <div class=\"table-border-line --top\"></div>\r\n <div class=\"table-border-line --right\"></div>\r\n <div class=\"table-border-line --bottom\"></div>\r\n <div class=\"table-border-line --left\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n<after-view-checked (loaded)=\"handleReady()\"></after-view-checked>\r\n<settings *ngIf=\"_showSettings && !setting.hiddenSetting\" [entityMetadataService]=\"entityMetadataService\"\r\n [parentContext]=\"context\" [parentSetting]=\"setting\" [parentModel]=\"model\" (onSave)=\"onSaveSettings($event)\"\r\n (onCancel)=\"_showSettings = false\">\r\n</settings>\r\n<settings-row *ngIf=\"_showSettingsRowColor && !setting.hiddenSetting\" [entityMetadataService]=\"entityMetadataService\"\r\n [parentContext]=\"context\" [parentSetting]=\"setting\" [parentModel]=\"model\" (onSave)=\"onSaveColorSettings($event)\"\r\n (onCancel)=\"_showSettingsRowColor = false\">\r\n</settings-row>\r\n<workflow-setting-dialog *ngIf=\"_showSettingsWorkflow && !setting.hiddenSettingWorkflow\" [parentSetting]=\"setting\"\r\n [parentContext]=\"context\" [parentModel]=\"model\" (onSaved)=\"onSaveWorkflowSettings($event)\"\r\n (onRemoved)=\"onRemoveWorkflowSettings($event)\" (onCancel)=\"_showSettingsWorkflow = false\"></workflow-setting-dialog>\r\n<tn-dialog *ngIf=\"workflowSettingModel.showEditForm\" [header]=\"'C\u1EA5u h\u00ECnh quy tr\u00ECnh nghi\u1EC7p v\u1EE5' | translate\"\r\n [popupSize]=\"workflowSettingModel.popupSize\" (onHide)=\"workflowSettingModel.showEditForm = false\">\r\n <workflow-setting-new #formBase [parentSetting]=\"setting\" (onSaved)=\"onSaveWorkflowSettingsNew($event)\"\r\n (onCancel)=\"workflowSettingModel.showEditForm = false\"></workflow-setting-new>\r\n</tn-dialog>\r\n<entity-permission *ngIf=\"_showSettingsPermission && !setting.hiddenSettingPermission\" [parentSetting]=\"setting\"\r\n [parentContext]=\"context\" [parentModel]=\"model\" [searchInfo]=\"searchInfo\"\r\n (onCancel)=\"_showSettingsPermission = false\">\r\n</entity-permission>\r\n<p-contextMenu #contextMenu [appendTo]=\"'body'\" [model]=\"buttonContexts\">\r\n</p-contextMenu>\r\n<tn-dialog *ngIf=\"showFormWorkflow\" #dialog [header]=\"headerWorkflow | translate\" [popupSize]=\"popupSizeWorkflow\"\r\n [scrollBarStyleClass]=\"'fit-content'\" (onHide)=\"showFormWorkflow = false\">\r\n <div style=\"height: 100%\">\r\n <simple-workflow-form #formBase [baseService]=\"setting.baseService\" [item]=\"currentItem\"\r\n [action]=\"actionWorkflow\" (onInvalidWorkflow)=\"handleInvalidWF($event)\" (onSaved)=\"handleProcessedWorflow()\"\r\n (onCancel)=\"showFormWorkflow = false\">\r\n </simple-workflow-form>\r\n </div>\r\n</tn-dialog>\r\n<tn-dialog *ngIf=\"processWorkflowModel.showEditForm\" #dialog [header]=\"processWorkflowModel.header | translate\"\r\n [popupSize]=\"processWorkflowModel.popupSize\" [scrollBarStyleClass]=\"'fit-content'\"\r\n (onHide)=\"processWorkflowModel.showEditForm = false\">\r\n <div style=\"height: 100%\">\r\n <process-workflow-form #formBase [businessSetting]=\"setting\" [item]=\"currentItem\"\r\n [workflow]=\"processWorkflowModel.data.workflow\" [action]=\"processWorkflowModel.data.action\"\r\n (onSaved)=\"handleProcessedWorkflowBase()\" (onCancel)=\"processWorkflowModel.showEditForm = false\">\r\n </process-workflow-form>\r\n </div>\r\n</tn-dialog>\r\n<tn-dialog *ngIf=\"choYKienModel.showEditForm\" #dialog [header]=\"choYKienModel.header | translate\"\r\n [popupSize]=\"choYKienModel.popupSize\" [scrollBarStyleClass]=\"'fit-content'\"\r\n (onHide)=\"choYKienModel.showEditForm = false\">\r\n <div style=\"height: 100%\">\r\n <cho-y-kien-form #formBase [bussinessSetting]=\"setting\" [rowItem]=\"choYKienModel.data.rowData\"\r\n (onSaved)=\"choYKienModel.showEditForm = false\" (onCancel)=\"choYKienModel.showEditForm = false\">\r\n </cho-y-kien-form>\r\n </div>\r\n</tn-dialog>\r\n<tn-dialog *ngIf=\"workflowHistoryModel.showEditForm\" #dialog [header]=\"workflowHistoryModel.header | translate\"\r\n [popupSize]=\"workflowHistoryModel.popupSize\" [scrollBarStyleClass]=\"'fit-content'\"\r\n (onHide)=\"workflowHistoryModel.showEditForm = false\">\r\n <div style=\"height: 100%\">\r\n <workflow-history-new #formBase [businessSetting]=\"setting\" [item]=\"currentItem\"\r\n [workflowSetting]=\"workflowHistoryModel.data.workflowSetting\"\r\n (onCancel)=\"workflowHistoryModel.showEditForm = false\">\r\n </workflow-history-new>\r\n </div>\r\n</tn-dialog>\r\n<tn-dialog *ngIf=\"permissionSharingModel.showEditForm\" #dialog [header]=\"permissionSharingModel.header | translate\"\r\n [popupSize]=\"permissionSharingModel.popupSize\" [scrollBarStyleClass]=\"'fit-content'\"\r\n (onHide)=\"permissionSharingModel.showEditForm = false\">\r\n <div style=\"height: 100%\">\r\n <permission-sharing #formBase [item]=\"rowDataCurrent\" [baseService]=\"setting.baseService\"\r\n (onCancel)=\"permissionSharingModel.showEditForm = false\">\r\n </permission-sharing>\r\n </div>\r\n</tn-dialog>\r\n<workflow-history-dialog *ngIf=\"showHistoryWorkflow\" [baseService]=\"setting.baseService\" [item]=\"currentItem\"\r\n [workflowSetting]=\"setting.workflowSetting\" (onHide)=\"handleHideHistoryWorkflow()\">\r\n</workflow-history-dialog>\r\n<tn-dialog *ngIf=\"startWorkflowModel.showEditForm\" #dialog [header]=\"startWorkflowModel.header | translate\"\r\n [popupSize]=\"startWorkflowModel.popupSize\" [scrollBarStyleClass]=\"'fit-content'\"\r\n (onHide)=\"startWorkflowModel.showEditForm = false\">\r\n <div style=\"height: 100%\">\r\n <start-workflow #formBase [workflows]=\"startWorkflowModel.data.workflows\"\r\n [defaultWorkflow]=\"startWorkflowModel.data.defaultWorkflow\"\r\n (onCancel)=\"startWorkflowModel.showEditForm = false\" (onSaved)=\"handleStartWorkflowFromDialog($event)\">\r\n </start-workflow>\r\n </div>\r\n</tn-dialog>\r\n<tn-dialog *ngIf=\"congViecModel.showEditForm\" #dialog [styleClass]=\"'congviec-form tn-form-dialog'\"\r\n [header]=\"congViecModel.header | translate\" [popupSize]=\"congViecModel.popupSize\"\r\n (onHide)=\"congViecModel.showEditForm = false\">\r\n <base-congviec-form #formBase [parentSetting]=\"congViecModel.data.congViecSetting\"\r\n [model]=\"congViecModel.data.model\" (onSaved)=\"congViecModel.showEditForm = false;getData()\"\r\n (onCancel)=\"congViecModel.showEditForm = false\">\r\n </base-congviec-form>\r\n</tn-dialog>\r\n<ng-template #tableGetGroupFieldFalse>\r\n <p-table #table [dataKey]=\"'id'\" [scrollable]=\"pTableScrollable\" [scrollHeight]=\"pTableScrollHeight\"\r\n [columns]=\"setting.cols\" [paginator]=\"false\" [value]=\"_dataSource\" (onSort)=\"onSort($event, table)\"\r\n [class]=\"_tableClass\" [responsive]=\"responsive\" [lazy]=\"lazy\" [loading]=\"model.loading\"\r\n [(selection)]=\"model.selectedItems\" (onRowReorder)=\"handleRowOrdered($event)\">\r\n <ng-template *ngIf=\"header\" pTemplate=\"header\" let-columns>\r\n <ng-container\r\n *ngTemplateOutlet=\"header, context: {$implicit: columns, crudList: this, rowHeaderFilter: rowHeaderFilter, contentTh: contentTh, containerSticky: containerSticky, funcCheckAll: handleCheckAll}\">\r\n </ng-container>\r\n </ng-template>\r\n <ng-template *ngIf=\"!header\" pTemplate=\"header\" let-columns>\r\n <ng-container *ngTemplateOutlet=\"trHeader; context: {$implicit: columns, funcCheckAll: handleCheckAll}\">\r\n </ng-container>\r\n </ng-template>\r\n <ng-template pTemplate=\"body\" let-rowData let-columns=\"columns\" let-index=\"rowIndex\" let-expanded=\"expanded\">\r\n <ng-container\r\n *ngTemplateOutlet=\"trBody; context: {$implicit: rowData, columns: columns, index: index, expanded: expanded, eventSelectRow: handleSelectRow, eventChecked: handleCheckRowData}\">\r\n </ng-container>\r\n <after-view-checked *ngIf=\"index == _dataSource.length - 1\" style=\"display: none;\" [renderKey]=\"_dataSource\"\r\n (loaded)=\"handleTableRendered()\">\r\n </after-view-checked>\r\n </ng-template>\r\n <ng-template *ngIf=\"rowExpansion\" pTemplate=\"rowexpansion\" let-rowData let-expanded=\"expanded\">\r\n <ng-container\r\n *ngTemplateOutlet=\"rowExpansion; context: {rowData: rowData, expanded: expanded, getColSpanGroup: getColSpanGroup}\">\r\n </ng-container>\r\n </ng-template>\r\n <ng-template *ngIf=\"summary\" pTemplate=\"summary\">\r\n <ng-container *ngTemplateOutlet=\"summary\"></ng-container>\r\n </ng-template>\r\n <ng-template *ngIf=\"footer\" pTemplate=\"footer\" let-columns>\r\n <ng-container *ngTemplateOutlet=\"footer; context: {$implicit: columns}\"></ng-container>\r\n </ng-template>\r\n <ng-template *ngIf=\"colgroup\" pTemplate=\"colgroup\" let-columns>\r\n <ng-container *ngTemplateOutlet=\"colgroup; context: {$implicit: columns}\"></ng-container>\r\n </ng-template>\r\n </p-table>\r\n</ng-template>\r\n<ng-template #tableGetGroupFieldTrue>\r\n <p-table #tableGroup [scrollable]=\"pTableScrollable\" [scrollHeight]=\"pTableScrollHeight\" [columns]=\"setting.cols\"\r\n [paginator]=\"false\" [value]=\"_dataSource\" [metaKeySelection]=\"false\" (onSort)=\"onSort($event, tableGroup)\"\r\n [class]=\"_tableClass\" [customSort]=\"true\" [responsive]=\"responsive\" [lazy]=\"true\" [loading]=\"model.loading\"\r\n [(selection)]=\"model.selectedItems\" [expandedRowKeys]=\"model.expandedRowKeys\" [dataKey]=\"_groupField\">\r\n <ng-template *ngIf=\"header\" pTemplate=\"header\" let-columns>\r\n <ng-container\r\n *ngTemplateOutlet=\"header, context: {$implicit: columns, crudList: this, rowHeaderFilter: rowHeaderFilter, contentTh: contentTh, containerSticky: containerSticky, funcCheckAll: handleCheckAll_Group}\">\r\n </ng-container>\r\n </ng-template>\r\n <ng-template *ngIf=\"!header\" pTemplate=\"header\" let-columns>\r\n <ng-container\r\n *ngTemplateOutlet=\"trHeader; context: {$implicit: columns, funcCheckAll: handleCheckAll_Group}\">\r\n </ng-container>\r\n </ng-template>\r\n <ng-template pTemplate=\"body\" let-rowData let-rowIndex=\"rowIndex\" let-expanded=\"expanded\" let-columns=\"columns\">\r\n <tr *ngIf=\"rowGroupMetadata[rowData[_groupField]] && rowGroupMetadata[rowData[_groupField]].index == rowIndex\"\r\n class=\"p-widget-header group-row\" style=\"border: 0px; border-bottom: 1px solid #eee\">\r\n <td *ngIf=\"!setting.hiddenCheckbox\" class=\"center chkbox\" [class.sticky]=\"setting.stickyColumn\">\r\n <p-checkbox [(ngModel)]=\"rowGroupChecked[rowData[_groupField]]\" binary=\"true\"\r\n (onChange)=\"handleCheckRowGroup(rowData)\">\r\n </p-checkbox>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </td>\r\n <ng-container *ngIf=\"!rowGroup\">\r\n <td [colSpan]=\"getColSpanGroup()\" [class]=\"_classRowGroup\">\r\n <div class=\"container-row-group\">\r\n <a href=\"javascript:;\" [pRowToggler]=\"rowData\" class=\"container-row-group-toggle\"\r\n [class.sticky]=\"setting.stickyColumn\">\r\n <i style=\"margin-right:5px\"\r\n [ngClass]=\"expanded ? 'fas fa-fw fa-caret-down' : 'fas fa-fw fa-caret-right'\"></i>\r\n <span class=\"content-row-group\">\r\n <ng-container *ngIf=\"!contentRowGroup\">\r\n <ng-container [ngTemplateOutlet]=\"_contentRowGroup\"\r\n [ngTemplateOutletContext]=\"getContextRowGroup(rowData)\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"contentRowGroup\">\r\n <ng-container [ngTemplateOutlet]=\"contentRowGroup\"\r\n [ngTemplateOutletContext]=\"getContextRowGroup(rowData)\">\r\n </ng-container>\r\n </ng-container>\r\n </span>\r\n </a>\r\n </div>\r\n </td>\r\n </ng-container>\r\n <ng-container *ngIf=\"rowGroup\">\r\n <ng-container [ngTemplateOutlet]=\"rowGroup\"\r\n [ngTemplateOutletContext]=\"getContextRowGroupRoot(rowData, expanded)\">\r\n </ng-container>\r\n </ng-container>\r\n </tr>\r\n </ng-template>\r\n <ng-template pTemplate=\"rowexpansion\" let-columns=\"columns\" let-rowData let-index=\"rowIndex\">\r\n <ng-container\r\n *ngTemplateOutlet=\"trBody; context: {$implicit: rowData, columns: columns, index: index, expanded: false, eventSelectRow: handleSelectRowGroup, eventChecked: handleCheckRowData_Group}\">\r\n </ng-container>\r\n <after-view-checked *ngIf=\"index == _dataSource.length - 1\" style=\"display: none;\" [renderKey]=\"_dataSource\"\r\n (loaded)=\"handleTableRendered()\">\r\n </after-view-checked>\r\n </ng-template>\r\n <ng-template *ngIf=\"summary\" pTemplate=\"summary\">\r\n <ng-container *ngTemplateOutlet=\"summary\"></ng-container>\r\n </ng-template>\r\n <ng-template *ngIf=\"footer\" pTemplate=\"footer\" let-columns>\r\n <ng-container *ngTemplateOutlet=\"footer; context: {$implicit: columns}\"></ng-container>\r\n </ng-template>\r\n <ng-template *ngIf=\"colgroup\" pTemplate=\"colgroup\" let-columns>\r\n <ng-container *ngTemplateOutlet=\"colgroup; context: {$implicit: columns}\"></ng-container>\r\n </ng-template>\r\n </p-table>\r\n <after-view-checked></after-view-checked>\r\n</ng-template>\r\n<ng-template #trHeader let-columns let-funcCheckAll=\"funcCheckAll\">\r\n <tr class=\"title-row\">\r\n <ng-container *ngIf=\"!setting.hiddenCheckbox\">\r\n <th [style.width]=\"widthCheckbox\" class=\"chkbox link-or-action cell-checkbox\"\r\n [class.sticky]=\"setting.stickyColumn\">\r\n <button *ngIf=\"!hasTemplate('headerCheckbox')\" type=\"button\" pButton pRipple icon=\"pi pi-refresh\"\r\n class=\"p-button-rounded p-button-text btnReload\" pTooltip=\"L\u00E0m m\u1EDBi d\u1EEF li\u1EC7u\" tooltipPosition=\"top\"\r\n [disabled]=\"model.loading\" (click)=\"reload()\"></button>\r\n <ng-container *ngIf=\"hasTemplate('headerCheckbox')\">\r\n <ng-container [ngTemplateOutletContext]=\"{crudList: this}\"\r\n [ngTemplateOutlet]=\"getTemplate('headerCheckbox')\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n </ng-container>\r\n <th *ngIf=\"!setting.hiddenOrderColumn\" [style.width]=\"widthOrderColumn\" class=\"stt nopad center\"\r\n [class.sticky]=\"setting.stickyColumn\">\r\n {{ 'TT' |translate}}\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n <th *ngIf=\"rowExpansion\" class=\"nopad row-expansion-toggle center\" style=\"width: 2.5rem\"\r\n [class.sticky]=\"setting.stickyColumn\">\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n <ng-container *ngFor=\"let col of columns; let i = index\">\r\n <th *ngIf=\"col && col.visible && col.field!='function'\" [ngStyle]=\"col.extendData.headerStyle\"\r\n [pTooltip]=\"col.fullLabel\" tooltipStyleClass=\"unset-width\" [class]=\"col.extendData.headerClass\"\r\n [class.first-th]=\"i==0\" [escape]=\"false\" tooltipPosition=\"top\" [tnSortableColumn]=\"col.field\">\r\n <ng-container *ngTemplateOutlet=\"contentTh; context: {$implicit: col}\"></ng-container>\r\n <ng-container *ngIf=\"col.sort || col.sortClient\">\r\n <ng-container *ngTemplateOutlet=\"sortIcon; context: {field: col.field}\"></ng-container>\r\n </ng-container>\r\n </th>\r\n </ng-container>\r\n <th *ngIf=\"enableReorderRow\" style=\"width: 30px\">\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n <ng-container *ngTemplateOutlet=\"colFunctionHeader\"></ng-container>\r\n </tr>\r\n <ng-container *ngTemplateOutlet=\"rowHeaderFilter; context: {columns: columns, funcCheckAll: funcCheckAll}\">\r\n </ng-container>\r\n</ng-template>\r\n<ng-template #rowHeaderFilter let-columns=\"columns\" let-funcCheckAll=\"funcCheckAll\">\r\n <tr class=\"filter-row\" *ngIf=\"!setting.hiddenFilterRow\">\r\n <th *ngIf=\"!setting.hiddenCheckbox\" class=\"chkbox nopad center\" [class.sticky]=\"setting.stickyColumn\"\r\n [class.tricheckbox-custom-false]=\"checkedAll === false\" [style.width]=\"widthCheckbox\">\r\n <p-triStateCheckbox [(ngModel)]=\"checkedAll\" binary=\"true\" (onChange)=\"funcCheckAll()\">\r\n </p-triStateCheckbox>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n <th *ngIf=\"!setting.hiddenOrderColumn\" class=\"stt center v-top\" [class.sticky]=\"setting.stickyColumn\">\r\n <div *ngIf=\"!setting.hiddenSetting\" class=\"pick-color-row\" pTooltip=\"C\u1EA5u h\u00ECnh hi\u1EC3n th\u1ECB m\u00E0u\"\r\n tooltipPosition=\"top\" (click)=\"showSettingRowColor()\">\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n </div>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n <th *ngIf=\"rowExpansion\" class=\"nopad center row-expansion-toggle\" [class.sticky]=\"setting.stickyColumn\">\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n <ng-container *ngFor=\"let col of columns; let i = index\">\r\n <th *ngIf=\"col.visible && col.field != 'function'\" class=\"cell-header-filter center\">\r\n <ng-container *ngIf=\"col.allowFilter\">\r\n <ng-container *ngIf=\"col.templateFilter\">\r\n <ng-container [ngTemplateOutlet]=\"col.templateFilter\"\r\n [ngTemplateOutletContext]=\"{col: col, filterData: filterData, onSearch: onSearch, onShowFilterDropdownPanel: onShowFilterDropdownPanel, onHideFilterDropdownPanel: onHideFilterDropdownPanel}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!col.templateFilter\" [ngSwitch]=\"col.controlType\">\r\n <ng-container *ngSwitchCase=\"'dropdown'\">\r\n <ng-container [ngTemplateOutlet]=\"filterDropdown\"\r\n [ngTemplateOutletContext]=\"{col: col.rawColumn}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'number'\">\r\n <ng-container [ngTemplateOutlet]=\"filterNumber\" [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'date'\">\r\n <ng-container [ngTemplateOutlet]=\"filterDate\" [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'datetime'\">\r\n <ng-container [ngTemplateOutlet]=\"filterDate\" [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchDefault>\r\n <ng-container [ngSwitch]=\"col.dataType\">\r\n <ng-container *ngSwitchCase=\"'int'\">\r\n <ng-container [ngTemplateOutlet]=\"filterNumber\"\r\n [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'decimal'\">\r\n <ng-container [ngTemplateOutlet]=\"filterNumber\"\r\n [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'date'\">\r\n <ng-container [ngTemplateOutlet]=\"filterDate\"\r\n [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'datetime'\">\r\n <ng-container [ngTemplateOutlet]=\"filterDate\"\r\n [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"'boolean'\">\r\n <ng-container [ngTemplateOutlet]=\"filterBoolean\"\r\n [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchDefault>\r\n <ng-container [ngTemplateOutlet]=\"filterText\"\r\n [ngTemplateOutletContext]=\"{col: col}\">\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n </ng-container>\r\n <th *ngIf=\"enableReorderRow\" style=\"width: 30px\">\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n <th *ngIf=\"!setting.hiddenFunctionColumn\" class=\"center setting-cell column-function\"\r\n [class.sticky]=\"setting.stickyColumn\">\r\n <button *ngIf=\"!setting.hiddenSetting\" type=\"button\" pButton pRipple icon=\"pi pi-cog\"\r\n class=\"p-button-rounded p-button-text\" pTooltip=\"C\u1EA5u h\u00ECnh hi\u1EC3n th\u1ECB\" tooltipPosition=\"top\"\r\n (click)=\"showSettings()\"></button>\r\n <button *ngIf=\"!setting.hiddenSettingPermission\" type=\"button\" pButton pRipple icon=\"pi pi-users\"\r\n class=\"p-button-rounded p-button-text\" pTooltip=\"Ph\u00E2n quy\u1EC1n d\u1EEF li\u1EC7u\" tooltipPosition=\"left\"\r\n (click)=\"showSettingsPermission()\"></button>\r\n <button *ngIf=\"!setting.hiddenSettingWorkflow\" type=\"button\" pButton pRipple icon=\"pi pi-sitemap\"\r\n class=\"p-button-rounded p-button-text\" pTooltip=\"C\u1EA5u h\u00ECnh quy tr\u00ECnh\" tooltipPosition=\"left\"\r\n (click)=\"showSettingsWorkflow()\"></button>\r\n <button *ngIf=\"!setting.hiddenSettingWorkflowNew\" type=\"button\" pButton pRipple icon=\"pi pi-sitemap\"\r\n class=\"p-button-rounded p-button-text\" pTooltip=\"C\u1EA5u h\u00ECnh quy tr\u00ECnh\" tooltipPosition=\"left\"\r\n (click)=\"showSettingsWorkflowNew()\"></button>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n </tr>\r\n</ng-template>\r\n<ng-template #colFunctionHeader>\r\n <ng-container *ngIf=\"!setting.hiddenFunctionColumn\">\r\n <th class=\"column-function\" [class.sticky]=\"setting.stickyColumn\"\r\n [style.width]=\"widthFunctionColumn || _widthFunctionColumn\">\r\n <div class=\"cell-header-function\">\r\n <span>{{'GRID.FUNCTION'| translate}}</span>\r\n </div>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </th>\r\n </ng-container>\r\n</ng-template>\r\n<ng-template #contentTh let-col>\r\n <ng-container *ngIf=\"templateHeaderContent[col.field]\">\r\n <ng-container *ngTemplateOutlet=\"templateHeaderContent[col.field]\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!templateHeaderContent[col.field]\">\r\n {{col.label}}\r\n </ng-container>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n</ng-template>\r\n<ng-template #trBody let-rowData let-columns=\"columns\" let-index=\"index\" let-expanded=\"expanded\"\r\n let-eventSelectRow=\"eventSelectRow\" let-eventChecked=\"eventChecked\">\r\n <tr [tnReorderableRow]=\"index\" [attr.rowIndex]=\"index\"\r\n [ngClass]=\"mergeClassObj(rowData, { 'ui-state-highlight': rowData._checked })\" [pTooltip]=\"rowData.tooltip\"\r\n tooltipPosition=\"top\" [tooltipStyleClass]=\"rowData.tooltipClass\" [escape]=\"escape\"\r\n (click)=\"eventSelectRow($event, rowData)\">\r\n <ng-container *ngIf=\"!setting.hiddenCheckbox\">\r\n <td [style.width]=\"widthCheckbox\" class=\"chkbox link-or-action cell-checkbox\"\r\n [class.sticky]=\"setting.stickyColumn\">\r\n <ng-container *ngIf=\"!hasTemplate('checkbox')\">\r\n <p-checkbox [(ngModel)]=\"rowData._checked\" binary=\"true\" (onChange)=\"eventChecked(rowData)\">\r\n </p-checkbox>\r\n </ng-container>\r\n <ng-container *ngIf=\"hasTemplate('checkbox')\">\r\n <ng-container [ngTemplateOutlet]=\"getTemplate('checkbox')\"\r\n [ngTemplateOutletContext]=\"{rowData: rowData, rowIndex: index}\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </td>\r\n </ng-container>\r\n <td *ngIf=\"!setting.hiddenOrderColumn && (!rowData.hidden || !rowData.hidden[fieldOrder])\"\r\n [style.width]=\"widthOrderColumn\" class=\"stt\" style=\"text-align: center;\"\r\n [class.sticky]=\"setting.stickyColumn\" [attr.colSpan]=\"rowData.colSpan && rowData.colSpan[fieldOrder]\"\r\n [attr.rowSpan]=\"rowData.rowSpan && rowData.rowSpan[fieldOrder]\">\r\n <span class=\"row-card\" [ngStyle]=\"getBookmarkColor(rowData, columns)\"></span>\r\n {{rowData[fieldOrder]}}\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </td>\r\n <td *ngIf=\"rowExpansion\" class=\"no-padding center row-expansion-toggle\" [class.sticky]=\"setting.stickyColumn\">\r\n <ng-container *ngTemplateOutlet=\"iconToggleRowData; context: {rowData: rowData, expanded: expanded}\">\r\n </ng-container>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </td>\r\n <ng-container\r\n *ngTemplateOutlet=\"dynamicColBodys; context: {$implicit: columns, rowData: rowData, index: index, expanded: expanded}\">\r\n </ng-container>\r\n <td *ngIf=\"enableReorderRow\" class=\"no-padding center\">\r\n <i class=\"fas fa-arrows-alt\" style=\"cursor:pointer; padding: 8px; color: #555;\" pReorderableRowHandle></i>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </td>\r\n <ng-container *ngIf=\"!setting.hiddenFunctionColumn\">\r\n <td class=\"text-center column-function\" style=\"text-align: center;\" [class.sticky]=\"setting.stickyColumn\">\r\n <div *ngIf=\"hasTemplate('function')\" class=\"p-toolbar-group-center button-group\">\r\n <ng-container [ngTemplateOutlet]=\"getTemplate('function')\"\r\n [ngTemplateOutletContext]=\"{rowData: rowData, rowIndex: index}\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </div>\r\n <div *ngIf=\"!hasTemplate('function')\" class=\"p-toolbar-group-center button-group\">\r\n <ng-container [ngTemplateOutletContext]=\"{rowData: rowData, rowIndex: index}\"\r\n [ngTemplateOutlet]=\"getTemplate('buttonBefore')\"></ng-container>\r\n <button *ngIf=\"setting.showVersionButton\" type=\"button\" pButton pRipple icon=\"pi pi-calendar\"\r\n class=\"p-button-rounded p-button-success link-or-action\" pTooltip=\"Xem l\u1ECBch s\u1EED phi\u00EAn b\u1EA3n\"\r\n tooltipPosition=\"top\" (click)=\"showListVersion(rowData)\"></button>\r\n <button *ngIf=\"!rowData.hiddenEdit\" type=\"button\" pButton pRipple [disabled]=\"disableEdit(rowData)\"\r\n pTooltip=\"{{'FORM.EDIT' | translate}}\" tooltipPosition=\"top\"\r\n class=\"p-button-rounded p-button-text p-button-info link-or-action\" icon=\"pi pi-pencil\"\r\n (click)=\"edit(rowData)\"></button>\r\n <button *ngIf=\"!rowData.hiddenDelete\" type=\"button\" pButton pRipple\r\n [disabled]=\"disableDelete(rowData)\" pTooltip=\"{{'FORM.DELETE' | translate}}\"\r\n tooltipPosition=\"top\" class=\"p-button-rounded p-button-text p-button-danger link-or-action\"\r\n icon=\"pi pi-trash\" (click)=\"delete(rowData)\"></button>\r\n <button *ngIf=\"!rowData.hiddenCopyLink\" type=\"button\" pButton pRipple\r\n [disabled]=\"disableCopyLink(rowData)\" pTooltip=\"{{'Sao ch\u00E9p li\u00EAn k\u1EBFt' | translate}}\"\r\n tooltipPosition=\"top\" class=\"p-button-rounded p-button-text p-button-info link-or-action\"\r\n icon=\"pi pi-link\" (click)=\"copyLink(rowData)\"></button>\r\n <button *ngIf=\"this.menuButtons\" type=\"button\" pButton icon=\"pi pi-ellipsis-v\"\r\n class=\"link-or-action p-button-text p-button-info p-button-rounded\" pTooltip=\"Ch\u1EE9c n\u0103ng kh\u00E1c\"\r\n tooltipPosition=\"top\" (click)=\"showContextMenu($event, rowData)\"></button>\r\n </div>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </td>\r\n </ng-container>\r\n </tr>\r\n</ng-template>\r\n<ng-template #dynamicColBodys let-columns let-rowData=\"rowData\" let-index=\"index\" let-expanded=\"expanded\">\r\n <ng-container *ngFor=\"let col of columns; let i = index\">\r\n <ng-container\r\n *ngTemplateOutlet=\"contentTd; context: {$implicit: rowData, col: col, index: index, i: i, expanded: expanded}\">\r\n </ng-container>\r\n </ng-container>\r\n</ng-template>\r\n<ng-template #contentTd let-rowData let-col=\"col\" let-index=\"index\" let-expanded=\"expanded\" let-i=\"i\">\r\n <td *ngIf=\"col && col.visible && col.field != 'function' && (!rowData.hidden || !rowData.hidden[col.field])\"\r\n [attr.colSpan]=\"rowData.colSpan && rowData.colSpan[col.field]\"\r\n [attr.rowSpan]=\"rowData.rowSpan && rowData.rowSpan[col.field]\" [ngStyle]=\"col.extendData.style\"\r\n [class]=\"col.cellClass\" [class.first-td]=\"i == 0\">\r\n <span *ngIf=\"col.pipe\">\r\n <span class=\"p-column-title\" [pTooltip]=\"col.fullLabel\" [escape]=\"false\"\r\n tooltipPosition=\"top\">{{col.label}}</span>\r\n {{rowData['pipe__' + col.field]}}\r\n </span>\r\n <span *ngIf=\"!col.pipe\">\r\n <span class=\"p-column-title\" [pTooltip]=\"col.fullLabel\" [escape]=\"false\"\r\n tooltipPosition=\"top\">{{col.label}}</span>\r\n <span *ngIf=\"setting.showEditLink && col.showEditLink\" [pTooltip]=\"config.tooltipView\" tooltipPosition=\"top\"\r\n class=\"link-or-action\">\r\n <a href=\"javascript:;\" (click)=\"view(rowData)\" [pTooltip]=\"config.tooltipView\" tooltipPosition=\"top\">\r\n <ng-container [ngTemplateOutlet]=\"contentCell\"\r\n [ngTemplateOutletContext]=\"getContextCell(rowData, index, col, expanded, this)\">\r\n </ng-container>\r\n </a>\r\n </span>\r\n <span *ngIf=\"!setting.showEditLink || !col.showEditLink\">\r\n <ng-container [ngTemplateOutlet]=\"contentCell\"\r\n [ngTemplateOutletContext]=\"getContextCell(rowData, index, col, expanded, this)\">\r\n </ng-container>\r\n </span>\r\n </span>\r\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\r\n </td>\r\n</ng-template>\r\n<ng-template #contentCell let-col=\"col\" let-rowData=\"rowData\" let-rowIndex=\"rowIndex\" let-field=\"field\"\r\n let-expanded=\"expanded\">\r\n <ng-container *ngIf=\"col.template\">\r\n <ng-container [ngTemplateOutlet]=\"col.template\"\r\n [ngTemplateOutletContext]=\"getContextCell(rowData, rowIndex, col, expanded,this)\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!col.template\">\r\n <ng-container [ngSwitch]=\"col.dataType\">\r\n <span *ngSwitchCase=\"'color'\" style=\"display:block;text-align:center;\">\r\n <div pTooltip=\"{{rowData[field]}}\" tooltipPosition=\"top\" [ngStyle]=\"{'background-color':rowData[field]}\"\r\n style=\"width:30px;height:30px;margin:0 auto;\"></div>\r\n </span>\r\n <span *ngSwitchCase=\"'icon'\" style=\"display:block;text-align:center;\">\r\n <i pTooltip=\"{{rowData[field]}}\" tooltipPosition=\"top\" style=\"text-align: center;\"\r\n [ngClass]=\"rowData[field]\"></i>\r\n </span>\r\n <span *ngSwitchCase=\"'date'\" pTooltip=\"{{rowData[field] | date:'dd/MM/yyyy'}}\" tooltipPosition=\"top\">\r\n {{_crudService.renderDate(rowData[field], col.format)}}\r\n </span>\r\n <span *ngSwitchCase=\"'datetime'\" pTooltip=\"{{rowData[field] | date:'dd/MM/yyyy HH:mm'}}\"\r\n tooltipPosition=\"top\">\r\n {{_crudService.renderDateTime(rowData[field], col.format)}}\r\n </span>\r\n <span *ngSwitchCase=\"'user'\" class=\"user\">\r\n {{rowData[field] | userFormat | async}}\r\n </span>\r\n <div *ngSwitchCase=\"'users'\" [innerHTML]=\"rowData[field] | usersFormat | async\">\r\n </div>\r\n <span *ngSwitchCase=\"'int'\">\r\n {{rowData[field]}}\r\n </span>\r\n <span *ngSwitchCase=\"'decimal'\">\r\n {{rowData[field]}}\r\n </span>\r\n <span *ngSwitchCase=\"'boolean'\">\r\n <p-checkbox class=\"boolean-data-type\" [(ngModel)]=\"rowData[field]\" binary=\"true\"\r\n [disabled]=\"col.disableCheckBox\">\r\n </p-checkbox>\r\n </span>\r\n <span *ngSwitchCase=\"'html'\">\r\n <div *ngIf=\"rowData[field]==null?'':rowData[field]\" [innerHTML]=\"rowData[field] | safeHtml\"></div>\r\n </span>\r\n <span *ngSwitchCase=\"'metadataStatus'\">\r\n <span *ngIf=\"rowData['rejectReason']\" class=\"label-danger\" [pTooltip]=\"rowData['rejectReason']\"\r\n tooltipStyleClass=\"unset-width\" [escape]=\"false\" tooltipPosition=\"top\">T\u1EEB ch\u1ED1i</span>\r\n <span *ngIf=\"rowData[field] == '0' && !rowData['rejectReason']\" class=\"label-secondary\">Ch\u01B0a\r\n duy\u1EC7t</span>\r\n <span *ngIf=\"rowData[field] == '1' && !rowData['rejectReason']\" class=\"label-warning\">Ch\u1EDD duy\u1EC7t</span>\r\n <span *ngIf=\"rowData[field] == '2'\" class=\"label-primary\">\u0110\u00E3 duy\u1EC7t</span>\r\n </span>\r\n <ng-container *ngSwitchCase=\"'string'\">\r\n <ng-container *ngTemplateOutlet=\"contentCellString; context: {$implicit: rowData, field: col.field}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchCase=\"null\">\r\n <ng-container *ngTemplateOutlet=\"contentCellString; context: {$implicit: rowData, field: col.field}\">\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngSwitchDefault>\r\n <ng-container [ngTemplateOutlet]=\"getComponentByType(col.dataType)\"\r\n [ngTemplateOutletContext]=\"getContextCell(rowData, rowIndex, col, expanded, this)\">\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</ng-template>\r\n<ng-template #contentCellString let-rowData let-field=\"field\">\r\n <span>\r\n <!-- __sv: Short Value -->\r\n <ng-container *ngIf=\"rowData[field + '__sv']\">\r\n <ng-container *ngIf=\"!rowData[field + '__showFull']\">\r\n {{rowData[field + '__sv']}}\r\n <span class=\"toggle-showfull\" (click)=\"toggleShowFull(rowData, field)\" pTooltip=\"B\u1EA5m \u0111\u1EC3 xem th\u00EAm\"\r\n tooltipPosition=\"top\">[...]</span>\r\n </ng-container>\r\n <ng-container *ngIf=\"rowData[field + '__showFull']\">\r\n {{rowData[field]}}\r\n <span class=\"toggle-showfull\" (click)=\"toggleShowFull(rowData, field)\">Thu g\u1ECDn</span>\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!rowData[field + '__sv']\">\r\n {{rowData[field]}}\r\n </ng-container>\r\n </span>\r\n</ng-template>\r\n<ng-template #iconToggleRowGroup let-rowData=\"rowData\" let-expanded=\"expanded\">\r\n <a href=\"javascript:;\" (click)=\"handleToggleRow(rowData, $event)\">\r\n <i style=\"margin-right:5px\" [ngClass]=\"expanded ? 'fas fa-fw fa-caret-down' : 'fas fa-fw fa-caret-right'\"></i>\r\n </a>\r\n</ng-template>\r\n<ng-template #iconToggleRowData let-rowData=\"rowData\" let-expanded=\"expanded\">\r\n <button type=\"button\" pButton pRipple class=\"link-or-action p-button-text p-button-rounded p-button-plain\"\r\n [icon]=\"expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'\"\r\n (click)=\"handleToggleRow(rowData, $event)\"></button>\r\n</ng-template>\r\n<ng-template #_contentRowGroup let-rowData=\"rowData\" let-groupCol=\"groupCol\" let-groupField=\"_groupField\">\r\n <ng-container [ngTemplateOutlet]=\"contentCell\"\r\n [ngTemplateOutletContext]=\"{rowData: rowData, col: groupCol, field: _groupField}\">\r\n </ng-container>\r\n <span> ({{rowGroupMetadata[rowData[_groupField]].size}})</span>\r\n</ng-template>\r\n<ng-template #entityWorkflowStatus let-rowData=\"rowData\">\r\n <div class=\"container-text-workflow\">\r\n <span class=\"content\">{{rowData.statusString ? rowData.statusString : rowData.strcurrentStateCode}}</span>\r\n <button *ngIf=\"!rowData.hiddenWorkflowAction\" type=\"button\" pButton icon=\"pi pi-ellipsis-v\"\r\n class=\"link-or-action p-button-text p-button-rounded\" pTooltip=\"H\u00E0nh \u0111\u1ED9ng\" tooltipPosition=\"top\"\r\n (click)=\"showActionWorkflow($event, rowData)\"></button>\r\n </div>\r\n</ng-template>\r\n<ng-template #trangThaiV5 let-rowData=\"rowData\">\r\n <div class=\"container-text-workflow\">\r\n <button *ngIf=\"!rowData.__workflowCode\" pButton class=\"p-button-text link-or-action\" label=\"B\u1EAFt \u0111\u1EA7u\"\r\n style=\"border: 1px solid #7ca9cd;\" pTooltip=\"B\u1EAFt \u0111\u1EA7u ch\u1EA1y quy tr\u00ECnh\" tooltipPosition=\"top\"\r\n (click)=\"showFormStartWorkflow(rowData)\"></button>\r\n <ng-container *ngIf=\"rowData.__workflowCode\">\r\n <span class=\"content\">{{rowData.__textTrangThai}}</span>\r\n <button *ngIf=\"!rowData.hiddenWorkflowAction\" type=\"button\" pButton icon=\"pi pi-ellipsis-v\"\r\n class=\"link-or-action p-button-text p-button-rounded\" pTooltip=\"H\u00E0nh \u0111\u1ED9ng\" tooltipPosition=\"top\"\r\n [disabled]=\"showingActionWorkflow\" (click)=\"showActionWorkflowNew($event, rowData)\"></button>\r\n </ng-container>\r\n </div>\r\n</ng-template>\r\n<ng-template #viewHistory let-rowData=\"rowData\">\r\n <button pButton icon=\"pi pi-calendar\" class=\"p-button-text p-button-rounded link-or-action\" pTooltip=\"Xem l\u1ECBch s\u1EED\"\r\n tooltipPosition=\"top\" (click)=\"viewHistoryWorkflowNew(rowData)\"></button>\r\n</ng-template>\r\n<ng-template #workflowCoreStatus let-rowData=\"rowData\">\r\n <div class=\"container-text-workflow\">\r\n <a class=\"content\" (click)=\"goToTask($event)\" href=\"javascript:;\">{{rowData.strworkflowCoreStatus}}</a>\r\n </div>\r\n</ng-template>\r\n<ng-template #containerSticky>\r\n <span class=\"fix-sticky top\"></span>\r\n <span class=\"fix-sticky right\"></span>\r\n <!-- <span class=\"fix-sticky bottom\"></span> -->\r\n <span class=\"fix-sticky left\"></span>\r\n</ng-template>\r\n<ng-template #sortIcon let-field=\"field\">\r\n <i class=\"p-sortable-column-icon pi\" style=\"font-size: 0.8em;\"\r\n [ngClass]=\"{'pi-sort-amount-up-alt': field == _sortField && _sortDir === 1, 'pi-sort-amount-down': field == _sortField && _sortDir === -1, 'pi-sort-alt': field != _sortField || _sortDir === 0}\"></i>\r\n</ng-template>\r\n<ng-template #filterDropdown let-col=\"col\">\r\n <div #filterBox style=\"width: 100%; border-radius: 4px;\">\r\n <dropdown *ngIf=\"col && filterSchema.dropdown[col.field]\" [control]=\"filterSchema.dropdown[col.field]\"\r\n [dataSource]=\"filterSchema.dropdown[col.field].dataSource\" [(value)]=\"filterData[col.field]\"\r\n (onHideSmartEvent)=\"onSearch()\" (onShow)=\"onShowFilterDropdownPanel($event)\"\r\n (onHide)=\"onHideFilterDropdownPanel($event)\" (mousedown)=\"initFilterBoxFocus(filterBox)\"></dropdown>\r\n </div>\r\n</ng-template>\r\n<ng-template #filterText let-col=\"col\">\r\n <div #filterBox class=\"text-filter filter-box\" tabindex=\"-1\" (mousedown)=\"initFilterBoxFocus(filterBox)\">\r\n <div tabindex=\"-1\">\r\n <input pInputText type=\"text\" class=\"input-search\" [placeholder]=\"col.label\"\r\n [(ngModel)]=\"filterData[col.field]\" (change)=\"onSearch()\"\r\n (keyup.esc)=\"onClearSearch(filterBox, col.field)\">\r\n </div>\r\n <span [ngClass]=\"{'action-clear': true, 'dirty': filterData[col.field] != null && filterData[col.field] !== ''}\"\r\n [pTooltip]=\"'B\u1ECF filter'\" tooltipPosition=\"top\" (mousedown)=\"onClearSearch(filterBox, col.field)\"\r\n tabindex=\"-1\"><i class=\"pi pi-filter-slash\"></i></span>\r\n <after-view-checked style=\"display: none;\" (loaded)=\"initFilterBoxFocus(filterBox)\">\r\n </after-view-checked>\r\n </div>\r\n</ng-template>\r\n<ng-template #filterNumber let-col=\"col\">\r\n <div #filterBox class=\"number-picker-range filter-box\" tabindex=\"-1\" (mousedown)=\"initFilterBoxFocus(filterBox)\">\r\n <div tabindex=\"-1\">\r\n <tn-number-picker-range #numberRange [maskType]=\"col.dataType\" [(ngModel)]=\"filterData[col.field]\"\r\n [min]=\"col.min\" [max]=\"col.max\" (change)=\"onSearch()\">\r\n </tn-number-picker-range>\r\n </div>\r\n <span\r\n [ngClass]=\"{'action-clear': true, 'dirty': filterData[col.field] && ((filterData[col.field][0] != null && filterData[col.field][0] !== '') || (filterData[col.field][1] != null && filterData[col.field][1] !== ''))}\"\r\n [pTooltip]=\"'B\u1ECF filter'\" tooltipPosition=\"top\" (mousedown)=\"onClearNumberSearch(filterBox, numberRange)\"\r\n tabindex=\"-1\">\r\n <i class=\"pi pi-filter-slash\"></i></span>\r\n <after-view-checked style=\"display: none;\" (loaded)=\"initFilterBoxFocus(filterBox)\">\r\n </after-view-checked>\r\n </div>\r\n</ng-template>\r\n<ng-template #filterDate let-col=\"col\">\r\n <div #filterBox class=\"date-picker-range filter-box\" tabindex=\"-1\" (mousedown)=\"initFilterBoxFocus(filterBox)\">\r\n <div tabindex=\"-1\">\r\n <tn-datetime-picker-range #dateRange [control]=\"filterSchema.dateRange\"\r\n (onChanged)=\"onChangeDateTime($event, col.field)\">\r\n </tn-datetime-picker-range>\r\n </div>\r\n <span\r\n [ngClass]=\"{'action-clear': true, 'dirty': filterData[col.field] && ((filterData[col.field][0] != null && filterData[col.field][0] !== '') || (filterData[col.field][1] != null && filterData[col.field][1] !== ''))}\"\r\n [pTooltip]=\"'B\u1ECF filter'\" tooltipPosition=\"top\"\r\n (mousedown)=\"onClearDateSearch(filterBox, dateRange, col.field)\" tabindex=\"-1\"><i\r\n class=\"pi pi-filter-slash\"></i></span>\r\n <after-view-checked style=\"display: none;\" (loaded)=\"initFilterBoxFocus(filterBox)\">\r\n </after-view-checked>\r\n </div>\r\n</ng-template>\r\n<ng-template #filterBoolean let-col=\"col\">\r\n <div class=\"filter-boolean-box\">\r\n <p-selectButton\r\n [options]=\"[{value: true, label: 'C\u00F3', icon: 'pi pi-check'}, {value: false, label: 'Kh\u00F4ng', icon: 'pi pi-times'}]\"\r\n [multiple]=\"true\" [(ngModel)]=\"filterData[col.field]\" (onChange)=\"onChangeBoolean($event, col.field)\">\r\n <ng-template let-item>\r\n <i style=\"padding: 3px 0;\" [class]=\"item.icon\"></i>\r\n </ng-template>\r\n </p-selectButton>\r\n </div>\r\n</ng-template>",
18346
18449
  providers: [DecimalPipe, DatePipe],
18347
18450
  styles: [".container-table{display:flex;flex-direction:column;overflow:hidden}.container-table .container-table-inner{display:flex;height:auto;max-height:100%;min-height:60px;position:relative}.container-table-inner>tn-custom-scrollbar{width:100%}.cell-checkbox{text-align:center}.pick-color-row{border:1px solid #d1d1d1;border-radius:2px;bottom:0;cursor:pointer;display:flex;flex-wrap:wrap;height:1.4em;left:0;margin:auto;position:absolute;right:0;top:0;width:1.4em}.pick-color-row>div{background:#84d140;border:1px solid #fff;flex:0 0 50%}.pick-color-row>div:nth-child(2){background:#fc6868}.pick-color-row>div:nth-child(3){background:#fbc02d}.pick-color-row>div:nth-child(4){background:#7dc5ff}.cell-header-function{align-items:center;display:flex}.cell-header-function>span{flex:1 1;text-align:center}.cell-header-function button{height:24px;margin:0;padding:0;width:24px}.group-icon{color:#256aa2;font-weight:400}.group-icon i{font-size:.8em;margin-right:5px}.center{text-align:center!important}.row-card{height:100%;left:0;position:absolute;top:0;width:5px}.column-function{min-width:80px;padding:0}.custom-search-area{background-color:#f2f2f2;margin:-.5em -1em .5em;padding-left:.5em;padding-right:.5em}.main-container-search-inner{margin-bottom:-.5em}.main-title>h1{font-size:1.2em}.filter-row>th:not(.sticky):not(.chkbox){padding:3px!important}.container-text-workflow{align-items:center;display:flex;justify-content:center}.container-text-workflow .link-or-action{color:#2196f3;cursor:pointer}.container-text-workflow .content{flex:1 1}.btnReload{height:2rem;left:50%;position:absolute;top:50%;transform:translate(-50%,calc(-50% - 1px));width:2rem}.toggle-showfull{color:#00f;cursor:pointer;font-size:.8rem;font-weight:700;white-space:nowrap}::ng-deep crud-list .advance-search-container{display:flex;justify-content:flex-end}::ng-deep crud-list advance-search{display:block;flex:1;max-width:400px}::ng-deep crud-list .ps__rail-x,::ng-deep crud-list .ps__rail-y{z-index:5}::ng-deep crud-list .p-datatable .p-datatable-thead>tr>th.cell-fixed-filter{z-index:999}::ng-deep crud-list .p-datatable .p-datatable-thead>tr>th.cell-fixed-filter .fixed-filter{min-width:200px;position:fixed;z-index:10}::ng-deep crud-list .p-datatable .p-datatable-thead>tr>th .container-icon-loading{left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}::ng-deep crud-list .check-all-custom{height:0;position:absolute;width:0}::ng-deep crud-list .cell-header-filter{position:relative}::ng-deep crud-list .cell-header-filter .tn-dropdown{height:32px}::ng-deep crud-list .cell-header-filter tn-mask .p-inputtext{width:100%}::ng-deep crud-list .cell-header-filter .filter-box{background-color:#fff;border-radius:3px;display:flex;min-width:0}::ng-deep crud-list .cell-header-filter .filter-box>div{border:1px solid #ced4da;border-radius:3px 0 0 3px;border-right:none;flex:1;outline:none;overflow:hidden}::ng-deep crud-list .cell-header-filter .filter-box>span{align-items:center;background:#f5f6f8;border:1px solid #ced4da;color:#6c757d;cursor:pointer;display:inline-flex;flex-basis:32px;height:32px;justify-content:center;min-width:unset;outline:none}::ng-deep crud-list .cell-header-filter .filter-box>span.action-clear{border-radius:0 3px 3px 0}::ng-deep crud-list .cell-header-filter .filter-box>span.action-clear.dirty{color:#008eff}::ng-deep crud-list .cell-header-filter .filter-box input{border:none;box-shadow:none!important;padding-left:5px;padding-right:5px}::ng-deep crud-list .cell-header-filter .filter-box:not(.no-transition){transition:min-width .1s}::ng-deep crud-list .cell-header-filter .filter-box.boolean-filter>div{flex:0 0 109px;width:109px}::ng-deep crud-list .cell-header-filter .p-multiselect-label.p-placeholder{padding-left:.5rem;padding-right:.5rem}::ng-deep crud-list .cell-header-filter.focus-within,::ng-deep crud-list .cell-header-filter:focus-within{z-index:10!important}::ng-deep crud-list .cell-header-filter.focus-within .filter-boolean-box .p-button,::ng-deep crud-list .cell-header-filter:focus-within .filter-boolean-box .p-button{z-index:10}::ng-deep crud-list .cell-header-filter.focus-within .filter-box>div,::ng-deep crud-list .cell-header-filter:focus-within .filter-box>div{border-color:#2196f3;box-shadow:0 0 0 .2rem #a6d5fa;z-index:0}::ng-deep crud-list .cell-header-filter.focus-within .short-filter-box,::ng-deep crud-list .cell-header-filter:focus-within .short-filter-box{box-shadow:5px 0 15px 1px rgba(0,0,0,.27058823529411763);min-width:250px;position:absolute;top:calc(50% - 16px);z-index:2}::ng-deep crud-list .cell-header-filter.focus-within .short-filter-box>div,::ng-deep crud-list .cell-header-filter:focus-within .short-filter-box>div{border-color:#2196f3;box-shadow:0 0 0 .2rem #a6d5fa;flex:1;z-index:0}::ng-deep crud-list .cell-header-filter.focus-within .short-filter-box>span.action-clear,::ng-deep crud-list .cell-header-filter:focus-within .short-filter-box>span.action-clear{display:flex}::ng-deep crud-list .cell-header-filter.focus-within .short-filter-box.boolean-filter,::ng-deep crud-list .cell-header-filter:focus-within .short-filter-box.boolean-filter{min-width:140px}::ng-deep crud-list .cell-header-filter.focus-within .short-filter-box.boolean-filter>div,::ng-deep crud-list .cell-header-filter:focus-within .short-filter-box.boolean-filter>div{flex:0 0 109px;width:109px}::ng-deep crud-list .cell-header-filter.focus-within:nth-last-child(2) .short-filter-box,::ng-deep crud-list .cell-header-filter:focus-within:nth-last-child(2) .short-filter-box{left:50%;transform:translateX(-50%)}::ng-deep crud-list .cell-header-filter:last-child .filter-box{right:3px}::ng-deep crud-list .table-border-line{background-color:#eee;position:absolute;z-index:5}::ng-deep crud-list .table-border-line.--left,::ng-deep crud-list .table-border-line.--right{bottom:0;top:0;width:1px}::ng-deep crud-list .table-border-line.--bottom,::ng-deep crud-list .table-border-line.--top{height:1px;left:0;right:0}::ng-deep crud-list .table-border-line.--left{left:0}::ng-deep crud-list .table-border-line.--right{right:0}::ng-deep crud-list .table-border-line.--top{top:0}::ng-deep crud-list .table-border-line.--bottom{bottom:0}::ng-deep crud-list .filter-boolean-box{text-align:center}::ng-deep crud-list .filter-boolean-box .p-selectbutton{white-space:nowrap}::ng-deep crud-list .custom-search-area crud-form{width:100%}::ng-deep crud-list>p-contextmenu{display:none}@media (max-width:640px){::ng-deep crud-list .--table-responsive .p-datatable-wrapper{padding:1px}}"]
18348
18451
  },] }
@@ -18407,6 +18510,7 @@ CrudListComponent.propDecorators = {
18407
18510
  templatesFromParent: [{ type: Input }],
18408
18511
  childrenFromParent: [{ type: Input }],
18409
18512
  menuButtons: [{ type: Input }],
18513
+ disableShare: [{ type: Input }],
18410
18514
  fieldOrder: [{ type: Input }],
18411
18515
  style: [{ type: Input }],
18412
18516
  tableClass: [{ type: Input }],
@@ -18629,15 +18733,19 @@ class DataListBase extends ComponentBase {
18629
18733
  }
18630
18734
  this.checkAllowTrinhKy = this.checkAllowTrinhKy.bind(this);
18631
18735
  this.setting.checkAllowTrinhKy = this.checkAllowTrinhKy;
18736
+ this.setting.getItemState = this.getItemState;
18737
+ this.getItemState = this.getItemState.bind(this);
18632
18738
  this.getMenuButtons = this.getMenuButtons.bind(this);
18633
18739
  this.loadItemFromQueryParam();
18634
18740
  }
18635
18741
  loadItemFromQueryParam() {
18636
18742
  if (this.loadDetailFromQueryParam === undefined || this.loadDetailFromQueryParam === true) {
18637
18743
  let idInQueryString = null;
18744
+ let pid = null; // permission Id được người khác share
18638
18745
  if (this._activatedRoute.snapshot
18639
18746
  && this._activatedRoute.snapshot.queryParams) {
18640
18747
  idInQueryString = this._activatedRoute.snapshot.queryParams.id;
18748
+ pid = this._activatedRoute.snapshot.queryParams.pid;
18641
18749
  }
18642
18750
  if (idInQueryString) {
18643
18751
  // get detail data
@@ -18658,8 +18766,30 @@ class DataListBase extends ComponentBase {
18658
18766
  this._notifierService.showWarning('Không tìm thấy bản ghi cần xem chi tiết');
18659
18767
  });
18660
18768
  }
18769
+ else if (pid) {
18770
+ this.loadDetailPid(pid);
18771
+ }
18661
18772
  }
18662
18773
  }
18774
+ loadDetailPid(pid) {
18775
+ this.setting.baseService.getDetailByPid(pid)
18776
+ .then(res => this.handleResponse(res, '', f => {
18777
+ if (!res.data) {
18778
+ this._notifierService.showWarning('Không tìm thấy bản ghi cần xem chi tiết');
18779
+ }
18780
+ if ((res.data.basePermission & PermissionBase.EDIT) == PermissionBase.EDIT
18781
+ || (res.data.basePermission & PermissionBase.READ) == PermissionBase.READ) {
18782
+ res.data.pid = pid;
18783
+ this._edit(res.data);
18784
+ }
18785
+ else {
18786
+ this._notifierService.showWarning('Bạn không có quyền xem bản ghi');
18787
+ }
18788
+ })).catch(err => {
18789
+ console.error('error on get detail from querystring', err);
18790
+ this._notifierService.showWarning('Không tìm thấy bản ghi cần xem chi tiết');
18791
+ });
18792
+ }
18663
18793
  ngAfterViewInit() {
18664
18794
  this.handleAfterViewInit();
18665
18795
  }
@@ -18850,6 +18980,15 @@ class DataListBase extends ComponentBase {
18850
18980
  this.crudList.buildFilterColumn([colForAdmin]);
18851
18981
  }
18852
18982
  }
18983
+ getItemState(lstRowData) {
18984
+ return __awaiter(this, void 0, void 0, function* () {
18985
+ const result = {};
18986
+ lstRowData.forEach(item => {
18987
+ result[item.id] = {};
18988
+ });
18989
+ return result;
18990
+ });
18991
+ }
18853
18992
  checkAllowTrinhKy(rowData) {
18854
18993
  return __awaiter(this, void 0, void 0, function* () {
18855
18994
  return true;
@@ -18981,6 +19120,7 @@ class DataListBase extends ComponentBase {
18981
19120
  }
18982
19121
  cloneData(rowData) {
18983
19122
  return {
19123
+ pid: rowData.pid,
18984
19124
  id: rowData[this.setting.entityKey]
18985
19125
  };
18986
19126
  }
@@ -19008,7 +19148,7 @@ class DataListBase extends ComponentBase {
19008
19148
  this._notifierService.showDeleteDataSuccess();
19009
19149
  }
19010
19150
  else {
19011
- this._notifierService.showWarningByReponse(response);
19151
+ this._notifierService.showWarningByResponse(response);
19012
19152
  }
19013
19153
  }, error => {
19014
19154
  this._notifierService.showDeleteDataError();
@@ -19032,7 +19172,7 @@ class DataListBase extends ComponentBase {
19032
19172
  this._notifierService.showDeleteDataSuccess();
19033
19173
  }
19034
19174
  else {
19035
- this._notifierService.showWarningByReponse(response);
19175
+ this._notifierService.showWarningByResponse(response);
19036
19176
  }
19037
19177
  });
19038
19178
  }
@@ -19244,7 +19384,7 @@ class DataListBase extends ComponentBase {
19244
19384
  const dataStatus = (yield this._workflowPermissionDetailService.getAll([
19245
19385
  this.newFilter('itemId', Operator.in, dataSource.map(q => q.id)),
19246
19386
  this.newFilter('userId', Operator.equal, userIdCurrent)
19247
- ], 'itemId,userId,trangThai,textTrangThai,workflowCode,allowEdit,permission')).data;
19387
+ ], 'itemId,userId,trangThai,textTrangThai,workflowCode,permission')).data;
19248
19388
  if (dataStatus == null) {
19249
19389
  return this._notifierService.showWarning('Không lấy được thông tin trạng thái hiện tại của bản ghi');
19250
19390
  }
@@ -19257,7 +19397,7 @@ class DataListBase extends ComponentBase {
19257
19397
  };
19258
19398
  }
19259
19399
  else {
19260
- itemStatus = lstItemStatus.find(q => q.allowEdit);
19400
+ itemStatus = lstItemStatus.find(q => (q.permission & PermissionBase.EDIT) == PermissionBase.EDIT);
19261
19401
  if (itemStatus == null) {
19262
19402
  itemStatus = lstItemStatus[0];
19263
19403
  }
@@ -19265,7 +19405,6 @@ class DataListBase extends ComponentBase {
19265
19405
  rowItem.__trangThai = itemStatus.trangThai;
19266
19406
  rowItem.__textTrangThai = itemStatus.textTrangThai;
19267
19407
  rowItem.__workflowCode = itemStatus.workflowCode;
19268
- rowItem.__allowEdit = itemStatus.allowEdit;
19269
19408
  rowItem.__permission = itemStatus.permission;
19270
19409
  rowItem.__disableEdit = true;
19271
19410
  rowItem.__disableDelete = true;
@@ -28880,6 +29019,8 @@ class FileManagerComponent extends DataListBase {
28880
29019
  },
28881
29020
  breadcrumbs: []
28882
29021
  };
29022
+ this.showAttachLinkBox = false;
29023
+ this.typedLink = '';
28883
29024
  this._moduleConfig = this._moduleConfigService.getConfig();
28884
29025
  this.apiUploadUrl = this._fileObjectService.getUploadUrl();
28885
29026
  this.userId = this._userService.getUserIdCombine();
@@ -29122,30 +29263,35 @@ class FileManagerComponent extends DataListBase {
29122
29263
  visible: this._deviceDetectorService.isDesktop()
29123
29264
  },
29124
29265
  {
29125
- label: 'Xem các phiên bản khác', icon: 'fas fa-history', command: () => {
29126
- this.openFileVersions(item);
29127
- }
29266
+ label: ' số', icon: 'fas fa-signature', command: () => {
29267
+ this.signFile(item);
29268
+ },
29269
+ visible: !this.readonly
29128
29270
  },
29129
29271
  {
29130
- label: 'Tải về bản công khai', icon: 'fas fa-download', command: () => {
29272
+ label: 'Tải về', icon: 'fas fa-download', command: () => {
29131
29273
  this.download(item);
29132
29274
  }
29133
29275
  },
29134
29276
  {
29135
- label: ' số', icon: 'fas fa-signature', command: () => {
29136
- this.signFile(item);
29137
- },
29138
- visible: !this.readonly
29277
+ label: 'Sao chép đường dẫn', icon: 'fas fa-link', command: () => {
29278
+ this.copyDownloadLink(item);
29279
+ }
29139
29280
  },
29140
29281
  {
29141
- label: 'Xóa tệp tin', icon: 'far fa-trash-alt', command: () => {
29142
- this.deleteFile(item);
29282
+ label: 'Đổi tên', icon: 'fas fa-eraser', command: () => {
29283
+ this.renameFile(item);
29143
29284
  },
29144
29285
  visible: !this.readonly
29145
29286
  },
29146
29287
  {
29147
- label: 'Đổi tên', icon: 'fas fa-eraser', command: () => {
29148
- this.renameFile(item);
29288
+ label: 'Xem các phiên bản khác', icon: 'fas fa-history', command: () => {
29289
+ this.openFileVersions(item);
29290
+ }
29291
+ },
29292
+ {
29293
+ label: 'Xóa tệp tin', icon: 'far fa-trash-alt', command: () => {
29294
+ this.deleteFile(item);
29149
29295
  },
29150
29296
  visible: !this.readonly
29151
29297
  }
@@ -29375,7 +29521,7 @@ class FileManagerComponent extends DataListBase {
29375
29521
  this._notifierService.showDeleteDataSuccess();
29376
29522
  }
29377
29523
  else {
29378
- this._notifierService.showWarningByReponse(response);
29524
+ this._notifierService.showWarningByResponse(response);
29379
29525
  }
29380
29526
  });
29381
29527
  });
@@ -29387,6 +29533,24 @@ class FileManagerComponent extends DataListBase {
29387
29533
  this._downloadLinkService.download(model);
29388
29534
  });
29389
29535
  }
29536
+ copyDownloadLink(explorerItem) {
29537
+ return __awaiter(this, void 0, void 0, function* () {
29538
+ const model = this._downloadLinkService.getGenerateDownloadLinkModel(explorerItem);
29539
+ this._downloadLinkService.generateDownloadLink(model)
29540
+ .then(rs => {
29541
+ if (rs.success) {
29542
+ this._commonService.copyMessage(this._downloadLinkService.getAnonymousDownloadUrl(rs.data));
29543
+ this._notifierService.showSuccess('Đã sao chép vào bộ nhớ tạm. Đường dẫn này sẽ hết hạn sau 60 giây!');
29544
+ }
29545
+ else {
29546
+ this._notifierService.showWarning('Không thể sao chép liên kết tải tệp tin!');
29547
+ }
29548
+ })
29549
+ .catch(err => {
29550
+ this._notifierService.showWarning('Không thể sao chép liên kết tải tệp tin!');
29551
+ });
29552
+ });
29553
+ }
29390
29554
  // Tải nhiều thư mục/ tệp.
29391
29555
  downloadMultiple() {
29392
29556
  return __awaiter(this, void 0, void 0, function* () {
@@ -29463,7 +29627,7 @@ class FileManagerComponent extends DataListBase {
29463
29627
  this.data.moving = {};
29464
29628
  }
29465
29629
  else {
29466
- this._notifierService.showWarningByReponse(response);
29630
+ this._notifierService.showWarningByResponse(response);
29467
29631
  }
29468
29632
  });
29469
29633
  }
@@ -29622,12 +29786,40 @@ class FileManagerComponent extends DataListBase {
29622
29786
  onRowSelect(evt) {
29623
29787
  this.onSelected.emit(this.model.selectedItems);
29624
29788
  }
29789
+ addAttachLink() {
29790
+ if (this.typedLink && this.typedLink.length > 0) {
29791
+ const obj = this.parseAttachLink(this.typedLink);
29792
+ if (obj) {
29793
+ // do logic copy file by hash
29794
+ alert(obj);
29795
+ this.typedLink = '';
29796
+ this.showAttachLinkBox = false;
29797
+ this.getFolderContent(this.data.currentFolderId);
29798
+ this._notifierService.showSuccess('Tải thành công!');
29799
+ }
29800
+ else {
29801
+ this._notifierService.showWarning('Không hỗ trợ liên kết từ hệ thống khác hoặc liên kết không đúng!');
29802
+ }
29803
+ }
29804
+ }
29805
+ parseAttachLink(link) {
29806
+ if (link) {
29807
+ const parts = link.split('/file/v5/DownloadLink/Download/');
29808
+ if (parts.length == 2) {
29809
+ return parts[1];
29810
+ }
29811
+ }
29812
+ return null;
29813
+ }
29814
+ focusInput(input) {
29815
+ input.focus();
29816
+ }
29625
29817
  }
29626
29818
  FileManagerComponent.decorators = [
29627
29819
  { type: Component, args: [{
29628
29820
  // tslint:disable-next-line: component-selector
29629
29821
  selector: 'file-manager',
29630
- template: "<div *ngIf=\"layout == _layout.LIST\" class=\"full-layout\">\r\n <div class=\"fm-toolbar\">\r\n <div class=\"fm-toolbar-buttons\">\r\n <ng-container *ngIf=\"!readonly\">\r\n <button *ngIf=\"!hiddenCreateFolder\" pButton pRipple type=\"button\" pTooltip=\"T\u1EA1o th\u01B0 m\u1EE5c m\u1EDBi\"\r\n tooltipPosition=\"top\" icon=\"pi pi-folder\" class=\"p-button-text\" label=\"T\u1EA1o th\u01B0 m\u1EE5c\" iconPos=\"left\"\r\n (click)=\"createFolder()\">\r\n </button>\r\n\r\n <button pButton icon=\"pi pi-cloud-upload\" pTooltip=\"T\u1EA3i t\u1EC7p tin t\u1EEB m\u00E1y t\u00EDnh c\u1EE7a b\u1EA1n\"\r\n tooltipPosition=\"top\" type=\"button\" class=\"p-button-text p-button-primary\" label=\"T\u1EA3i l\u00EAn\"\r\n (click)=\"selectFile()\"></button>\r\n\r\n <button *ngIf=\"canSelect()\" class=\"p-button-text p-button-success\" pButton type=\"button\"\r\n pTooltip=\"Di chuy\u1EC3n th\u01B0 m\u1EE5c/t\u1EC7p tin \u0111\u00E3 ch\u1ECDn\" tooltipPosition=\"top\" icon=\"fas fa-arrows-alt\"\r\n iconPos=\"left\" label=\"Di chuy\u1EC3n\" (click)=\"moveExplorerItems()\">\r\n </button>\r\n\r\n <button *ngIf=\"canSetMove()\" class=\"p-button-text p-button-success\" pButton type=\"button\"\r\n pTooltip=\"Di chuy\u1EC3n th\u01B0 m\u1EE5c/t\u1EC7p tin \u0111\u00E3 ch\u1ECDn t\u1EDBi \u0111\u00E2y\" tooltipPosition=\"top\" icon=\"far fa-hand-paper\"\r\n iconPos=\"left\" label=\"\u0110\u1EB7t t\u1EA1i \u0111\u00E2y\" (click)=\"setMoveExplorerItems()\">\r\n </button>\r\n\r\n <button *ngIf=\"canSetMove()\" icon=\"pi pi-undo\" pButton class=\"p-button-text p-button-secondary\"\r\n type=\"button\" pTooltip=\"B\u1ECF di chuy\u1EC3n th\u01B0 m\u1EE5c/t\u1EC7p tin \u0111\u00E3 ch\u1ECDn\" tooltipPosition=\"top\" label=\"B\u1ECF qua\"\r\n (click)=\"cancelMove()\">\r\n </button>\r\n\r\n <button *ngIf=\"hasSelect()\" pButton type=\"button\"\r\n pTooltip=\"{{ 'X\u00F3a th\u01B0 m\u1EE5c/t\u1EC7p tin \u0111\u00E3 ch\u1ECDn' | translate }}\" tooltipPosition=\"top\" icon=\"pi pi-trash\"\r\n iconPos=\"left\" class=\"p-button-text p-button-danger\" label=\"X\u00F3a\"\r\n (click)=\"deleteMutiple(model.selectedItems)\"></button>\r\n </ng-container>\r\n <button *ngIf=\"readonly && hasSelect()\" class=\"p-button-text p-button-secondary\" pButton type=\"button\"\r\n pTooltip=\"N\u00E9n & t\u1EA3i v\u1EC1\" tooltipPosition=\"top\" icon=\"fas fa-file-archive\" iconPos=\"left\" label=\"T\u1EA3i v\u1EC1\"\r\n (click)=\"downloadMultiple()\">\r\n </button>\r\n </div>\r\n <ng-container *ngTemplateOutlet=\"breadCrumb\"></ng-container>\r\n </div>\r\n\r\n <div class=\"fm-grid\">\r\n <crud-list #crudList [model]=\"model\" [setting]=\"setting\" [dataSource]=\"_dataSource\"\r\n [disableKeypressControl]=\"true\" [showScrollBar]=\"false\" (onReload)=\"_triggerProcessData($event)\"\r\n class=\"--auto-height-content --no-wrapper-padding\" (onRowSelect)=\"onRowSelect($event)\">\r\n\r\n <ng-template #explorerItem let-rowData='rowData' let-col='col'>\r\n <span (click)=\"openObject(rowData)\" class=\"pull-left file-ex-icon\"\r\n [innerHTML]=\"rowData.name | fileIcon : !rowData.isFile\">\r\n </span>\r\n\r\n <span (click)=\"openObject(rowData)\" class=\"{{rowData.class}} file-ex-name\">\r\n {{rowData.name}}\r\n <div class=\"pull-right signature\" (click)=\"viewListSign($event, rowData.signatures)\"\r\n *ngIf=\"rowData.signatures\" pTooltip=\"Xem chi ti\u1EBFt k\u00FD s\u1ED1\" tooltipPosition=\"top\">\r\n <i class=\"fas fa-signature\"></i>\r\n </div>\r\n </span>\r\n </ng-template>\r\n\r\n <ng-template #fileSize let-rowData='rowData'>\r\n <div *ngIf=\"rowData.isFile\">{{rowData.fileSize | fileSize}}</div>\r\n </ng-template>\r\n\r\n <ng-template #function let-rowData=\"rowData\" let-crudList=\"crudList\">\r\n <div class=\"function-list\">\r\n <ng-container *ngIf=\"!readonly\">\r\n <button class=\"p-button-rounded p-button-text link-or-action\" pButton type=\"button\"\r\n tooltipPosition=\"top\" pTooltip=\"{{getButtonTooltip(rowData)}}\"\r\n icon=\"{{getButtonIcon(rowData)}}\" (click)=\"onButtonClick(rowData)\"></button>\r\n\r\n <button class=\"p-button-danger p-button-rounded p-button-text link-or-action\" pButton\r\n type=\"button\" pTooltip=\"X\u00F3a\" tooltipPosition=\"top\" icon=\"pi pi-trash\"\r\n (click)=\"deleteFile(rowData)\"></button>\r\n\r\n\r\n <button type=\"button\" pButton icon=\"pi pi-ellipsis-v\"\r\n class=\"link-or-action p-button-text p-button-rounded link-or-action\" pTooltip=\"Th\u00EAm\"\r\n tooltipPosition=\"top\" (click)=\"showContextMenu($event, rowData)\"></button>\r\n </ng-container>\r\n <button *ngIf=\"readonly\" class=\"p-button-secondary p-button-rounded p-button-text link-or-action\"\r\n pButton type=\"button\" pTooltip=\"T\u1EA3i v\u1EC1\" tooltipPosition=\"top\" icon=\"pi pi-cloud-download\"\r\n (click)=\"download(rowData)\"></button>\r\n </div>\r\n </ng-template>\r\n </crud-list>\r\n </div>\r\n</div>\r\n\r\n<div *ngIf=\"layout == _layout.SIMPLE\" class=\"not-full-layout\" [class.readonly]=\"readonly\">\r\n <div *ngIf=\"!readonly || data.breadcrumbs.length > 0\" class=\"fm-toolbar\">\r\n <div class=\"fm-toolbar-buttons\">\r\n <ng-container *ngIf=\"!readonly\">\r\n <button *ngIf=\"!hiddenCreateFolder\" (click)=\"createFolder()\" pButton pRipple type=\"button\"\r\n pTooltip=\"T\u1EA1o th\u01B0 m\u1EE5c m\u1EDBi\" tooltipPosition=\"top\" icon=\"pi pi-folder\" class=\"p-button-text\"\r\n label=\"T\u1EA1o th\u01B0 m\u1EE5c\" iconPos=\"left\">\r\n </button>\r\n <button type=\"button\" pButton class=\"p-button-text p-button-info link-or-action\"\r\n icon=\"pi pi-cloud-upload\" (click)=\"selectFile()\" label=\"T\u1EA3i l\u00EAn\"></button>\r\n </ng-container>\r\n </div>\r\n <ng-container *ngTemplateOutlet=\"breadCrumb\"></ng-container>\r\n </div>\r\n\r\n <div class=\"nfl-grid\">\r\n <div *ngFor=\"let rowData of _dataSource; index as i\" class=\"nfl-item\">\r\n <div class=\"nfl-no\">\r\n {{i + 1}}.\r\n </div>\r\n\r\n <div class=\"nfl-name\">\r\n <span class=\"pull-left file-ex-icon\" [innerHTML]=\"rowData.name | fileIcon : !rowData.isFile\">\r\n </span>\r\n <!-- <a (click)=\"openObject(rowData)\" class=\"{{rowData.class}} file-ex-name\">\r\n <span>{{rowData.nameWithoutExtension}}</span>\r\n <div *ngIf=\"rowData.signatures\" class=\"signature\" pTooltip=\"Xem chi ti\u1EBFt k\u00FD s\u1ED1\"\r\n tooltipPosition=\"top\" (click)=\"viewListSign($event, rowData.signatures)\">\r\n <i class=\"fas fa-signature\"></i>\r\n </div>\r\n </a>\r\n <a (click)=\"openObject(rowData)\" class=\"file-ex-extension\">{{rowData.extension}}</a> -->\r\n\r\n <a (click)=\"openObject(rowData)\" class=\"{{rowData.class}} file-ex-name\">\r\n <span>\r\n <span>{{rowData.nameWithoutExtension}}</span>\r\n <div *ngIf=\"rowData.signatures\" class=\"signature\" pTooltip=\"Xem chi ti\u1EBFt k\u00FD s\u1ED1\"\r\n tooltipPosition=\"top\" (click)=\"viewListSign($event, rowData.signatures)\">\r\n <i class=\"fas fa-signature\"></i>\r\n </div>\r\n </span>\r\n <span class=\"file-ex-extension\">{{rowData.extension}}</span>\r\n </a>\r\n </div>\r\n\r\n <div *ngIf=\"rowData.isFile\" class=\"nfl-version\">\r\n v{{rowData.currentFileVersion}}\r\n </div>\r\n\r\n <div class=\"nfl-function\">\r\n <ng-container *ngIf=\"!readonly\">\r\n <button class=\"p-button-rounded p-button-text link-or-action\" (click)=\"onButtonClick(rowData)\"\r\n pButton type=\"button\" tooltipPosition=\"top\" pTooltip=\"{{getButtonTooltip(rowData)}}\"\r\n icon=\"{{getButtonIcon(rowData)}}\"></button>\r\n\r\n <button class=\"p-button-danger p-button-rounded p-button-text link-or-action\"\r\n (click)=\"deleteFile(rowData)\" pButton type=\"button\" pTooltip=\"X\u00F3a\" tooltipPosition=\"top\"\r\n icon=\"pi pi-trash\"></button>\r\n\r\n <button type=\"button\" pButton icon=\"pi pi-ellipsis-v\"\r\n class=\"link-or-action p-button-text p-button-rounded link-or-action\" pTooltip=\"Th\u00EAm\"\r\n tooltipPosition=\"top\" (click)=\"showContextMenu($event, rowData)\"></button>\r\n </ng-container>\r\n\r\n <button *ngIf=\"readonly\" class=\"p-button-secondary p-button-rounded p-button-text link-or-action\"\r\n (click)=\"download(rowData)\" pButton type=\"button\" pTooltip=\"T\u1EA3i v\u1EC1\" tooltipPosition=\"top\"\r\n icon=\"pi pi-cloud-download\"></button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"!_dataSource || !_dataSource.length\" class=\"nfl-no-item\">\r\n Ch\u01B0a c\u00F3 t\u00E0i li\u1EC7u \u0111\u01B0\u1EE3c t\u1EA3i l\u00EAn\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<ng-template #breadCrumb>\r\n <div *ngIf=\"data.breadcrumbs.length > 0\" class=\"fm-toolbar-path\">\r\n <p-breadcrumb class=\"customBreadCrumb\" [model]=\"data.breadcrumbs\"></p-breadcrumb>\r\n </div>\r\n</ng-template>\r\n\r\n<p-fileUpload #fileControl [ngStyle]=\"{'display': 'none'}\" mode=\"basic\" [chooseLabel]=\"chooseLabel\" name=\"file\"\r\n [url]=\"apiUploadUrl\" [maxFileSize]=\"maxFileSize\" auto=\"true\"\r\n [invalidFileSizeMessageSummary]=\"invalidFileSizeMessageSummary\"\r\n [invalidFileSizeMessageDetail]=\"invalidFileSizeMessageDetail\"\r\n [invalidFileTypeMessageSummary]=\"invalidFileTypeMessageSummary\"\r\n [invalidFileTypeMessageDetail]=\"invalidFileTypeMessageDetail\"\r\n [invalidFileLimitMessageSummary]=\"invalidFileLimitMessageSummary\"\r\n [invalidFileLimitMessageDetail]=\"invalidFileLimitMessageDetail\" (onProgress)=\"onUploadProgress($event)\"\r\n (onBeforeUpload)=\"onBeforeUpload($event)\" (onSelect)=\"handleSelectFile($event)\" (onUpload)=\"onUploaded($event)\">\r\n</p-fileUpload>\r\n<p-contextMenu #contextMenu [appendTo]=\"'body'\" [model]=\"data.itemsMenuFile\" styleClass=\"fm-contextMenu-panel\">\r\n</p-contextMenu>\r\n\r\n<!-- T\u1EA1o m\u1EDBi/ \u0111\u1ED5i t\u00EAn th\u01B0 m\u1EE5c -->\r\n<tn-dialog *ngIf=\"forms.createFolder.show\" #dialog [styleClass]=\"'address-form'\"\r\n [header]=\"forms.createFolder.header | translate\" [popupSize]=\"forms[formIds.createFolder].popupSize\"\r\n (onHide)=\"onCancelForm(formIds.createFolder)\">\r\n <folder-form #formBase [parentModel]=\"model\" [parentContext]=\"context\"\r\n [model]=\"forms[formIds.createFolder].formData\" (onSaved)=\"onSavedForm(formIds.createFolder)\"\r\n (onCancel)=\"onCancelForm(formIds.createFolder)\">\r\n </folder-form>\r\n</tn-dialog>\r\n\r\n<!-- \u0110\u1ED5i t\u00EAn file -->\r\n<tn-dialog *ngIf=\"forms.renameFile.show\" #dialog [styleClass]=\"'address-form'\"\r\n [header]=\"forms.renameFile.header | translate\" [popupSize]=\"forms[formIds.renameFile].popupSize\"\r\n (onHide)=\"onCancelForm(formIds.renameFile)\">\r\n <file-form #formBase [parentModel]=\"model\" [parentContext]=\"context\" [model]=\"forms[formIds.renameFile].formData\"\r\n (onSaved)=\"onSavedForm(formIds.renameFile)\" (onCancel)=\"onCancelForm(formIds.renameFile)\">\r\n </file-form>\r\n</tn-dialog>\r\n\r\n<!-- Xem file tr\u1EF1c tuy\u1EBFn -->\r\n<file-viewer *ngIf=\"forms.fileViewer.show\" [parentModel]=\"model\" [parentContext]=\"context\"\r\n [model]=\"forms.fileViewer.formData\" (onClose)=\"closeFileViewer()\" [readonly]=\"readonly\">\r\n</file-viewer>\r\n\r\n<!-- Xem phi\u00EAn b\u1EA3n -->\r\n<tn-dialog *ngIf=\"forms.fileVersionList.show\" #dialog [styleClass]=\"'address-form'\"\r\n [header]=\"forms.fileVersionList.header | translate\" [popupSize]=\"forms[formIds.fileVersionList].popupSize\"\r\n (onHide)=\"onCancelForm(formIds.fileVersionList)\">\r\n <file-version-list *ngIf=\"forms.fileVersionList.show\" [parentModel]=\"model\" [parentContext]=\"context\"\r\n [fileId]=\"forms[formIds.fileVersionList].fileId\" [readonly]=\"readonly\">\r\n </file-version-list>\r\n</tn-dialog>\r\n<!--\r\n\r\n<share-file *ngIf=\"forms.shareFile.show\" [parentDataModel]=\"model\" [parentDataContext]=\"context\"\r\n [model]=\"forms.shareFile.formData\">\r\n</share-file>\r\n\r\n<share-folder *ngIf=\"forms.shareFolder.show\" [parentDataModel]=\"model\" [parentDataContext]=\"context\"\r\n [model]=\"forms.shareFolder.formData\">\r\n</share-folder>\r\n\r\n\r\n\r\n<signature-detail *ngIf=\"forms.signatureDetail.show\" [parentDataModel]=\"model\" [parentDataContext]=\"context\"\r\n [model]=\"forms.signatureDetail.formData\">\r\n</signature-detail> -->",
29822
+ template: "<div *ngIf=\"layout == _layout.LIST\" class=\"full-layout\">\r\n <div class=\"fm-toolbar\">\r\n <div class=\"fm-toolbar-buttons\">\r\n <ng-container *ngIf=\"!readonly\">\r\n <button *ngIf=\"!hiddenCreateFolder\" pButton pRipple type=\"button\" pTooltip=\"T\u1EA1o th\u01B0 m\u1EE5c m\u1EDBi\"\r\n tooltipPosition=\"top\" icon=\"pi pi-folder\" class=\"p-button-text\" label=\"T\u1EA1o th\u01B0 m\u1EE5c\" iconPos=\"left\"\r\n (click)=\"createFolder()\">\r\n </button>\r\n\r\n <button pButton icon=\"pi pi-cloud-upload\" pTooltip=\"T\u1EA3i t\u1EC7p tin t\u1EEB m\u00E1y t\u00EDnh c\u1EE7a b\u1EA1n\"\r\n tooltipPosition=\"top\" type=\"button\" class=\"p-button-text p-button-primary\" label=\"T\u1EA3i l\u00EAn\"\r\n (click)=\"selectFile()\"></button>\r\n\r\n <button pButton icon=\"pi pi-link\" pTooltip=\"T\u1EA3i t\u1EEB li\u00EAn k\u1EBFt trong h\u1EC7 th\u1ED1ng\"\r\n tooltipPosition=\"top\" type=\"button\" class=\"p-button-text p-button-primary\" label=\"T\u1EA3i li\u00EAn k\u1EBFt\"\r\n (click)=\"showAttachLinkBox = true\"></button>\r\n\r\n <button *ngIf=\"canSelect()\" class=\"p-button-text p-button-success\" pButton type=\"button\"\r\n pTooltip=\"Di chuy\u1EC3n th\u01B0 m\u1EE5c/t\u1EC7p tin \u0111\u00E3 ch\u1ECDn\" tooltipPosition=\"top\" icon=\"fas fa-arrows-alt\"\r\n iconPos=\"left\" label=\"Di chuy\u1EC3n\" (click)=\"moveExplorerItems()\">\r\n </button>\r\n\r\n <button *ngIf=\"canSetMove()\" class=\"p-button-text p-button-success\" pButton type=\"button\"\r\n pTooltip=\"Di chuy\u1EC3n th\u01B0 m\u1EE5c/t\u1EC7p tin \u0111\u00E3 ch\u1ECDn t\u1EDBi \u0111\u00E2y\" tooltipPosition=\"top\" icon=\"far fa-hand-paper\"\r\n iconPos=\"left\" label=\"\u0110\u1EB7t t\u1EA1i \u0111\u00E2y\" (click)=\"setMoveExplorerItems()\">\r\n </button>\r\n\r\n <button *ngIf=\"canSetMove()\" icon=\"pi pi-undo\" pButton class=\"p-button-text p-button-secondary\"\r\n type=\"button\" pTooltip=\"B\u1ECF di chuy\u1EC3n th\u01B0 m\u1EE5c/t\u1EC7p tin \u0111\u00E3 ch\u1ECDn\" tooltipPosition=\"top\" label=\"B\u1ECF qua\"\r\n (click)=\"cancelMove()\">\r\n </button>\r\n\r\n <button *ngIf=\"hasSelect()\" pButton type=\"button\"\r\n pTooltip=\"{{ 'X\u00F3a th\u01B0 m\u1EE5c/t\u1EC7p tin \u0111\u00E3 ch\u1ECDn' | translate }}\" tooltipPosition=\"top\" icon=\"pi pi-trash\"\r\n iconPos=\"left\" class=\"p-button-text p-button-danger\" label=\"X\u00F3a\"\r\n (click)=\"deleteMutiple(model.selectedItems)\"></button>\r\n </ng-container>\r\n <button *ngIf=\"readonly && hasSelect()\" class=\"p-button-text p-button-secondary\" pButton type=\"button\"\r\n pTooltip=\"N\u00E9n & t\u1EA3i v\u1EC1\" tooltipPosition=\"top\" icon=\"fas fa-file-archive\" iconPos=\"left\" label=\"T\u1EA3i v\u1EC1\"\r\n (click)=\"downloadMultiple()\">\r\n </button>\r\n </div>\r\n <ng-container *ngTemplateOutlet=\"breadCrumb\"></ng-container>\r\n </div>\r\n\r\n <div class=\"fm-grid\">\r\n <crud-list #crudList [model]=\"model\" [setting]=\"setting\" [dataSource]=\"_dataSource\"\r\n [disableKeypressControl]=\"true\" [showScrollBar]=\"false\" (onReload)=\"_triggerProcessData($event)\"\r\n class=\"--auto-height-content --no-wrapper-padding\" (onRowSelect)=\"onRowSelect($event)\">\r\n\r\n <ng-template #explorerItem let-rowData='rowData' let-col='col'>\r\n <span (click)=\"openObject(rowData)\" class=\"pull-left file-ex-icon\"\r\n [innerHTML]=\"rowData.name | fileIcon : !rowData.isFile\">\r\n </span>\r\n\r\n <span (click)=\"openObject(rowData)\" class=\"{{rowData.class}} file-ex-name\">\r\n {{rowData.name}}\r\n <div class=\"pull-right signature\" (click)=\"viewListSign($event, rowData.signatures)\"\r\n *ngIf=\"rowData.signatures\" pTooltip=\"Xem chi ti\u1EBFt k\u00FD s\u1ED1\" tooltipPosition=\"top\">\r\n <i class=\"fas fa-signature\"></i>\r\n </div>\r\n </span>\r\n </ng-template>\r\n\r\n <ng-template #fileSize let-rowData='rowData'>\r\n <div *ngIf=\"rowData.isFile\">{{rowData.fileSize | fileSize}}</div>\r\n </ng-template>\r\n\r\n <ng-template #function let-rowData=\"rowData\" let-crudList=\"crudList\">\r\n <div class=\"function-list\">\r\n <ng-container *ngIf=\"!readonly\">\r\n <button class=\"p-button-rounded p-button-text link-or-action\" pButton type=\"button\"\r\n tooltipPosition=\"top\" pTooltip=\"{{getButtonTooltip(rowData)}}\"\r\n icon=\"{{getButtonIcon(rowData)}}\" (click)=\"onButtonClick(rowData)\"></button>\r\n\r\n <button class=\"p-button-danger p-button-rounded p-button-text link-or-action\" pButton\r\n type=\"button\" pTooltip=\"X\u00F3a\" tooltipPosition=\"top\" icon=\"pi pi-trash\"\r\n (click)=\"deleteFile(rowData)\"></button>\r\n\r\n\r\n <button type=\"button\" pButton icon=\"pi pi-ellipsis-v\"\r\n class=\"link-or-action p-button-text p-button-rounded link-or-action\" pTooltip=\"Th\u00EAm\"\r\n tooltipPosition=\"top\" (click)=\"showContextMenu($event, rowData)\"></button>\r\n </ng-container>\r\n <button *ngIf=\"readonly\" class=\"p-button-secondary p-button-rounded p-button-text link-or-action\"\r\n pButton type=\"button\" pTooltip=\"T\u1EA3i v\u1EC1\" tooltipPosition=\"top\" icon=\"pi pi-cloud-download\"\r\n (click)=\"download(rowData)\"></button>\r\n <button *ngIf=\"readonly\" class=\"p-button-secondary p-button-rounded p-button-text link-or-action\"\r\n pButton type=\"button\" pTooltip=\"Sao ch\u00E9p \u0111\u01B0\u1EDDng d\u1EABn\" tooltipPosition=\"top\" icon=\"pi pi-link\"\r\n (click)=\"copyDownloadLink(rowData)\"></button>\r\n </div>\r\n </ng-template>\r\n </crud-list>\r\n </div>\r\n</div>\r\n\r\n<div *ngIf=\"layout == _layout.SIMPLE\" class=\"not-full-layout\" [class.readonly]=\"readonly\">\r\n <div *ngIf=\"!readonly || data.breadcrumbs.length > 0\" class=\"fm-toolbar\">\r\n <div class=\"fm-toolbar-buttons\">\r\n <ng-container *ngIf=\"!readonly\">\r\n <button *ngIf=\"!hiddenCreateFolder\" (click)=\"createFolder()\" pButton pRipple type=\"button\"\r\n pTooltip=\"T\u1EA1o th\u01B0 m\u1EE5c m\u1EDBi\" tooltipPosition=\"top\" icon=\"pi pi-folder\" class=\"p-button-text\"\r\n label=\"T\u1EA1o th\u01B0 m\u1EE5c\" iconPos=\"left\">\r\n </button>\r\n <button type=\"button\" pButton class=\"p-button-text p-button-info link-or-action\"\r\n icon=\"pi pi-cloud-upload\" (click)=\"selectFile()\" label=\"T\u1EA3i l\u00EAn\"></button>\r\n <button pButton icon=\"pi pi-link\" pTooltip=\"T\u1EA3i t\u1EEB li\u00EAn k\u1EBFt trong h\u1EC7 th\u1ED1ng\"\r\n tooltipPosition=\"top\" type=\"button\" class=\"p-button-text p-button-primary\" label=\"T\u1EA3i li\u00EAn k\u1EBFt\"\r\n (click)=\"showAttachLinkBox = true\"></button>\r\n </ng-container>\r\n </div>\r\n <ng-container *ngTemplateOutlet=\"breadCrumb\"></ng-container>\r\n </div>\r\n\r\n <div class=\"nfl-grid\">\r\n <div *ngFor=\"let rowData of _dataSource; index as i\" class=\"nfl-item\">\r\n <div class=\"nfl-no\">\r\n {{i + 1}}.\r\n </div>\r\n\r\n <div class=\"nfl-name\">\r\n <span class=\"pull-left file-ex-icon\" [innerHTML]=\"rowData.name | fileIcon : !rowData.isFile\">\r\n </span>\r\n <!-- <a (click)=\"openObject(rowData)\" class=\"{{rowData.class}} file-ex-name\">\r\n <span>{{rowData.nameWithoutExtension}}</span>\r\n <div *ngIf=\"rowData.signatures\" class=\"signature\" pTooltip=\"Xem chi ti\u1EBFt k\u00FD s\u1ED1\"\r\n tooltipPosition=\"top\" (click)=\"viewListSign($event, rowData.signatures)\">\r\n <i class=\"fas fa-signature\"></i>\r\n </div>\r\n </a>\r\n <a (click)=\"openObject(rowData)\" class=\"file-ex-extension\">{{rowData.extension}}</a> -->\r\n\r\n <a (click)=\"openObject(rowData)\" class=\"{{rowData.class}} file-ex-name\">\r\n <span>\r\n <span>{{rowData.nameWithoutExtension}}</span>\r\n <div *ngIf=\"rowData.signatures\" class=\"signature\" pTooltip=\"Xem chi ti\u1EBFt k\u00FD s\u1ED1\"\r\n tooltipPosition=\"top\" (click)=\"viewListSign($event, rowData.signatures)\">\r\n <i class=\"fas fa-signature\"></i>\r\n </div>\r\n </span>\r\n <span class=\"file-ex-extension\">{{rowData.extension}}</span>\r\n </a>\r\n </div>\r\n\r\n <div *ngIf=\"rowData.isFile\" class=\"nfl-version\">\r\n v{{rowData.currentFileVersion}}\r\n </div>\r\n\r\n <div class=\"nfl-function\">\r\n <ng-container *ngIf=\"!readonly\">\r\n <button class=\"p-button-rounded p-button-text link-or-action\" (click)=\"onButtonClick(rowData)\"\r\n pButton type=\"button\" tooltipPosition=\"top\" pTooltip=\"{{getButtonTooltip(rowData)}}\"\r\n icon=\"{{getButtonIcon(rowData)}}\"></button>\r\n\r\n <button class=\"p-button-danger p-button-rounded p-button-text link-or-action\"\r\n (click)=\"deleteFile(rowData)\" pButton type=\"button\" pTooltip=\"X\u00F3a\" tooltipPosition=\"top\"\r\n icon=\"pi pi-trash\"></button>\r\n\r\n <button type=\"button\" pButton icon=\"pi pi-ellipsis-v\"\r\n class=\"link-or-action p-button-text p-button-rounded link-or-action\" pTooltip=\"Th\u00EAm\"\r\n tooltipPosition=\"top\" (click)=\"showContextMenu($event, rowData)\"></button>\r\n </ng-container>\r\n\r\n <button *ngIf=\"readonly\" class=\"p-button-secondary p-button-rounded p-button-text link-or-action\"\r\n (click)=\"download(rowData)\" pButton type=\"button\" pTooltip=\"T\u1EA3i v\u1EC1\" tooltipPosition=\"top\"\r\n icon=\"pi pi-cloud-download\"></button>\r\n <button *ngIf=\"readonly\" class=\"p-button-secondary p-button-rounded p-button-text link-or-action\"\r\n pButton type=\"button\" pTooltip=\"Sao ch\u00E9p \u0111\u01B0\u1EDDng d\u1EABn\" tooltipPosition=\"top\" icon=\"pi pi-link\"\r\n (click)=\"copyDownloadLink(rowData)\"></button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"!_dataSource || !_dataSource.length\" class=\"nfl-no-item\">\r\n Ch\u01B0a c\u00F3 t\u00E0i li\u1EC7u \u0111\u01B0\u1EE3c t\u1EA3i l\u00EAn\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<ng-template #breadCrumb>\r\n <div *ngIf=\"data.breadcrumbs.length > 0\" class=\"fm-toolbar-path\">\r\n <p-breadcrumb class=\"customBreadCrumb\" [model]=\"data.breadcrumbs\"></p-breadcrumb>\r\n </div>\r\n</ng-template>\r\n\r\n<p-fileUpload #fileControl [ngStyle]=\"{'display': 'none'}\" mode=\"basic\" [chooseLabel]=\"chooseLabel\" name=\"file\"\r\n [url]=\"apiUploadUrl\" [maxFileSize]=\"maxFileSize\" auto=\"true\"\r\n [invalidFileSizeMessageSummary]=\"invalidFileSizeMessageSummary\"\r\n [invalidFileSizeMessageDetail]=\"invalidFileSizeMessageDetail\"\r\n [invalidFileTypeMessageSummary]=\"invalidFileTypeMessageSummary\"\r\n [invalidFileTypeMessageDetail]=\"invalidFileTypeMessageDetail\"\r\n [invalidFileLimitMessageSummary]=\"invalidFileLimitMessageSummary\"\r\n [invalidFileLimitMessageDetail]=\"invalidFileLimitMessageDetail\" (onProgress)=\"onUploadProgress($event)\"\r\n (onBeforeUpload)=\"onBeforeUpload($event)\" (onSelect)=\"handleSelectFile($event)\" (onUpload)=\"onUploaded($event)\">\r\n</p-fileUpload>\r\n<p-contextMenu #contextMenu [appendTo]=\"'body'\" [model]=\"data.itemsMenuFile\" styleClass=\"fm-contextMenu-panel\">\r\n</p-contextMenu>\r\n\r\n<!-- T\u1EA1o m\u1EDBi/ \u0111\u1ED5i t\u00EAn th\u01B0 m\u1EE5c -->\r\n<tn-dialog *ngIf=\"forms.createFolder.show\" #dialog [styleClass]=\"'address-form'\"\r\n [header]=\"forms.createFolder.header | translate\" [popupSize]=\"forms[formIds.createFolder].popupSize\"\r\n (onHide)=\"onCancelForm(formIds.createFolder)\">\r\n <folder-form #formBase [parentModel]=\"model\" [parentContext]=\"context\"\r\n [model]=\"forms[formIds.createFolder].formData\" (onSaved)=\"onSavedForm(formIds.createFolder)\"\r\n (onCancel)=\"onCancelForm(formIds.createFolder)\">\r\n </folder-form>\r\n</tn-dialog>\r\n\r\n<!-- \u0110\u1ED5i t\u00EAn file -->\r\n<tn-dialog *ngIf=\"forms.renameFile.show\" #dialog [styleClass]=\"'address-form'\"\r\n [header]=\"forms.renameFile.header | translate\" [popupSize]=\"forms[formIds.renameFile].popupSize\"\r\n (onHide)=\"onCancelForm(formIds.renameFile)\">\r\n <file-form #formBase [parentModel]=\"model\" [parentContext]=\"context\" [model]=\"forms[formIds.renameFile].formData\"\r\n (onSaved)=\"onSavedForm(formIds.renameFile)\" (onCancel)=\"onCancelForm(formIds.renameFile)\">\r\n </file-form>\r\n</tn-dialog>\r\n\r\n<!-- Xem file tr\u1EF1c tuy\u1EBFn -->\r\n<file-viewer *ngIf=\"forms.fileViewer.show\" [parentModel]=\"model\" [parentContext]=\"context\"\r\n [model]=\"forms.fileViewer.formData\" (onClose)=\"closeFileViewer()\" [readonly]=\"readonly\">\r\n</file-viewer>\r\n\r\n<!-- Xem phi\u00EAn b\u1EA3n -->\r\n<tn-dialog *ngIf=\"forms.fileVersionList.show\" #dialog [styleClass]=\"'address-form'\"\r\n [header]=\"forms.fileVersionList.header | translate\" [popupSize]=\"forms[formIds.fileVersionList].popupSize\"\r\n (onHide)=\"onCancelForm(formIds.fileVersionList)\">\r\n <file-version-list *ngIf=\"forms.fileVersionList.show\" [parentModel]=\"model\" [parentContext]=\"context\"\r\n [fileId]=\"forms[formIds.fileVersionList].fileId\" [readonly]=\"readonly\">\r\n </file-version-list>\r\n</tn-dialog>\r\n\r\n<tn-dialog *ngIf=\"showAttachLinkBox\" #dialog2 [maximizable]=\"false\"\r\n [header]=\"'Nh\u1EADp li\u00EAn k\u1EBFt' | translate\" [popupSize]=\"{ width: 600, height: 50}\" (onHide)=\"showAttachLinkBox = false; typedLink=''\">\r\n <div class=\"p-col-12\">\r\n <div class=\"p-grid\">\r\n <div class=\"p-md-10\">\r\n <input #input type=\"text\" placeholder=\"Nh\u1EADp li\u00EAn k\u1EBFt sao ch\u00E9p t\u1EEB t\u1EC7p tin kh\u00E1c...\" (keyup.enter)=\"addAttachLink()\" pInputText [(ngModel)]=\"typedLink\" class=\"p-col-12\"/>\r\n </div>\r\n <div class=\"p-md-2\">\r\n <button type=\"button\" (click)=\"addAttachLink()\" [disabled]=\"typedLink != ''? null : true\" pButton class=\"p-button-primary p-col-12\" label=\"Ok\"></button>\r\n </div>\r\n </div>\r\n </div>\r\n <after-view-checked (loaded)=\"focusInput(input)\"></after-view-checked>\r\n</tn-dialog>\r\n<!--\r\n\r\n<share-file *ngIf=\"forms.shareFile.show\" [parentDataModel]=\"model\" [parentDataContext]=\"context\"\r\n [model]=\"forms.shareFile.formData\">\r\n</share-file>\r\n\r\n<share-folder *ngIf=\"forms.shareFolder.show\" [parentDataModel]=\"model\" [parentDataContext]=\"context\"\r\n [model]=\"forms.shareFolder.formData\">\r\n</share-folder>\r\n\r\n\r\n\r\n<signature-detail *ngIf=\"forms.signatureDetail.show\" [parentDataModel]=\"model\" [parentDataContext]=\"context\"\r\n [model]=\"forms.signatureDetail.formData\">\r\n</signature-detail> -->",
29631
29823
  providers: [
29632
29824
  {
29633
29825
  provide: NG_VALUE_ACCESSOR,
@@ -30341,7 +30533,7 @@ class FileViewerComponent extends ComponentBase {
30341
30533
  this.onClose.next(true);
30342
30534
  }
30343
30535
  else {
30344
- this._notifierService.showWarningByReponse(response);
30536
+ this._notifierService.showWarningByResponse(response);
30345
30537
  }
30346
30538
  });
30347
30539
  });
@@ -32837,7 +33029,12 @@ var EnumWorkflowHistoryStatus;
32837
33029
  EnumWorkflowHistoryStatus[EnumWorkflowHistoryStatus["IN_MAIN_THREAD"] = 0] = "IN_MAIN_THREAD";
32838
33030
  EnumWorkflowHistoryStatus[EnumWorkflowHistoryStatus["NOT_IN_MAIN_THREAD"] = 1] = "NOT_IN_MAIN_THREAD";
32839
33031
  EnumWorkflowHistoryStatus[EnumWorkflowHistoryStatus["RECALLED"] = 2] = "RECALLED";
32840
- })(EnumWorkflowHistoryStatus || (EnumWorkflowHistoryStatus = {}));
33032
+ })(EnumWorkflowHistoryStatus || (EnumWorkflowHistoryStatus = {}));
33033
+ var EnumPermissionType;
33034
+ (function (EnumPermissionType) {
33035
+ EnumPermissionType[EnumPermissionType["MAIN"] = 0] = "MAIN";
33036
+ EnumPermissionType[EnumPermissionType["SHARE"] = 1] = "SHARE"; // Bản ghi tạo ra để chia sẻ
33037
+ })(EnumPermissionType || (EnumPermissionType = {}));
32841
33038
 
32842
33039
  const StateMachineTopic = {
32843
33040
  CONNECTION_CHANGE: 'CONNECTION_CHANGE'
@@ -35520,6 +35717,7 @@ class TnDialogComponent {
35520
35717
  this.closeOnEscape = true;
35521
35718
  this.showFooter = true;
35522
35719
  this.hiddenSave = true;
35720
+ this.maximizable = true;
35523
35721
  this.scrollConfig = { suppressScrollX: true, suppressScrollY: false };
35524
35722
  this.scrollStyle = {};
35525
35723
  this.onSave = new EventEmitter();
@@ -35594,7 +35792,7 @@ class TnDialogComponent {
35594
35792
  TnDialogComponent.decorators = [
35595
35793
  { type: Component, args: [{
35596
35794
  selector: 'tn-dialog',
35597
- template: "<p-dialog #dialog [closeOnEscape]=\"closeOnEscape\" [appendTo]=\"'body'\" [focusOnShow]=\"false\" [focusTrap]=\"false\"\r\n [header]=\"header | translate\" [(visible)]=\"visible\" [modal]=\"modal\" [responsive]=\"true\" [maximizable]=\"true\"\r\n [autoZIndex]=\"true\" [styleClass]=\"styleClass\" [maskStyleClass]=\"maskClass\"\r\n [style]=\"{'width': popupSize.width + 'px', 'min-width': popupSize.width + 'px', 'height': popupSize.height + 'px', 'min-height': popupSize.height + 'px'}\"\r\n (onShow)=\"handleShowDialog($event)\" (onHide)=\"handleHideDialog($event)\" (onShow)=\"handleShowDialog($event)\">\r\n <tn-custom-scrollbar #scrollbar [useDefaultScrollBar]=\"useDefaultScrollBar\" [class]=\"scrollBarStyleClass\"\r\n [config]=\"scrollConfig\" [style]=\"scrollStyle\" class=\"tn-dialog-scrollbar\">\r\n <ng-content></ng-content>\r\n </tn-custom-scrollbar>\r\n <p-footer *ngIf=\"showFooter && formBase && formBase.buttonTemplate\">\r\n <ng-container *ngTemplateOutlet=\"formBase.buttonTemplate\">\r\n </ng-container>\r\n </p-footer>\r\n <p-footer *ngIf=\"showFooter && footer\">\r\n <ng-container *ngTemplateOutlet=\"footer\"></ng-container>\r\n </p-footer>\r\n</p-dialog>",
35795
+ template: "<p-dialog #dialog [closeOnEscape]=\"closeOnEscape\" [appendTo]=\"'body'\" [focusOnShow]=\"false\" [focusTrap]=\"false\"\r\n [header]=\"header | translate\" [(visible)]=\"visible\" [modal]=\"modal\" [responsive]=\"true\" [maximizable]=\"maximizable\"\r\n [autoZIndex]=\"true\" [styleClass]=\"styleClass\" [maskStyleClass]=\"maskClass\"\r\n [style]=\"{'width': popupSize.width + 'px', 'min-width': popupSize.width + 'px', 'height': popupSize.height + 'px', 'min-height': popupSize.height + 'px'}\"\r\n (onShow)=\"handleShowDialog($event)\" (onHide)=\"handleHideDialog($event)\" (onShow)=\"handleShowDialog($event)\">\r\n <tn-custom-scrollbar #scrollbar [useDefaultScrollBar]=\"useDefaultScrollBar\" [class]=\"scrollBarStyleClass\"\r\n [config]=\"scrollConfig\" [style]=\"scrollStyle\" class=\"tn-dialog-scrollbar\">\r\n <ng-content></ng-content>\r\n </tn-custom-scrollbar>\r\n <p-footer *ngIf=\"showFooter && formBase && formBase.buttonTemplate\">\r\n <ng-container *ngTemplateOutlet=\"formBase.buttonTemplate\">\r\n </ng-container>\r\n </p-footer>\r\n <p-footer *ngIf=\"showFooter && footer\">\r\n <ng-container *ngTemplateOutlet=\"footer\"></ng-container>\r\n </p-footer>\r\n</p-dialog>",
35598
35796
  styles: [""]
35599
35797
  },] }
35600
35798
  ];
@@ -35622,6 +35820,7 @@ TnDialogComponent.propDecorators = {
35622
35820
  positionTop: [{ type: Input }],
35623
35821
  minY: [{ type: Input }],
35624
35822
  hiddenSave: [{ type: Input }],
35823
+ maximizable: [{ type: Input }],
35625
35824
  onSave: [{ type: Output }],
35626
35825
  onCancel: [{ type: Output }],
35627
35826
  onShow: [{ type: Output }],
@@ -37582,6 +37781,140 @@ ChoYKienFormComponent.propDecorators = {
37582
37781
  rowItem: [{ type: Input }]
37583
37782
  };
37584
37783
 
37784
+ class WorkflowPermissionService extends BaseService {
37785
+ constructor(http, injector, _moduleConfigService) {
37786
+ super(http, injector, `${_moduleConfigService.getConfig().environment.apiDomain.workflowEndpoint}/WorkflowPermission`);
37787
+ this.entityName = 'WorkflowPermission';
37788
+ this.serviceCode = 'workflow';
37789
+ this.endPoint = _moduleConfigService.getConfig().environment.apiDomain.workflowEndpoint;
37790
+ }
37791
+ }
37792
+ WorkflowPermissionService.ɵprov = ɵɵdefineInjectable({ factory: function WorkflowPermissionService_Factory() { return new WorkflowPermissionService(ɵɵinject(HttpClient), ɵɵinject(INJECTOR), ɵɵinject(ModuleConfigService)); }, token: WorkflowPermissionService, providedIn: "root" });
37793
+ WorkflowPermissionService.decorators = [
37794
+ { type: Injectable, args: [{
37795
+ providedIn: 'root'
37796
+ },] }
37797
+ ];
37798
+ WorkflowPermissionService.ctorParameters = () => [
37799
+ { type: HttpClient },
37800
+ { type: Injector },
37801
+ { type: ModuleConfigService }
37802
+ ];
37803
+
37804
+ class PermissionSharingComponent extends DataListBase {
37805
+ constructor(_injector, _workflowPermissionService) {
37806
+ super(_injector);
37807
+ this._injector = _injector;
37808
+ this._workflowPermissionService = _workflowPermissionService;
37809
+ }
37810
+ ngOnInit() {
37811
+ this.setting.baseService = this._workflowPermissionService;
37812
+ this.setting.settingKey = 'permission-sharing';
37813
+ this.setting.title = '';
37814
+ this.setting.heightType = HeightType.dynamic;
37815
+ this.setting.showEditLink = false;
37816
+ this.setting.hiddenToolbar = true;
37817
+ this.setting.hiddenWorkflowColumn = true;
37818
+ this.setting.hiddenSettingWorkflow = true;
37819
+ this.setting.hiddenSettingWorkflowNew = true;
37820
+ this.setting.hiddenSettingPermission = true;
37821
+ this.init();
37822
+ }
37823
+ init() {
37824
+ this.setting.modelSchemas = [
37825
+ new ModelSchema({ field: 'userIdCreated', name: 'Người chia sẻ', fullName: 'Người chia sẻ', description: '' }),
37826
+ new ModelSchema({ field: 'permission', name: 'Quyền', fullName: 'Quyền', description: '' }),
37827
+ new ModelSchema({ field: 'created', name: 'Thời gian', fullName: 'Thời gian', description: '' }),
37828
+ ];
37829
+ this.setting.cols = [
37830
+ new ColumnSchemaBase({
37831
+ field: 'userIdCreated',
37832
+ baseService: this._userService,
37833
+ displayField: 'fullNameNew'
37834
+ }),
37835
+ new ColumnSchemaBase({
37836
+ field: 'strPermissions',
37837
+ label: this._translateService.instant('Quyền'),
37838
+ }),
37839
+ new ColumnSchemaBase({
37840
+ field: 'created',
37841
+ dataType: 'datetime',
37842
+ width: '20%'
37843
+ })
37844
+ ];
37845
+ this.model.ready = true;
37846
+ super.ngOnInit();
37847
+ }
37848
+ modifyGridInfo(gridInfo) {
37849
+ return __awaiter(this, void 0, void 0, function* () {
37850
+ gridInfo.filters.unshift(this.newFilter('itemId', Operator.equal, this.item.id), this.newFilter('type', Operator.equal, EnumPermissionType.SHARE));
37851
+ gridInfo.sorts.unshift(this.newSort('created', -1));
37852
+ });
37853
+ }
37854
+ beforeRenderDataSource(dataSource) {
37855
+ return __awaiter(this, void 0, void 0, function* () {
37856
+ const separator = ', ';
37857
+ dataSource.forEach(item => {
37858
+ item.hiddenEdit = true;
37859
+ item.hiddenCopyLink = true;
37860
+ // Tổng hợp quyền của bản ghi
37861
+ let strPermissions = '';
37862
+ if (this.checkHasPermission(item.permission, PermissionBase.READ)) {
37863
+ strPermissions += `xem${separator}`;
37864
+ }
37865
+ if (this.checkHasPermission(item.permission, PermissionBase.EDIT)) {
37866
+ strPermissions += `sửa${separator}`;
37867
+ }
37868
+ if (this.checkHasPermission(item.permission, PermissionBase.DELETE)) {
37869
+ strPermissions += `xóa${separator}`;
37870
+ }
37871
+ if (strPermissions.length > 0) {
37872
+ strPermissions = strPermissions.substring(0, strPermissions.length - separator.length);
37873
+ strPermissions = strPermissions.substring(0, 1).toUpperCase() + strPermissions.substring(1);
37874
+ }
37875
+ item.strPermissions = strPermissions;
37876
+ });
37877
+ });
37878
+ }
37879
+ checkHasPermission(permission, permissionCheck) {
37880
+ return (permission & permissionCheck) == permissionCheck;
37881
+ }
37882
+ delete(item) {
37883
+ this.deletePermissionSharing([item.id]);
37884
+ }
37885
+ deleteMultiple(items) {
37886
+ this.deletePermissionSharing(items.map(q => q.id));
37887
+ }
37888
+ deletePermissionSharing(ids) {
37889
+ if (ids.length == 0) {
37890
+ return this._notifierService.showWarning('Bạn chưa chọn link muốn xóa');
37891
+ }
37892
+ this._notifierService.showConfirm('Bạn có chắc chắn muốn xóa link đã chọn')
37893
+ .then(res => {
37894
+ if (!res)
37895
+ return;
37896
+ this.baseService.deleteLinkSharing(ids)
37897
+ .then(res => this.handleResponse(res, 'Xóa thành công', f => this._triggerProcessData()));
37898
+ });
37899
+ }
37900
+ }
37901
+ PermissionSharingComponent.decorators = [
37902
+ { type: Component, args: [{
37903
+ selector: 'permission-sharing',
37904
+ template: "<crud-list *ngIf=\"model.ready\" #crudList [model]=\"model\" [setting]=\"setting\" [dataSource]=\"model.dataSource\"\r\n [disableShare]=\"true\" [hiddenCopyLink]=\"true\" [hiddenAdd]=\"true\" (onReload)=\"_triggerProcessData($event)\"\r\n (onAdd)=\"_add($event)\" (onEdit)=\"_edit($event)\" (onView)=\"_view($event)\" (onDelete)=\"delete($event)\"\r\n (onDeleteMultiple)=\"deleteMultiple($event)\" (onReloaded)=\"_handleReloaded($event)\">\r\n</crud-list>",
37905
+ providers: [ComponentContextService],
37906
+ styles: [".state-designer-container>div:first-child{font-size:.9em;font-weight:700;padding:.5em 0}.container-receiver div{margin-bottom:10px}.container-receiver div:last-child{margin-bottom:0}::ng-deep workflow-history-new tr.recalled{opacity:.5}"]
37907
+ },] }
37908
+ ];
37909
+ PermissionSharingComponent.ctorParameters = () => [
37910
+ { type: Injector },
37911
+ { type: WorkflowPermissionService }
37912
+ ];
37913
+ PermissionSharingComponent.propDecorators = {
37914
+ baseService: [{ type: Input }],
37915
+ item: [{ type: Input }]
37916
+ };
37917
+
37585
37918
  class CanBoHoSoService extends BaseService {
37586
37919
  constructor(http, injector, _moduleConfigService) {
37587
37920
  super(http, injector, `${_moduleConfigService.getConfig().environment.apiDomain.canboEndpoint}/${_moduleConfigService.getConfig().environment.apiVersion}/CanBo_HoSo`);
@@ -38456,6 +38789,9 @@ class WorkflowHistoryNewComponent extends DataListBase {
38456
38789
  item.jsonModelChange = [];
38457
38790
  }
38458
38791
  }
38792
+ else if (item.actionCode == ActionThuHoiBase) {
38793
+ item.class = 'recalled';
38794
+ }
38459
38795
  }
38460
38796
  else if (item.status == EnumWorkflowHistoryStatus.RECALLED) {
38461
38797
  item.class = 'recalled';
@@ -39239,7 +39575,7 @@ class BaseCauHinhWorkflowDetailComponent extends ComponentBase {
39239
39575
  BaseCauHinhWorkflowDetailComponent.decorators = [
39240
39576
  { type: Component, args: [{
39241
39577
  selector: 'base-cauhinh-workflow-detail',
39242
- template: "<workflow-picker #workflowPicker *ngIf=\"readyGenWorkflow\" #formBase [data]=\"workflowData\" [showButtonSave]=\"true\"\r\n (onSaveSetting)=\"handleSave($event)\"></workflow-picker>\r\n<after-view-checked *ngIf=\"hasCountDown\" (loaded)=\"handleReadyToGetWorkflowData()\">\r\n</after-view-checked>",
39578
+ template: "<workflow-picker #workflowPicker *ngIf=\"readyGenWorkflow\" #formBase [data]=\"workflowData\" [showButtonSave]=\"true\"\r\n (onSaveSetting)=\"handleSave($event)\"></workflow-picker>\r\n<after-view-checked *ngIf=\"hasCountDown\" (loaded)=\"handleReadyToGetWorkflowData()\">\r\n</after-view-checked>\r\n",
39243
39579
  providers: [ComponentContextService],
39244
39580
  styles: [".container-task-info .percent-done{background-color:#f0f0f0;border-radius:2px;height:5px;margin-top:5px;overflow:hidden;position:relative}.container-task-info .percent-done .detail{border-radius:2px;color:#fff;font-size:13px;height:5px;left:0;position:absolute;text-align:center;top:0}"]
39245
39581
  },] }
@@ -39410,8 +39746,10 @@ class BaseCongviecDinhkemComponent extends DataListBase {
39410
39746
  this.fileDataService = fileDataService;
39411
39747
  this.formState = FormState.VIEW;
39412
39748
  this.layoutFile = EnumFileLayout;
39413
- this.formModel = {};
39414
39749
  this.enumFormState = FormState;
39750
+ this.formModel = {};
39751
+ this.showAttachLinkBox = false;
39752
+ this.typedLink = '';
39415
39753
  }
39416
39754
  ngOnInit() {
39417
39755
  this.setting.objectName = 'mục đính kèm';
@@ -39491,37 +39829,59 @@ class BaseCongviecDinhkemComponent extends DataListBase {
39491
39829
  return __awaiter(this, void 0, void 0, function* () {
39492
39830
  const content = this._commonService.pasteByStorage();
39493
39831
  if (content) {
39494
- const obj = this.parseFromClipboard(content);
39495
- console.log('obj parsed', obj);
39832
+ const obj = this.parseAttachLink(content);
39496
39833
  if (obj.length > 0) {
39497
- this._notifierService.showSuccess('Đang thêm mục đính kèm');
39498
39834
  this._congViecDinhKemService.themDinhKemNghiepVu(this.taskId, obj).then(rs => {
39499
39835
  if (rs.success) {
39500
- this._notifierService.showSuccess('Thêm mục đính kèm thành công');
39836
+ this._notifierService.showSuccess('Thêm mục đính kèm thành công!');
39501
39837
  this.reload();
39502
39838
  this._commonService.clearClipboardStorage();
39503
39839
  }
39504
39840
  else {
39505
- this._notifierService.showWarning('Thêm mục đính kèm không thành công');
39841
+ this.showAttachLinkBox = true;
39506
39842
  }
39507
39843
  }).catch(err => {
39508
- console.error(err);
39509
- this._notifierService.showWarning('Thêm mục đính kèm không thành công');
39844
+ this.showAttachLinkBox = true;
39510
39845
  });
39511
39846
  }
39512
39847
  else {
39513
- this._notifierService.showWarning('Không tìm thấy mục đính kèm trong bộ nhớ tạm, vui lòng sao chép mục đính kèm vào bộ nhớ tạm trước khi thêm');
39848
+ this.showAttachLinkBox = true;
39514
39849
  }
39515
39850
  }
39516
39851
  else {
39517
- this._notifierService.showWarning('Không tìm thấy mục đính kèm trong bộ nhớ tạm, vui lòng sao chép mục đính kèm vào bộ nhớ tạm trước khi thêm');
39852
+ this.showAttachLinkBox = true;
39518
39853
  }
39519
39854
  });
39520
39855
  }
39856
+ addAttachLink() {
39857
+ if (this.typedLink && this.typedLink.length > 0) {
39858
+ const obj = this.parseAttachLink(this.typedLink);
39859
+ if (obj.length > 0) {
39860
+ this._congViecDinhKemService.themDinhKemNghiepVu(this.taskId, obj).then(rs => {
39861
+ if (rs.success) {
39862
+ this._notifierService.showSuccess('Thêm mục đính kèm thành công!');
39863
+ this.showAttachLinkBox = false;
39864
+ this.typedLink = '';
39865
+ this.reload();
39866
+ }
39867
+ else {
39868
+ this._notifierService.showWarning('Liên kết không hợp lệ!');
39869
+ }
39870
+ }).catch(err => {
39871
+ this._notifierService.showWarning('Liên kết không hợp lệ!');
39872
+ });
39873
+ }
39874
+ else {
39875
+ this._notifierService.showWarning('Liên kết không hợp lệ!');
39876
+ }
39877
+ }
39878
+ }
39879
+ focusInput(input) {
39880
+ input.focus();
39881
+ }
39521
39882
  // http://localhost:27230/universal-link?serviceCode=congviec&entity=DM_Priority&entityKey=0911f3e7-3db0-4b68-87cd-07d425741e9e&state=&sourcePath=http://localhost:27230/dm-priority
39522
- parseFromClipboard(content) {
39883
+ parseAttachLink(content) {
39523
39884
  const links = content.split('\r\n');
39524
- console.log('links', links);
39525
39885
  const op = [];
39526
39886
  for (const link of links) {
39527
39887
  const temp = link.split('universal-link')[1];
@@ -39565,7 +39925,7 @@ class BaseCongviecDinhkemComponent extends DataListBase {
39565
39925
  BaseCongviecDinhkemComponent.decorators = [
39566
39926
  { type: Component, args: [{
39567
39927
  selector: 'base-congviec-dinhkem',
39568
- template: "<crud-list #crudList [model]=\"model\" [setting]=\"setting\" [dataSource]=\"model.dataSource\" [hiddenAdd]=\"true\"\r\n [hiddenEdit]=\"true\" [hiddenDelete]=\"true\" [hiddenCopyLink]=\"true\" (onReload)=\"_triggerProcessData($event)\"\r\n (onView)=\"viewLinkItem($event)\" (onDelete)=\"deleteLinkItem($event)\"\r\n (onDeleteMultiple)=\"deleteLinkItemMultiple($event)\" (onReloaded)=\"_unmarkLoading()\">\r\n <ng-template #tieuDe let-rowData=\"rowData\">\r\n {{rowData.tenHienThiDoiTuong}}: [{{rowData.tieuDe}}]\r\n </ng-template>\r\n <ng-template #buttonAfterToolbar>\r\n <button *ngIf=\"formState == enumFormState.EDIT || formState == enumFormState.ADD\" type=\"button\" pButton pRipple label=\"Th\u00EAm m\u1EDBi\" icon=\"pi pi-plus\"\r\n class=\"p-button-text p-button-primary\" pTooltip=\"Th\u00EAm m\u1EDBi t\u1EEB b\u1ED9 nh\u1EDB t\u1EA1m\" (click)=\"themDinhKem()\"></button>\r\n <button type=\"button\" *ngIf=\"(formState == enumFormState.EDIT || formState == enumFormState.ADD) && model.selectedItems.length > 0\" pButton pRipple\r\n label=\"X\u00F3a\" icon=\"pi pi-trash\" class=\"p-button-rounded p-button-text p-button-danger\"\r\n (click)=\"deleteLinkItemMultiple($event)\"></button>\r\n </ng-template>\r\n <ng-template #function let-rowData=\"rowData\">\r\n <button *ngIf=\"formState == enumFormState.EDIT || formState == enumFormState.ADD\" type=\"button\" pButton pRipple icon=\"pi pi-trash\"\r\n class=\"p-button-rounded p-button-text p-button-danger\" pTooltip=\"H\u1EE7y \u0111\u00EDnh k\u00E8m\" tooltipPosition=\"top\"\r\n (click)=\"deleteLinkItem(rowData)\"></button>\r\n </ng-template>\r\n <ng-template #fileDinhKem let-rowData=\"rowData\">\r\n <file-manager [readonly]=\"true\" [serviceCode]=\"rowData.serviceCode\" [entity]=\"rowData.entity\"\r\n [entityKey]=\"rowData.entityKey\" [layout]=\"layoutFile.SIMPLE\" [fileDataService]=\"fileDataService\">\r\n </file-manager>\r\n </ng-template>\r\n</crud-list>\r\n\r\n<tn-dialog *ngIf=\"showDetailForm\" #dialog [styleClass]=\"'congviec-form tn-form-dialog'\"\r\n [header]=\"setting.popupHeader | translate\" [popupSize]=\"setting.popupSize\" (onHide)=\"showDetailForm = false\">\r\n <base-congviec-dinhkem-form #formBase [taskId]=\"taskId\" [parentModel]=\"model\" [parentContext]=\"context\"\r\n [model]=\"formModel\" (onSaved)=\"showDetailForm = false;crudList.reload()\" (onCancel)=\"_handleCancel($event)\"\r\n (onAfterSaved)=\"onAfterSaved($event)\">\r\n </base-congviec-dinhkem-form>\r\n</tn-dialog>",
39928
+ template: "<crud-list #crudList [model]=\"model\" [setting]=\"setting\" [dataSource]=\"model.dataSource\" [hiddenAdd]=\"true\"\r\n [hiddenEdit]=\"true\" [hiddenDelete]=\"true\" [hiddenCopyLink]=\"true\" (onReload)=\"_triggerProcessData($event)\"\r\n (onView)=\"viewLinkItem($event)\" (onDelete)=\"deleteLinkItem($event)\"\r\n (onDeleteMultiple)=\"deleteLinkItemMultiple($event)\" (onReloaded)=\"_unmarkLoading()\">\r\n <ng-template #tieuDe let-rowData=\"rowData\">\r\n {{rowData.tenHienThiDoiTuong}}: [{{rowData.tieuDe}}]\r\n </ng-template>\r\n <ng-template #buttonAfterToolbar>\r\n <button *ngIf=\"formState == enumFormState.EDIT || formState == enumFormState.ADD\" type=\"button\" pButton pRipple\r\n label=\"Th\u00EAm m\u1EDBi\" icon=\"pi pi-plus\" class=\"p-button-text p-button-primary\" (click)=\"themDinhKem()\"></button>\r\n <button type=\"button\"\r\n *ngIf=\"(formState == enumFormState.EDIT || formState == enumFormState.ADD) && model.selectedItems.length > 0\"\r\n pButton pRipple label=\"X\u00F3a\" icon=\"pi pi-trash\" class=\"p-button-rounded p-button-text p-button-danger\"\r\n (click)=\"deleteLinkItemMultiple($event)\"></button>\r\n </ng-template>\r\n <ng-template #function let-rowData=\"rowData\">\r\n <button *ngIf=\"formState == enumFormState.EDIT || formState == enumFormState.ADD\" type=\"button\" pButton pRipple\r\n icon=\"pi pi-trash\" class=\"p-button-rounded p-button-text p-button-danger\" pTooltip=\"H\u1EE7y \u0111\u00EDnh k\u00E8m\"\r\n tooltipPosition=\"top\" (click)=\"deleteLinkItem(rowData)\"></button>\r\n </ng-template>\r\n <ng-template #fileDinhKem let-rowData=\"rowData\">\r\n <file-manager [readonly]=\"true\" [serviceCode]=\"rowData.serviceCode\" [entity]=\"rowData.entity\"\r\n [entityKey]=\"rowData.entityKey\" [layout]=\"layoutFile.SIMPLE\" [fileDataService]=\"fileDataService\">\r\n </file-manager>\r\n </ng-template>\r\n</crud-list>\r\n\r\n<tn-dialog *ngIf=\"showDetailForm\" #dialog [styleClass]=\"'congviec-form tn-form-dialog'\"\r\n [header]=\"setting.popupHeader | translate\" [popupSize]=\"setting.popupSize\" (onHide)=\"showDetailForm = false\">\r\n <base-congviec-dinhkem-form #formBase [taskId]=\"taskId\" [parentModel]=\"model\" [parentContext]=\"context\"\r\n [model]=\"formModel\" (onSaved)=\"showDetailForm = false;crudList.reload()\" (onCancel)=\"_handleCancel($event)\"\r\n (onAfterSaved)=\"onAfterSaved($event)\">\r\n </base-congviec-dinhkem-form>\r\n</tn-dialog>\r\n\r\n<tn-dialog *ngIf=\"showAttachLinkBox\" #dialog2 [maximizable]=\"false\" [header]=\"'Nh\u1EADp li\u00EAn k\u1EBFt' | translate\"\r\n [popupSize]=\"{ width: 600, height: 50}\" (onHide)=\"showAttachLinkBox = false; typedLink=''\">\r\n <div class=\"p-col-12\">\r\n <div class=\"p-grid\">\r\n <div class=\"p-md-10\">\r\n <input #input type=\"text\" placeholder=\"Nh\u1EADp li\u00EAn k\u1EBFt sao ch\u00E9p t\u1EEB ph\u00E2n h\u1EC7 kh\u00E1c...\" pInputText\r\n class=\"p-col-12\" [(ngModel)]=\"typedLink\" (keyup.enter)=\"addAttachLink()\" />\r\n </div>\r\n <div class=\"p-md-2\">\r\n <button type=\"button\" pButton class=\"p-button-primary p-col-12\" label=\"Ok\"\r\n [disabled]=\"typedLink != ''? null : true\" (click)=\"addAttachLink()\"></button>\r\n </div>\r\n </div>\r\n </div>\r\n <after-view-checked (loaded)=\"focusInput(input)\"></after-view-checked>\r\n</tn-dialog>",
39569
39929
  providers: [ComponentContextService],
39570
39930
  styles: [""]
39571
39931
  },] }
@@ -39668,6 +40028,12 @@ class BaseCongViecFormComponent extends DataFormBase {
39668
40028
  this.autoFocus = true;
39669
40029
  this.enumFormState = FormState;
39670
40030
  this.enumLoaiDanhSachCongViec = EnumLoaiDanhSachCongViec;
40031
+ this.users = {
40032
+ taskName: '',
40033
+ assigner: 0,
40034
+ assignee: 0,
40035
+ relatedUsers: [],
40036
+ };
39671
40037
  this.tabDataChild = [
39672
40038
  {
39673
40039
  code: 'fileDinhKem',
@@ -39683,6 +40049,11 @@ class BaseCongViecFormComponent extends DataFormBase {
39683
40049
  code: 'taskLienQuan',
39684
40050
  icon: 'pi pi-share-alt',
39685
40051
  label: 'Công việc liên quan'
40052
+ },
40053
+ {
40054
+ code: 'traoDoiCongViec',
40055
+ icon: 'pi pi-comment',
40056
+ label: 'Trao đổi công việc',
39686
40057
  }
39687
40058
  ];
39688
40059
  this.handleChangeLoaiCongViecWhenAdd = (evt) => __awaiter(this, void 0, void 0, function* () {
@@ -39690,6 +40061,9 @@ class BaseCongViecFormComponent extends DataFormBase {
39690
40061
  yield this.loadWorkflowByLoaiCongViec(evt, evt.model.id);
39691
40062
  }
39692
40063
  });
40064
+ this.users.assigner = 0;
40065
+ this.users.assignee = 0;
40066
+ this.users.relatedUsers = [];
39693
40067
  }
39694
40068
  set tenCongViec(value) {
39695
40069
  this._tenCongViec = value;
@@ -39784,18 +40158,24 @@ class BaseCongViecFormComponent extends DataFormBase {
39784
40158
  this.setWorkflowDatasource(evt, workflowSetting);
39785
40159
  });
39786
40160
  }
39787
- onBeforeSave() {
39788
- }
39789
40161
  onAfterSave(res) {
39790
40162
  if (this.model.formState == FormState.ADD && res && res.success && res.data) {
39791
40163
  this.onAfterSaved.emit(res.data);
39792
40164
  }
39793
40165
  }
40166
+ onTabChange(evt) {
40167
+ this.currentTabIndex = evt.index;
40168
+ this.users.taskName = this.model.data.ten;
40169
+ }
40170
+ forcusToFirstInputControl(event) {
40171
+ event.preventDefault();
40172
+ this.context.fireEvent(ComCtxConstants.COMMON.FOCUS_TO_FIRST_INPUT_CONTROL);
40173
+ }
39794
40174
  }
39795
40175
  BaseCongViecFormComponent.decorators = [
39796
40176
  { type: Component, args: [{
39797
40177
  selector: 'base-congviec-form',
39798
- template: "<crud-form #crudForm [(data)]=\"model.data\" [setting]=\"setting\" [context]=\"context\" [disableCaching]=\"true\"\r\n [autoFocus]=\"autoFocus\" (onFormReady)=\"_handleFormReady($event)\">\r\n</crud-form>\r\n<base-congviec-dinhkem [loadDetailFromQueryParam]=\"false\" [formState]=\"model.formState\" [taskId]=\"model.data.id\">\r\n</base-congviec-dinhkem>\r\n<div class=\"tab-child\">\r\n <tn-tabview [data]=\"tabDataChild\">\r\n <ng-template #fileDinhKem>\r\n <file-manager [loadDetailFromQueryParam]=\"false\" [serviceCode]=\"setting.baseService.serviceCode\"\r\n [entity]=\"setting.baseService.entityName\" [entityKey]=\"model.data.id\"\r\n [readonly]=\"model.formState == enumFormState.VIEW\">\r\n </file-manager>\r\n </ng-template>\r\n <ng-template #taskChild>\r\n <div style=\"height: 100%\">\r\n <base-congviec [loadDetailFromQueryParam]=\"false\" [isChildView]=\"true\" [formState]=\"model.formState\"\r\n [loaiDanhSach]=\"enumLoaiDanhSachCongViec.CongViecCon\" [idCongViec]=\"model.data.id\">\r\n </base-congviec>\r\n </div>\r\n </ng-template>\r\n <ng-template #taskLienQuan>\r\n <base-congviec [loadDetailFromQueryParam]=\"false\" [isChildView]=\"true\" [formState]=\"model.formState\"\r\n [loaiDanhSach]=\"enumLoaiDanhSachCongViec.CongViecLienQuan\" [idCongViec]=\"model.data.id\">\r\n </base-congviec>\r\n </ng-template>\r\n </tn-tabview>\r\n</div>\r\n<ng-template #buttonTemplate>\r\n <button *ngIf=\"!model.data.__disableEdit && !__isFormView\" type=\"button\" pButton icon=\"pi pi-save\"\r\n class=\"p-button-text\" [label]=\"'FORM.SAVE' | translate\" (click)=\"_handleSave($event)\"></button>\r\n <button type=\"button\" pButton icon=\"pi pi-replay\" class=\"p-button-text p-button-secondary\"\r\n [label]=\"'FORM.CANCEL' | translate\" preventTab (click)=\"_handleCancel($event)\"></button>\r\n</ng-template>",
40178
+ template: "<crud-form #crudForm [(data)]=\"model.data\" [setting]=\"setting\" [context]=\"context\" [disableCaching]=\"true\"\r\n [autoFocus]=\"autoFocus\" (onFormReady)=\"_handleFormReady($event)\">\r\n</crud-form>\r\n<base-congviec-dinhkem [loadDetailFromQueryParam]=\"false\" [formState]=\"model.formState\" [taskId]=\"model.data.id\">\r\n</base-congviec-dinhkem>\r\n<div class=\"tab-child\">\r\n <tn-tabview [data]=\"tabDataChild\" (onTabChange)=\"onTabChange($event)\">\r\n <ng-template #fileDinhKem>\r\n <file-manager [loadDetailFromQueryParam]=\"false\" [serviceCode]=\"setting.baseService.serviceCode\"\r\n [entity]=\"setting.baseService.entityName\" [entityKey]=\"model.data.id\"\r\n [readonly]=\"model.formState == enumFormState.VIEW\">\r\n </file-manager>\r\n </ng-template>\r\n <ng-template #taskChild>\r\n <div style=\"height: 100%\">\r\n <base-congviec [loadDetailFromQueryParam]=\"false\" [isChildView]=\"true\" [formState]=\"model.formState\"\r\n [loaiDanhSach]=\"enumLoaiDanhSachCongViec.CongViecCon\" [idCongViec]=\"model.data.id\">\r\n </base-congviec>\r\n </div>\r\n </ng-template>\r\n <ng-template #taskLienQuan>\r\n <base-congviec [loadDetailFromQueryParam]=\"false\" [isChildView]=\"true\" [formState]=\"model.formState\"\r\n [loaiDanhSach]=\"enumLoaiDanhSachCongViec.CongViecLienQuan\" [idCongViec]=\"model.data.id\">\r\n </base-congviec>\r\n </ng-template>\r\n <ng-template #traoDoiCongViec>\r\n <div style=\"height: 350px;\">\r\n <chat-box [showSendMessageBox]=\"false\" [serviceCode]=\"'congviec'\" [entity]=\"'congviec'\"\r\n [taskId]=\"model.data.id\" [parentModel]=\"model\" [parentContext]=\"context\"\r\n [users]=\"users\"\r\n ></chat-box>\r\n </div>\r\n <chat-send-message-box [parentContext]=\"context\">\r\n </chat-send-message-box>\r\n </ng-template>\r\n </tn-tabview>\r\n</div>\r\n<ng-template #buttonTemplate>\r\n <button *ngIf=\"!model.data.__disableEdit && !__isFormView\" type=\"button\" pButton icon=\"pi pi-save\"\r\n class=\"p-button-text\" [label]=\"'FORM.SAVE' | translate\" (click)=\"_handleSave($event)\"></button>\r\n <button type=\"button\" pButton icon=\"pi pi-replay\" class=\"p-button-text p-button-secondary\"\r\n [label]=\"'FORM.CANCEL' | translate\" preventTab (click)=\"_handleCancel($event)\"></button>\r\n</ng-template>\r\n",
39799
40179
  providers: [ComponentContextService],
39800
40180
  styles: [".tab-child{padding:1em}"]
39801
40181
  },] }
@@ -40116,7 +40496,7 @@ class BaseCongViecComponent extends DataListBase {
40116
40496
  this.reload();
40117
40497
  }
40118
40498
  else {
40119
- this._notifierService.showWarningByReponse(response);
40499
+ this._notifierService.showWarningByResponse(response);
40120
40500
  }
40121
40501
  }, error => {
40122
40502
  this._notifierService.showDeleteDataError();
@@ -40130,7 +40510,7 @@ class BaseCongViecComponent extends DataListBase {
40130
40510
  this.reload();
40131
40511
  }
40132
40512
  else {
40133
- this._notifierService.showWarningByReponse(response);
40513
+ this._notifierService.showWarningByResponse(response);
40134
40514
  }
40135
40515
  }, error => {
40136
40516
  this._notifierService.showDeleteDataError();
@@ -41815,6 +42195,1180 @@ UsersFormatPipe.ctorParameters = () => [
41815
42195
  { type: UserService }
41816
42196
  ];
41817
42197
 
42198
+ class ServiceRequestModel {
42199
+ constructor(init) {
42200
+ this.service = '';
42201
+ this.entityInstanceId = '';
42202
+ this.parent = null;
42203
+ this.serviceCode = '';
42204
+ this.entity = '';
42205
+ this.entityKey = '';
42206
+ for (const key in init) {
42207
+ this[key] = init[key];
42208
+ }
42209
+ }
42210
+ }
42211
+
42212
+ class ContentsService extends BaseService {
42213
+ constructor(_injector, _httpClient, _moduleConfigService, _fileService) {
42214
+ super(_httpClient, _injector, `${_moduleConfigService.getConfig().environment.apiDomain.chatEndpoint}/${_moduleConfigService.getConfig().environment.apiVersion}/Contents`);
42215
+ this._moduleConfigService = _moduleConfigService;
42216
+ this._fileService = _fileService;
42217
+ this.entityName = 'Contents';
42218
+ this.serviceCode = 'chat';
42219
+ this.endPoint = `${_moduleConfigService.getConfig().environment.apiDomain.chatEndpoint}`;
42220
+ }
42221
+ getByService(model, page = 0) {
42222
+ const { serviceCode, entity, entityKey } = model;
42223
+ const url = `${this.serviceUri}/GetByService?serviceCode=${serviceCode}&entity=${entity}&entityKey=${entityKey}&page=${page}`;
42224
+ return this.defaultGet(url);
42225
+ }
42226
+ getByTaskId(model, taskId) {
42227
+ const { serviceCode, entity, entityKey } = model;
42228
+ const url = `${this.serviceUri}/GetByTaskId?serviceCode=${serviceCode}&entity=${entity}&entityKey=${entityKey}&taskId=${taskId}`;
42229
+ return this.defaultGet(url);
42230
+ }
42231
+ getContentById(data) {
42232
+ let url = `${this.serviceUri}/GetByChatId/${data.instanceId}`;
42233
+ if (data.page) {
42234
+ url += `${url}?page=${data.page}`;
42235
+ }
42236
+ return this.defaultGet(url);
42237
+ }
42238
+ sendMessage(messageContent) {
42239
+ const url = `${this.serviceUri}/SendMessage`;
42240
+ return this.defaultPost(url, messageContent);
42241
+ }
42242
+ markAsReadAllContents(chatId) {
42243
+ const url = `${this.serviceUri}ReadInfo/MarkAsReadAllContents/${chatId}`;
42244
+ return this.defaultPost(url, chatId);
42245
+ }
42246
+ }
42247
+ ContentsService.ɵprov = ɵɵdefineInjectable({ factory: function ContentsService_Factory() { return new ContentsService(ɵɵinject(INJECTOR), ɵɵinject(HttpClient), ɵɵinject(ModuleConfigService), ɵɵinject(FileExplorerService)); }, token: ContentsService, providedIn: "root" });
42248
+ ContentsService.decorators = [
42249
+ { type: Injectable, args: [{
42250
+ providedIn: 'root'
42251
+ },] }
42252
+ ];
42253
+ ContentsService.ctorParameters = () => [
42254
+ { type: Injector },
42255
+ { type: HttpClient },
42256
+ { type: ModuleConfigService },
42257
+ { type: FileExplorerService }
42258
+ ];
42259
+
42260
+ class StatusExtendsService extends BaseService {
42261
+ constructor(_injector, _http, _moduleConfigService) {
42262
+ super(_http, _injector, `${_moduleConfigService.getConfig().environment.apiDomain.chatEndpoint}/${_moduleConfigService.getConfig().environment.apiVersion}/StatusExtends`);
42263
+ this._moduleConfigService = _moduleConfigService;
42264
+ this.entityName = 'StatusExtends';
42265
+ this.serviceCode = 'chat';
42266
+ this.endPoint = `${_moduleConfigService.getConfig().environment.apiDomain.chatEndpoint}`;
42267
+ }
42268
+ insertUserOnline(chatId) {
42269
+ const statusExtends = { chatId: chatId };
42270
+ const url = `${this.serviceUri}/InsertUserOnline`;
42271
+ return this.defaultPost(url, statusExtends);
42272
+ }
42273
+ removeUserOnline(id) {
42274
+ return this.deleteById(id);
42275
+ }
42276
+ }
42277
+ StatusExtendsService.ɵprov = ɵɵdefineInjectable({ factory: function StatusExtendsService_Factory() { return new StatusExtendsService(ɵɵinject(INJECTOR), ɵɵinject(HttpClient), ɵɵinject(ModuleConfigService)); }, token: StatusExtendsService, providedIn: "root" });
42278
+ StatusExtendsService.decorators = [
42279
+ { type: Injectable, args: [{
42280
+ providedIn: 'root'
42281
+ },] }
42282
+ ];
42283
+ StatusExtendsService.ctorParameters = () => [
42284
+ { type: Injector },
42285
+ { type: HttpClient },
42286
+ { type: ModuleConfigService }
42287
+ ];
42288
+
42289
+ class ChatService extends BaseService {
42290
+ constructor(_injector, _httpClient, _moduleConfigService, _folderService, _myDriveService, _fileService, _contentService, _statusService) {
42291
+ super(_httpClient, _injector, `${_moduleConfigService.getConfig().environment.apiDomain.chatEndpoint}/${_moduleConfigService.getConfig().environment.apiVersion}/Instances`);
42292
+ this._moduleConfigService = _moduleConfigService;
42293
+ this._folderService = _folderService;
42294
+ this._myDriveService = _myDriveService;
42295
+ this._fileService = _fileService;
42296
+ this._contentService = _contentService;
42297
+ this._statusService = _statusService;
42298
+ this.entityName = 'Instances';
42299
+ this.serviceCode = 'chat';
42300
+ this.SERVICE = 'chat';
42301
+ this.ENTITY_CONTENT = 'contents';
42302
+ this.endPoint = `${_moduleConfigService.getConfig().environment.apiDomain.chatEndpoint}`;
42303
+ }
42304
+ getListAttachment(id) {
42305
+ return __awaiter(this, void 0, void 0, function* () {
42306
+ const request = new ServiceRequestModel({
42307
+ service: this.SERVICE,
42308
+ serviceCode: this.SERVICE,
42309
+ entity: this.ENTITY_CONTENT,
42310
+ entityInstanceId: id,
42311
+ entityKey: 'id',
42312
+ });
42313
+ // const result = await this._folderService.getServiceFolderId(request);
42314
+ // if (!result.success || !result.data) {
42315
+ // return [];
42316
+ // }
42317
+ // const folder = await this._folderService.getDetail(result.data);
42318
+ // // const folder = await this._myDriveService.getByFolderId(result.data);
42319
+ // if (result.success) {
42320
+ // if (folder.data.length > 0) {
42321
+ // return folder.data.map(x => {
42322
+ // const item = <any>{
42323
+ // id: x.id,
42324
+ // fileName: x.name,
42325
+ // type: this._commonService.isImage(x.name) ? 'image' : ''
42326
+ // };
42327
+ //
42328
+ // item.url = this._fileService.getFileDownloadUrl(x.id);
42329
+ //
42330
+ // return item;
42331
+ // });
42332
+ // }
42333
+ // }
42334
+ return [];
42335
+ });
42336
+ }
42337
+ getChatId(model) {
42338
+ const { serviceCode, entity, entityKey } = model;
42339
+ const url = `${this.serviceUri}/GetIdByService?serviceCode=${serviceCode}&entity=${entity}&entityKey=${entityKey}`;
42340
+ return this.defaultGet(url);
42341
+ }
42342
+ getChatIdByTask(serviceRequest, taskId) {
42343
+ const { serviceCode, entity, entityKey } = serviceRequest;
42344
+ const url = `${this.serviceUri}/GetIdByTaskId?serviceCode=${serviceCode}&entity=${entity}&entityKey=${entityKey}&taskId=${taskId}`;
42345
+ return this.defaultGet(url);
42346
+ }
42347
+ getByService(model, page = 0) {
42348
+ return this._contentService.getByService(model, page);
42349
+ }
42350
+ getContentByTaskId(serviceRequest, taskId) {
42351
+ return this._contentService.getByTaskId(serviceRequest, taskId);
42352
+ }
42353
+ markAsReadAllContents(chatId) {
42354
+ return this._contentService.markAsReadAllContents(chatId);
42355
+ }
42356
+ sendMessage(messageContent) {
42357
+ return this._contentService.sendMessage(messageContent);
42358
+ }
42359
+ insertUserOnline(chatId) {
42360
+ return this._statusService.insertUserOnline(chatId);
42361
+ }
42362
+ removeUserOnline(id) {
42363
+ return this._statusService.removeUserOnline(id);
42364
+ }
42365
+ }
42366
+ ChatService.ɵprov = ɵɵdefineInjectable({ factory: function ChatService_Factory() { return new ChatService(ɵɵinject(INJECTOR), ɵɵinject(HttpClient), ɵɵinject(ModuleConfigService), ɵɵinject(FolderService), ɵɵinject(MyDriveService), ɵɵinject(FileExplorerService), ɵɵinject(ContentsService), ɵɵinject(StatusExtendsService)); }, token: ChatService, providedIn: "root" });
42367
+ ChatService.decorators = [
42368
+ { type: Injectable, args: [{
42369
+ providedIn: 'root'
42370
+ },] }
42371
+ ];
42372
+ ChatService.ctorParameters = () => [
42373
+ { type: Injector },
42374
+ { type: HttpClient },
42375
+ { type: ModuleConfigService },
42376
+ { type: FolderService },
42377
+ { type: MyDriveService },
42378
+ { type: FileExplorerService },
42379
+ { type: ContentsService },
42380
+ { type: StatusExtendsService }
42381
+ ];
42382
+
42383
+ class MessageBoardService extends BaseService {
42384
+ constructor(_injector, _http, _moduleConfigService) {
42385
+ super(_http, _injector, `${_moduleConfigService.getConfig().environment.apiDomain.chatEndpoint}/${_moduleConfigService.getConfig().environment.apiVersion}/MessageBoards`);
42386
+ this._moduleConfigService = _moduleConfigService;
42387
+ this.entityName = 'MessageBoards';
42388
+ this.serviceCode = 'chat';
42389
+ this.endPoint = `${this._moduleConfigService.getConfig().environment.apiDomain.chatEndpoint}`;
42390
+ }
42391
+ pinMessage(messageId, pinned, correlationId) {
42392
+ const url = `${this.serviceUri}/PinnedMessage`;
42393
+ return this.defaultPost(url, { pinned: pinned, id: messageId, correlationId: correlationId });
42394
+ }
42395
+ getLatestPinnedMessage(chatId) {
42396
+ const url = `${this.serviceUri}/GetLatestPinnedMessage?chatId=${chatId}`;
42397
+ return this.defaultGet(url);
42398
+ }
42399
+ getListPinnedMessage(chatId) {
42400
+ const url = `${this.serviceUri}/GetListPinnedMessage?chatId=${chatId}`;
42401
+ return this.defaultGet(url);
42402
+ }
42403
+ }
42404
+ MessageBoardService.ɵprov = ɵɵdefineInjectable({ factory: function MessageBoardService_Factory() { return new MessageBoardService(ɵɵinject(INJECTOR), ɵɵinject(HttpClient), ɵɵinject(ModuleConfigService)); }, token: MessageBoardService, providedIn: "root" });
42405
+ MessageBoardService.decorators = [
42406
+ { type: Injectable, args: [{
42407
+ providedIn: 'root'
42408
+ },] }
42409
+ ];
42410
+ MessageBoardService.ctorParameters = () => [
42411
+ { type: Injector },
42412
+ { type: HttpClient },
42413
+ { type: ModuleConfigService }
42414
+ ];
42415
+
42416
+ class CheckControlVisibleService {
42417
+ constructor() { }
42418
+ checkDisplayStatus(elem) {
42419
+ return new Promise((resolve, reject) => {
42420
+ this.doCheck(resolve, elem);
42421
+ });
42422
+ }
42423
+ doCheck(resolve, elem) {
42424
+ let timeoutCheckDisplayStatus;
42425
+ timeoutCheckDisplayStatus = setTimeout(() => {
42426
+ this.doCheck(resolve, elem);
42427
+ }, 100);
42428
+ var newStatus = this.isVisible(elem);
42429
+ if (newStatus) {
42430
+ setTimeout(() => {
42431
+ // show control
42432
+ resolve(true);
42433
+ });
42434
+ clearTimeout(timeoutCheckDisplayStatus);
42435
+ }
42436
+ }
42437
+ isVisible(elem) {
42438
+ const style = getComputedStyle(elem);
42439
+ if (style.display === 'none')
42440
+ return false;
42441
+ if (style.visibility !== 'visible')
42442
+ return false;
42443
+ if (+style.opacity < 0.1)
42444
+ return false;
42445
+ if (elem.offsetWidth + elem.offsetHeight + elem.getBoundingClientRect().height +
42446
+ elem.getBoundingClientRect().width === 0) {
42447
+ return false;
42448
+ }
42449
+ const elemCenter = {
42450
+ x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
42451
+ y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
42452
+ };
42453
+ let pointContainer = document.elementFromPoint(elemCenter.x, elemCenter.y);
42454
+ if (pointContainer) {
42455
+ do {
42456
+ if (pointContainer === elem)
42457
+ return true;
42458
+ } while (pointContainer = pointContainer.parentNode);
42459
+ }
42460
+ return false;
42461
+ }
42462
+ }
42463
+ CheckControlVisibleService.ɵprov = ɵɵdefineInjectable({ factory: function CheckControlVisibleService_Factory() { return new CheckControlVisibleService(); }, token: CheckControlVisibleService, providedIn: "root" });
42464
+ CheckControlVisibleService.decorators = [
42465
+ { type: Injectable, args: [{
42466
+ providedIn: 'root'
42467
+ },] }
42468
+ ];
42469
+ CheckControlVisibleService.ctorParameters = () => [];
42470
+
42471
+ const NEW_MESSAGE = 'NewMessage';
42472
+ const PINNED_CHANGED = 'PinnedChanged';
42473
+ var NotificationType;
42474
+ (function (NotificationType) {
42475
+ NotificationType[NotificationType["NewMessage"] = 0] = "NewMessage";
42476
+ NotificationType[NotificationType["PinnedChanged"] = 1] = "PinnedChanged";
42477
+ })(NotificationType || (NotificationType = {}));
42478
+ var MessageType;
42479
+ (function (MessageType) {
42480
+ MessageType[MessageType["TEXT"] = 0] = "TEXT";
42481
+ MessageType[MessageType["FILE"] = 1] = "FILE";
42482
+ })(MessageType || (MessageType = {}));
42483
+
42484
+ // fix for build prod
42485
+ const moment$1 = moment_;
42486
+ class ChatBoxComponent extends ComponentBase {
42487
+ constructor(injector, _chatService, _messageBoardService, _userService, _checkControlVisible, _signalrService, _fileService, _crudService, _notifierService, _moduleConfigService) {
42488
+ super(injector);
42489
+ this._chatService = _chatService;
42490
+ this._messageBoardService = _messageBoardService;
42491
+ this._userService = _userService;
42492
+ this._checkControlVisible = _checkControlVisible;
42493
+ this._signalrService = _signalrService;
42494
+ this._fileService = _fileService;
42495
+ this._crudService = _crudService;
42496
+ this._notifierService = _notifierService;
42497
+ this._moduleConfigService = _moduleConfigService;
42498
+ this.showSendMessageBox = true;
42499
+ this.userPickerForm = {
42500
+ selectedValue: [],
42501
+ data: null,
42502
+ };
42503
+ this.topic = '';
42504
+ this.firstTime = true;
42505
+ this.multiple = true;
42506
+ this.showAddNoteForm = false;
42507
+ this.fileApi = '';
42508
+ this.peopleAll = [];
42509
+ this.correlationIds = [];
42510
+ this.attachments = [];
42511
+ this.image = '';
42512
+ this.peopleAllUsers = [];
42513
+ this.peopleRelatedUsers = [];
42514
+ this.editFormModel = {};
42515
+ this._moduleConfig = this._moduleConfigService.getConfig();
42516
+ this.environment = this._moduleConfig.environment;
42517
+ this.defaultAvatar = this.environment.appMetadata.main.defaultMaleAvatar;
42518
+ this.fileApi = this.environment.apiDomain.fileEndpoint;
42519
+ this.model.userPickerForm = { popupSize: PopupSize, data: {} };
42520
+ this.model.quickNoteForm = { popupSize: {}, data: {} };
42521
+ this.context.subscribe('QUICK_NOTE_POPUP.CLOSE_POPUP', response => {
42522
+ this.model.editFormModel.showQuickNoteForm = false;
42523
+ });
42524
+ }
42525
+ updateUsers(assignee, assigner, relatedUser) {
42526
+ this.assignee = assignee;
42527
+ this.assigner = assigner;
42528
+ this.relatedUser = relatedUser;
42529
+ let all = [];
42530
+ all.push(assignee);
42531
+ all.push(assigner);
42532
+ if (this.relatedUser.length > 0) {
42533
+ all = all.concat(relatedUser);
42534
+ }
42535
+ this.peopleAll = all.filter((x, i, a) => a.indexOf(x) == i);
42536
+ }
42537
+ ngOnInit() {
42538
+ this.initClassVar();
42539
+ this.getMessages(null);
42540
+ this._chatService.getChatIdByTask(this.serviceRequestModel, this.taskId).then(rs => {
42541
+ if (!rs.success)
42542
+ this._notifierService.showWarning(rs.message);
42543
+ if (!rs.data)
42544
+ return;
42545
+ this.model.id = rs.data;
42546
+ this.rootContext.fireEvent(ComCtxConstants.ROOT.CHAT_INSTANCE_ID_LOADED, this.model.id);
42547
+ this.topic = `chat.${this.model.id}`;
42548
+ this._signalrService.start(null, this.topic, data => this.handleChanges(data));
42549
+ // get pinned message
42550
+ if (this.model.id) {
42551
+ this._messageBoardService.getLatestPinnedMessage(this.model.id).then(rs => {
42552
+ if (rs.data) {
42553
+ this.model.pinnedMessage = rs.data.content;
42554
+ }
42555
+ });
42556
+ }
42557
+ });
42558
+ this.rootContext.subscribe(ComCtxConstants.ROOT.CHAT_MESSAGE_SENDING, (data) => __awaiter(this, void 0, void 0, function* () {
42559
+ this.model.correlationIds.push(data.message.correlationId);
42560
+ if (data.attachments && data.attachments.length > 0) {
42561
+ data.attachments = data.attachments.map(x => {
42562
+ x.url = null;
42563
+ return x;
42564
+ });
42565
+ }
42566
+ const temp = yield this.appendMessage(data.message.messageContent, 'own', 'sending', this.currentUser.userName, data.attachments, data.message.correlationId, false);
42567
+ console.log(temp);
42568
+ }));
42569
+ this.rootContext.subscribe(ComCtxConstants.ROOT.CHAT_MESSAGE_SENT, data => {
42570
+ });
42571
+ this.rootContext.subscribe(ComCtxConstants.ROOT.CHAT_LOAD_MORE, data => {
42572
+ // this.getMessages(this.model.createdFrom);
42573
+ });
42574
+ this.rootContext.subscribe(ComCtxConstants.ROOT.CHAT_SCROLLING, scrolling => {
42575
+ if (scrolling) {
42576
+ this.model.scrolling = true;
42577
+ }
42578
+ else {
42579
+ this.model.scrolling = false;
42580
+ this.model.newMessageNotUpdatedCount = 0;
42581
+ }
42582
+ });
42583
+ this.rootContext.subscribe(ComCtxConstants.ROOT.CHAT_HAS_NEW_MESSAGE_NOT_UPDATED, count => {
42584
+ this.model.scrolling = count !== 0;
42585
+ this.model.newMessageNotUpdatedCount = count;
42586
+ });
42587
+ this.context.subscribe('CLOSE_POPUP', rs => {
42588
+ this.model.userPickerForm.show = false;
42589
+ this.parentContext.fireEvent('TASK.RELATED_USER_CHANGED', rs);
42590
+ });
42591
+ this.parentContext.subscribe('TASK.DATA_CHANGED', rs => {
42592
+ this.updateUsers(rs.assignee, rs.assigner, rs.relatedUser);
42593
+ });
42594
+ }
42595
+ handleChanges(data) {
42596
+ return __awaiter(this, void 0, void 0, function* () {
42597
+ const newMessage = JSON.parse(data);
42598
+ if (!newMessage || !newMessage.data) {
42599
+ this._notifierService.showWarning('SYS_ERR_DEV: Lỗi SignalR');
42600
+ return;
42601
+ }
42602
+ switch (newMessage.notificationType) {
42603
+ case NotificationType.NewMessage:
42604
+ case NEW_MESSAGE: {
42605
+ yield this.handleNewMessageNotification(newMessage.data);
42606
+ break;
42607
+ }
42608
+ case NotificationType.PinnedChanged:
42609
+ case PINNED_CHANGED: {
42610
+ const ind = this.model.correlationIds.findIndex(x => x == newMessage.correlationId);
42611
+ if (ind > -1) {
42612
+ this.model.correlationIds.splice(ind, 1);
42613
+ }
42614
+ else {
42615
+ yield this.handlePinnedChangeNotification(newMessage.data);
42616
+ }
42617
+ break;
42618
+ }
42619
+ }
42620
+ });
42621
+ }
42622
+ initClassVar() {
42623
+ this.fileViewerModel = {
42624
+ data: {},
42625
+ showEditForm: false,
42626
+ };
42627
+ this.userPickerControl = new UserPickerControlSchema({
42628
+ field: 'id',
42629
+ label: '',
42630
+ fullLabel: '',
42631
+ multiple: true,
42632
+ hiddenCheck: () => this.userPickerForm.show,
42633
+ });
42634
+ this.serviceRequestModel = {
42635
+ service: this.serviceCode,
42636
+ serviceCode: this.serviceCode,
42637
+ entity: this.entity,
42638
+ entityKey: 'id',
42639
+ entityInstanceId: this.taskId
42640
+ };
42641
+ this.model.dataSource = [];
42642
+ this.model.correlationIds = [];
42643
+ this.model.attachments = [];
42644
+ this.model.maxFileSize = 3000000;
42645
+ this.model.img = {};
42646
+ this.currentUser = this._userService.getCurrentUser();
42647
+ this.peopleAllUsers = [];
42648
+ this.peopleRelatedUsers = [];
42649
+ this.model.editFormModel = [];
42650
+ if (this.users) {
42651
+ this.model.taskName = this.users.taskName;
42652
+ this.updateUsers(this.users.assignee, this.users.assigner, this.users.relatedUsers);
42653
+ this.getRelatedUserInfo();
42654
+ }
42655
+ }
42656
+ getRelatedUserInfo() {
42657
+ return __awaiter(this, void 0, void 0, function* () {
42658
+ const peopleRelatedUsers = yield this._userService.getBasicUsersInfo(this.relatedUser.join());
42659
+ if (peopleRelatedUsers == null || peopleRelatedUsers.length == 0) {
42660
+ return;
42661
+ }
42662
+ for (const item of peopleRelatedUsers) {
42663
+ this.peopleRelatedUsers.push({
42664
+ title: item.fullName,
42665
+ label: item.fullName,
42666
+ value: item.id
42667
+ });
42668
+ }
42669
+ });
42670
+ }
42671
+ handlePinnedChangeNotification(data) {
42672
+ return __awaiter(this, void 0, void 0, function* () {
42673
+ if (data.pinned) {
42674
+ this.model.pinnedMessage = data.message;
42675
+ }
42676
+ else {
42677
+ this.model.pinnedMessage = null;
42678
+ }
42679
+ });
42680
+ }
42681
+ handleNewMessageNotification(newMessage) {
42682
+ return __awaiter(this, void 0, void 0, function* () {
42683
+ const ind = this.model.correlationIds.findIndex(x => x == newMessage.correlationId);
42684
+ if (newMessage.messageType == MessageType.FILE) {
42685
+ newMessage.attachments = yield this._chatService.getListAttachment(newMessage.id);
42686
+ }
42687
+ if (ind === -1) {
42688
+ yield this.appendMessage(newMessage.content, this.getTypeOfMessage(newMessage.createdBy), 'received', newMessage.createdBy, newMessage.attachments, '', true);
42689
+ }
42690
+ else {
42691
+ this.updateMessage(newMessage.correlationId, newMessage);
42692
+ this.model.correlationIds.splice(ind, 1);
42693
+ }
42694
+ });
42695
+ }
42696
+ getMessages(createdFrom) {
42697
+ this._chatService.getContentByTaskId(this.serviceRequestModel, this.taskId).then((rs) => __awaiter(this, void 0, void 0, function* () {
42698
+ const currentUserName = this.currentUser.userName;
42699
+ let nearByCreated = '';
42700
+ let index = 0;
42701
+ let userNames = '';
42702
+ if (!rs.success) {
42703
+ return this._notifierService.showWarning(rs.message);
42704
+ }
42705
+ for (const item of rs.data) {
42706
+ if (item.createdBy && item.createdBy != '')
42707
+ userNames += `${index == 0 ? '' : ','}${item.createdBy}`;
42708
+ if (index === 0)
42709
+ this.model.createdFrom = item.created;
42710
+ item.type = item.createdBy === currentUserName ? 'own' : 'from';
42711
+ if (item.messageType === MessageType.FILE) {
42712
+ item.attachments = yield this._chatService.getListAttachment(item.id);
42713
+ }
42714
+ item.isLastMessageFlow = false;
42715
+ if (item.createdBy !== nearByCreated) {
42716
+ if (+item > -0) {
42717
+ rs.data[+item - 1].isLastMessageFlow = true;
42718
+ }
42719
+ nearByCreated = item.createdBy;
42720
+ item.isFirstMessageFlow = true;
42721
+ }
42722
+ else {
42723
+ item.isFirstMessageFlow = false;
42724
+ }
42725
+ if (+index === rs.data.length - 1)
42726
+ item.isLastMessageFlow = true;
42727
+ index++;
42728
+ }
42729
+ if (createdFrom) {
42730
+ this.model.dataSource = [...rs.data, ...this.model.dataSource];
42731
+ }
42732
+ else {
42733
+ this.model.dataSource = rs.data;
42734
+ }
42735
+ if (userNames != '') {
42736
+ const userInfos = yield this._userService.getBasicUsersInfoByUserNames(userNames);
42737
+ if (userInfos != null) {
42738
+ for (const item of this.model.dataSource) {
42739
+ const user = userInfos.find(x => x.userName == item.createdBy);
42740
+ if (!user) {
42741
+ continue;
42742
+ }
42743
+ item.avatar = user.avatar;
42744
+ item.fullName = user.fullName;
42745
+ }
42746
+ }
42747
+ }
42748
+ this.rootContext.fireEvent(ComCtxConstants.ROOT.CHAT_DATA_LOADED, true);
42749
+ }));
42750
+ }
42751
+ scrollToBottom(speed = 0, force = false, sent) {
42752
+ if (!this.model.scrolling) {
42753
+ this.rootContext.fireEvent(ComCtxConstants.ROOT.CHAT_HAS_NEW_MESSAGE, { speed, force: true });
42754
+ }
42755
+ else if (sent !== false) {
42756
+ this.rootContext.fireEvent(ComCtxConstants.ROOT.CHAT_HAS_NEW_MESSAGE, { speed, force });
42757
+ }
42758
+ }
42759
+ appendMessage(message, type, status, createdBy, attachments = [], correlationId = '', sent) {
42760
+ var _a, _b;
42761
+ return __awaiter(this, void 0, void 0, function* () {
42762
+ let fullName = '';
42763
+ let avatar = '';
42764
+ const user = yield this._userService.getBasicUserInfoByUserName(createdBy);
42765
+ fullName = (_a = user.fullName) !== null && _a !== void 0 ? _a : '';
42766
+ avatar = (_b = user.avatar) !== null && _b !== void 0 ? _b : '';
42767
+ if (attachments && attachments.length > 0) {
42768
+ const clonedAttachment = JSON.parse(JSON.stringify(attachments));
42769
+ this.model.dataSource.push({
42770
+ created: new Date(),
42771
+ createdBy: createdBy,
42772
+ fullName: fullName,
42773
+ status: status,
42774
+ type: type,
42775
+ avatar: avatar,
42776
+ attachments: clonedAttachment,
42777
+ correlationId: correlationId,
42778
+ isFirstMessageFlow: false,
42779
+ isLastMessageFlow: false,
42780
+ sent: sent
42781
+ });
42782
+ this.updateFirstOrLastMessage();
42783
+ }
42784
+ if (message && message.trim() != '') {
42785
+ this.model.dataSource.push({
42786
+ created: new Date(),
42787
+ createdBy: createdBy,
42788
+ fullName: fullName,
42789
+ content: message,
42790
+ status: status,
42791
+ type: type,
42792
+ avatar: avatar,
42793
+ correlationId: correlationId,
42794
+ isFirstMessageFlow: false,
42795
+ isLastMessageFlow: false,
42796
+ sent: sent
42797
+ });
42798
+ this.updateFirstOrLastMessage();
42799
+ }
42800
+ return this.model.dataSource;
42801
+ });
42802
+ }
42803
+ updateFirstOrLastMessage() {
42804
+ if (this.model.dataSource.length > 0) {
42805
+ const length = this.model.dataSource.length;
42806
+ if (length === 1) {
42807
+ this.model.dataSource[0].isFirstMessageFlow = true;
42808
+ }
42809
+ else {
42810
+ const createdBy = this.model.dataSource[length - 2].createdBy;
42811
+ const createdBy2 = this.model.dataSource[length - 1].createdBy;
42812
+ if (createdBy !== createdBy2) {
42813
+ this.model.dataSource[length - 2].isLastMessageFlow = true;
42814
+ this.model.dataSource[length - 1].isFirstMessageFlow = true;
42815
+ }
42816
+ else {
42817
+ this.model.dataSource[length - 2].isLastMessageFlow = false;
42818
+ this.model.dataSource[length - 1].isLastMessageFlow = true;
42819
+ }
42820
+ }
42821
+ }
42822
+ }
42823
+ updateMessage(correlationId, message) {
42824
+ const item = this.model.dataSource.find(x => x.correlationId === correlationId);
42825
+ if (item) {
42826
+ if (message.attachments && message.attachments.length > 0) {
42827
+ item.attachments = message.attachments;
42828
+ }
42829
+ item.id = message.id;
42830
+ item.sent = true;
42831
+ }
42832
+ }
42833
+ updateMessageStatus(message, status, errorMessage = '') {
42834
+ const item = this.model.dataSource.find(x => x.message === message);
42835
+ item.status = status;
42836
+ item.errorMessage = errorMessage;
42837
+ }
42838
+ getDisplayStatus(status) {
42839
+ switch (status) {
42840
+ case 'sending':
42841
+ return 'Đang gửi';
42842
+ case 'sent':
42843
+ return 'Đã gửi';
42844
+ default:
42845
+ return '';
42846
+ }
42847
+ }
42848
+ ngOnDestroy() {
42849
+ // unscrible signalr
42850
+ this._signalrService.unSubscribeViewCode(null, this.topic);
42851
+ this.rootContext.unSubscribe(ComCtxConstants.ROOT.CHAT_MESSAGE_SENDING);
42852
+ this.rootContext.unSubscribe(ComCtxConstants.ROOT.CHAT_MESSAGE_SENT);
42853
+ this.rootContext.unSubscribe(ComCtxConstants.ROOT.CHAT_LOAD_MORE);
42854
+ this.rootContext.unSubscribe(ComCtxConstants.ROOT.CHAT_SCROLLING);
42855
+ this.rootContext.unSubscribe(ComCtxConstants.ROOT.CHAT_HAS_NEW_MESSAGE_NOT_UPDATED);
42856
+ super.ngOnDestroy();
42857
+ }
42858
+ getTypeOfMessage(createdBy) {
42859
+ return createdBy === this.currentUser.userName ? 'own' : 'from';
42860
+ }
42861
+ trackByFunc(index, item) {
42862
+ return item.id;
42863
+ }
42864
+ trackAttachmentByFunc(index, item) {
42865
+ return item.fileName;
42866
+ }
42867
+ handlePaste(event) {
42868
+ const objectData = this.getImageClipboardData(event);
42869
+ if (objectData) {
42870
+ this.model.attachments.push({
42871
+ type: 'image',
42872
+ url: objectData.url,
42873
+ data: objectData.blob,
42874
+ fileName: this._commonService.guid() + '.png'
42875
+ });
42876
+ }
42877
+ }
42878
+ getImageClipboardData(e) {
42879
+ for (let i = 0; i < e.clipboardData.items.length; i++) {
42880
+ const item = e.clipboardData.items[i];
42881
+ if (item.type.indexOf('image') != -1) {
42882
+ const imageObj = item.getAsFile();
42883
+ if (imageObj.size < this.model.maxFileSize) {
42884
+ return { url: URL.createObjectURL(imageObj), blob: imageObj };
42885
+ }
42886
+ else {
42887
+ return null;
42888
+ }
42889
+ }
42890
+ }
42891
+ return null;
42892
+ }
42893
+ viewOrDownloadFile(evt, attachmentItem) {
42894
+ return __awaiter(this, void 0, void 0, function* () {
42895
+ if (this._fileService.isSupportedViewOnline(attachmentItem.fileName)) {
42896
+ // this.model.fileViewer.data = {};
42897
+ // this.model.fileViewer.data.fileId = attachmentItem.id;
42898
+ // this.model.fileViewer.data.fileName = attachmentItem.fileName;
42899
+ // this.model.fileViewer.data.isFileVersion = false;
42900
+ // this.model.fileViewer.show = true;
42901
+ this.fileViewerModel = {
42902
+ data: {
42903
+ fileId: attachmentItem.id,
42904
+ fileName: attachmentItem.fileName,
42905
+ isFileVersion: false,
42906
+ },
42907
+ showEditForm: true,
42908
+ };
42909
+ }
42910
+ else {
42911
+ top.location.href = yield this.getDownloadLink(attachmentItem);
42912
+ }
42913
+ });
42914
+ }
42915
+ getDownloadLink(file) {
42916
+ return new Promise((resolve, reject) => {
42917
+ const model = new GenerateLinkDownloadDTO();
42918
+ model.fileId = file.id;
42919
+ model.isFileVersion = false;
42920
+ this._fileService.generateLinkDownload(model)
42921
+ .then(response => {
42922
+ const downloadUrl = this._fileService.getAnonymousDownloadUrl(response.data);
42923
+ resolve(downloadUrl);
42924
+ }, error => {
42925
+ throw new Error('Cannot get download link');
42926
+ });
42927
+ });
42928
+ }
42929
+ browseFileFromPersonal() {
42930
+ }
42931
+ browseFileFromComputer() {
42932
+ this.fileElement.advancedFileInput.nativeElement.click();
42933
+ }
42934
+ onSelectFileFromComputer(evt) {
42935
+ try {
42936
+ if (evt.files && evt.files.length > 0) {
42937
+ for (let index = 0; index < evt.files.length; index++) {
42938
+ const fileName = evt.files[index].name;
42939
+ const type = this._commonService.isImage(fileName) ? 'image' : 'file';
42940
+ const attachmentItem = {
42941
+ type: type,
42942
+ data: evt.files[index], fileName: fileName
42943
+ };
42944
+ if (attachmentItem.type == 'image') {
42945
+ attachmentItem.url = evt.files[index].objectURL.changingThisBreaksApplicationSecurity;
42946
+ }
42947
+ this.model.attachments.push(attachmentItem);
42948
+ }
42949
+ }
42950
+ }
42951
+ catch (e) {
42952
+ console.error('error on process select file computer', e);
42953
+ }
42954
+ // this.fileElement.clear();
42955
+ }
42956
+ removeAttachment(item) {
42957
+ const ind = this.model.attachments.findIndex(x => x.url === item.url);
42958
+ this.model.attachments.splice(ind, 1);
42959
+ }
42960
+ hasAttachment(item) {
42961
+ return item.attachments && item.attachments.length > 0;
42962
+ }
42963
+ loadImg(evt, parentIndex, index) {
42964
+ this.model.img[`${parentIndex}${index}`] = true;
42965
+ this.model.img[`${parentIndex}width${index}`] = (evt.target.width + 32) + 'px';
42966
+ }
42967
+ inTheSameTime(i, item, dataSource) {
42968
+ if (i < dataSource.length - 1) {
42969
+ const d1 = new Date(dataSource[i + 1].created);
42970
+ const d2 = new Date(item.created);
42971
+ const ms = d1.getTime() - d2.getTime();
42972
+ return ms < 30000;
42973
+ }
42974
+ return false;
42975
+ }
42976
+ pinMessage(item) {
42977
+ if (this.model.pinnedMessage) {
42978
+ if (this.model.pinnedMessage.id != item.id) {
42979
+ this._notifierService.showConfirm('Bạn có chắc chắn muốn ghim tin nhắn này? Tin nhắn đã ghim trước đó sẽ được bỏ ghim.').then(rs => {
42980
+ if (!rs)
42981
+ return;
42982
+ this.doPin(item, item.id, true);
42983
+ });
42984
+ }
42985
+ else {
42986
+ this.doPin(item, item.id, false);
42987
+ }
42988
+ }
42989
+ else {
42990
+ this.doPin(item, item.id, true);
42991
+ }
42992
+ }
42993
+ doPin(item, id, pinned) {
42994
+ const correlationId = this._commonService.guid();
42995
+ this.model.correlationIds.push(correlationId);
42996
+ this._messageBoardService.pinMessage(id, pinned, correlationId).then(rs => {
42997
+ if (pinned) {
42998
+ this.model.pinnedMessage = item;
42999
+ }
43000
+ else {
43001
+ this.model.pinnedMessage = null;
43002
+ }
43003
+ });
43004
+ }
43005
+ getCurrentUserAvatar(avatar) {
43006
+ if (avatar != null) {
43007
+ return `${this.fileApi}/file/public/${avatar}/Download`;
43008
+ }
43009
+ else {
43010
+ return this.defaultAvatar;
43011
+ }
43012
+ }
43013
+ addPeople() {
43014
+ this.userPickerForm.selectedValue = this.peopleRelatedUsers;
43015
+ this.userPickerForm.multiple = this.multiple;
43016
+ this.userPickerForm.show = true;
43017
+ }
43018
+ quickNote(item) {
43019
+ return __awaiter(this, void 0, void 0, function* () {
43020
+ const userResult = yield this._userService.getBasicUserInfo(item.createdBy);
43021
+ this.context.data.noteDataModel = {
43022
+ editFormModel: {
43023
+ showEditForm: true,
43024
+ showQuickNoteForm: true,
43025
+ popupSize: {},
43026
+ data: {
43027
+ name: item.content1,
43028
+ content: '<b>' + userResult.fullName + '</b>' + ' đã chat tại công việc '
43029
+ + '<b>' + this.model.taskName + '</b>' + ' với nội dung '
43030
+ + '<b>' + item.content1 + '</b>' + ' vào lúc ' + moment$1(new Date(item.created)).format('YYYY-MM-DD hh:mm:ss A')
43031
+ }
43032
+ }
43033
+ };
43034
+ this.model.editFormModel.showQuickNoteForm = true;
43035
+ this.showAddNoteForm = true;
43036
+ });
43037
+ }
43038
+ onMouseUp(event) {
43039
+ event.cancelBubble = true;
43040
+ event.stopPropagation();
43041
+ }
43042
+ addClassToMessage(item, isPinnedMessage) {
43043
+ let styleClass = '';
43044
+ if (!isPinnedMessage) {
43045
+ if (item.isFirstMessageFlow) {
43046
+ styleClass = 'first';
43047
+ }
43048
+ else if (item.isLastMessageFlow) {
43049
+ styleClass = 'last';
43050
+ }
43051
+ else {
43052
+ styleClass = 'middle';
43053
+ }
43054
+ }
43055
+ if (item.sent == false) {
43056
+ styleClass = 'sending';
43057
+ }
43058
+ return styleClass;
43059
+ }
43060
+ }
43061
+ ChatBoxComponent.decorators = [
43062
+ { type: Component, args: [{
43063
+ selector: 'chat-box',
43064
+ template: "<div class=\"dashboard\">\r\n <div class=\"chat\">\r\n <div class=\"group-info\">\r\n <a href=\"javascript:\">C\u00F3 {{peopleAll.length}} ng\u01B0\u1EDDi trong nh\u00F3m n\u00E0y</a>\r\n <div class=\"circleButton\" pTooltip=\"Xem to\u00E0n b\u1ED9 \u0111\u00EDnh k\u00E8m\" tooltipPosition=\"top\">\r\n <a href=\"javascript:\"><i class=\"far fa-images\"></i></a>\r\n </div>\r\n <div (click)=\"addPeople()\" class=\"circleButton\" pTooltip=\"Th\u00EAm m\u1EDBi ng\u01B0\u1EDDi v\u00E0o nh\u00F3m\" tooltipPosition=\"top\"\r\n disabled=\"true\">\r\n <a href=\"javascript:\"><i class=\"fas fa-user-plus\"></i></a>\r\n </div>\r\n </div>\r\n <ul #scrollMe [ngClass]=\"{'hasPin': model.pinnedMessage != null}\">\r\n <li *ngIf=\"model.pinnedMessage\" class=\"clearfix pin\" [ngClass]=\"{'message-from': true}\">\r\n <ng-container\r\n *ngTemplateOutlet=\"messageItem; context: { i : -1, item: model.pinnedMessage, isPinnedMessage: true}\">\r\n </ng-container>\r\n </li>\r\n <li *ngFor=\"let item of model.dataSource; let i = index; trackBy: trackByFunc\" class=\"clearfix\"\r\n [ngClass]=\"{ 'message-own': item.type == 'own'}\">\r\n <ng-container *ngTemplateOutlet=\"messageItem; context: { i : i, item: item}\">\r\n </ng-container>\r\n </li>\r\n </ul>\r\n <!-- <chat-send-message-box *ngIf=\"showSendMessageBox\"></chat-send-message-box>-->\r\n <div [ngClass]=\"{'visible2': model.scrolling, 'hidden2': !model.scrolling}\" class=\"scroll-to-bottom\">\r\n <span *ngIf=\"model.newMessageNotUpdatedCount > 0\" (click)=\"scrollToBottom(350, true, null)\">\r\n {{model.newMessageNotUpdatedCount <= 5 ? model.newMessageNotUpdatedCount : '5+' }} </span>\r\n <span (click)=\"scrollToBottom(350, true, null)\" *ngIf=\"model.newMessageNotUpdatedCount == 0\">\r\n <i class=\"fas fa-chevron-down\"></i>\r\n </span>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<file-viewer *ngIf=\"fileViewerModel.showEditForm\" [parentContext]=\"context\" [parentModel]=\"model\"\r\n [model]=\"fileViewerModel\">\r\n</file-viewer>\r\n\r\n<ng-template #messageItem let-i=\"i\" let-isPinnedMessage=\"isPinnedMessage\" let-item=\"item\">\r\n <img *ngIf=\"item.isFirstMessageFlow && item.type != 'own' && !isPinnedMessage && item.avatar != null\" alt=\"\"\r\n class=\"chat-avatar\" src=\"{{getCurrentUserAvatar(item.avatar)}}\">\r\n <p *ngIf=\"(item.isFirstMessageFlow && item.type != 'own') && !isPinnedMessage\" class=\"message-created-by\">\r\n {{item.fullName}}\r\n </p>\r\n <span *ngIf=\"!hasAttachment(item)\">\r\n <!-- [class]=\"addClassToMessage(item, isPinnedMessage)\">-->\r\n <p *ngIf=\"!hasAttachment(item)\" class=\"message-content\">\r\n <i (click)=\"pinMessage(item)\" class=\"fas fa-thumbtack\" style=\"right: 0;\"></i>\r\n <i (click)=\"quickNote(item)\" class=\"fas fa-sticky-note\"></i>\r\n {{item.content}}\r\n </p>\r\n <p *ngIf=\"!isPinnedMessage && (item.isLastMessageFlow || !inTheSameTime(i, item, model.dataSource))\"\r\n class=\"message-created\" pTooltip=\"{{item.created | date:'dd/MM/yyyy HH:mm'}}\"\r\n tooltipPosition=\"{{item.type != 'own'?'right':'left'}}\">\r\n {{_crudService.renderDateTime(item.created)}}\r\n </p>\r\n <p *ngIf=\"isPinnedMessage\" class=\"message-created\">\r\n {{item.createdBy}} \u0111\u00E3 g\u1EEDi l\u00FAc {{item.created | date:'dd/MM/yyyy HH:mm'}}\r\n </p>\r\n </span>\r\n <ng-container *ngIf=\"hasAttachment(item)\">\r\n <ng-container *ngFor=\"let attachmentItem of item.attachments;let index=index\">\r\n <div class=\"file\"\r\n [ngClass]=\"{'first':item.isFirstMessageFlow && index == 0, 'middle':index > 0 || !item.isFirstMessageFlow, 'image' : attachmentItem.type == 'image'}\"\r\n [ngStyle]=\"{'width': model.img[i + 'width' + index]}\">\r\n <p class=\"attachment\">\r\n <span (mouseup)=\"onMouseUp($event)\" class=\"attachment-item\">\r\n <a *ngIf=\"attachmentItem.type != 'image'\" (click)=\"viewOrDownloadFile($event, attachmentItem)\">\r\n <i class=\"fas fa-paperclip\"></i>{{attachmentItem.fileName}}\r\n </a>\r\n <a *ngIf=\"attachmentItem.type == 'image'\" #aElement\r\n [ngClass]=\"{'hidden': !model.img[i + '' + index], 'visible':model.img[i + '' + index]}\"\r\n (click)=\"viewOrDownloadFile($event, attachmentItem)\">\r\n <img class=\"message-img\" (load)=\"loadImg($event, i, index)\"\r\n [src]=\"attachmentItem.url | secure | async\" />\r\n </a>\r\n </span>\r\n </p>\r\n <div style=\"clear: both\"></div>\r\n <p class=\"message-created\" pTooltip=\"{{item.created | date:'dd/MM/yyyy HH:mm'}}\"\r\n tooltipPosition=\"{{item.type != 'own'?'right':'left'}}\">\r\n {{_crudService.renderDateTime(item.created)}}\r\n </p>\r\n </div>\r\n <div style=\"clear: both\"></div>\r\n </ng-container>\r\n </ng-container>\r\n <after-view-checked *ngIf=\"model.dataSource.length == i + 1\" (loading)=\"scrollToBottom(0, false, item.sent)\">\r\n </after-view-checked>\r\n</ng-template>\r\n\r\n<!--<tn-dialog *ngIf=\"userPickerForm.show\" #dialog [styleClass]=\"'tn-form-dialog'\"-->\r\n<!-- [header]=\"'Th\u00EAm m\u1EDBi ng\u01B0\u1EDDi d\u00F9ng' | translate\" [popupSize]=\"userPickerForm.popupSize\"-->\r\n<!-- (onCancel)=\"userPickerForm.show = false\"-->\r\n<!-- (onHide)=\"userPickerForm.show = false\">-->\r\n<!-- &lt;!&ndash; <congviec-form #formBase [parentModel]=\"model\" [parentContext]=\"context\" [model]=\"formModel\"&ndash;&gt;-->\r\n<!-- &lt;!&ndash; (onSaved)=\"showDetailForm = false;crudList.reload()\" (onCancel)=\"_handleCancel($event)\"&ndash;&gt;-->\r\n<!-- &lt;!&ndash; (onAfterSaved)=\"onAfterSaved($event)\"></congviec-form>&ndash;&gt;-->\r\n<!-- <user-picker-box #formBase [control]=\"userPickerControl\"-->\r\n<!-- [(ngModel)]=\"this.peopleAll\" [multiple]=\"userPickerControl.multiple\">-->\r\n<!-- </user-picker-box>-->\r\n<!--</tn-dialog>-->\r\n\r\n\r\n<!--<tn-dialog *ngIf=\"userPickerForm.show\" #dialog [styleClass]=\"'tn-form-dialog'\"-->\r\n<!-- [header]=\"'Th\u00EAm m\u1EDBi ng\u01B0\u1EDDi d\u00F9ng' | translate\" [popupSize]=\"userPickerForm.popupSize\" (onHide)=\"userPickerForm.show == false\">-->\r\n<!-- &lt;!&ndash; <congviec-form #formBase [parentModel]=\"model\" [parentContext]=\"context\" [model]=\"formModel\"&ndash;&gt;-->\r\n<!-- &lt;!&ndash; (onSaved)=\"showDetailForm = false;crudList.reload()\" (onCancel)=\"_handleCancel($event)\"&ndash;&gt;-->\r\n<!-- &lt;!&ndash; (onAfterSaved)=\"onAfterSaved($event)\"></congviec-form>&ndash;&gt;-->\r\n\r\n<!-- &lt;!&ndash;<quick-add-form *ngIf=\"model.editFormModel.showQuickNoteForm\" [parentContext]=\"context\"&ndash;&gt;-->\r\n<!-- &lt;!&ndash; [parentModel]=\"context.data.noteDataModel\"></quick-add-form>&ndash;&gt;-->\r\n<!--</tn-dialog>-->",
43065
+ providers: [ComponentContextService, CheckControlVisibleService],
43066
+ styles: [".paging-advance{list-style:none;margin:3px 0;padding-left:0}.paging-advance li{line-height:30;padding-left:15px;width:150px}.paging-advance li.disabled{color:#bdbdbd;outline:none}.paging-advance li.disabled:hover{background:none;cursor:default}.paging-advance li:hover{background:red;cursor:pointer}.paging-advance-overlay .ui-overlaypanel-content{padding:0}.paging-advance-overlay.ui-overlaypanel-shifted:before{left:1.25em;margin-left:-10;right:auto}.paging-advance-overlay.ui-overlaypanel-shifted:after{left:1.25em;margin-left:-8px;right:auto}.chat-avatar{border:2px solid #eee;height:36px}", "@charset \"UTF-8\";@import url(C:\\Users\\vietp\\source\\repos\\5.1\\shared\\AppSharedV5\\node_modules\\@angular\\material\\prebuilt-themes\\indigo-pink.css);@import url(C:\\Users\\vietp\\source\\repos\\5.1\\shared\\AppSharedV5\\node_modules\\jsoneditor\\dist\\jsoneditor.min.css);.flex{display:flex}.flex .fit{flex:1 1}.flex.flex-column{flex-direction:column}.flex.flex-wrap{flex-wrap:wrap}.flex.center-v{align-items:center}.flex.center-all,.flex.center-h{justify-content:center}.flex.center-all{align-items:center}.validate-item{color:#e00000;display:inline-block;font-size:.9em;white-space:nowrap}.tn-scroll-bar.bgWhite>div,.validate-item{background-color:#fff}.label-primary{background-color:#1ab394;padding:2px}.label-danger,.label-primary{border-radius:.25em;color:#fff;display:inline-block;font-size:12px;margin-left:3px;margin-right:3px;min-width:60px}.label-danger{background-color:#ed5565;padding:2px 5px}.label-warning{background-color:#b8860b}.label-secondary,.label-warning{border-radius:.25em;color:#fff;display:inline-block;font-size:12px;margin-left:3px;margin-right:3px;min-width:60px;padding:2px}.label-secondary{background-color:#a9a9a9}.label-done{background-color:#3b1ef7;border-radius:.25em;color:#fff;display:inline-block;font-size:12px;margin-left:3px;margin-right:3px;min-width:60px;padding:2px}.text-navy{color:#1ab394!important}.text-danger{color:red!important}.fa-user-edit{font-size:14px}.flexcolumn{border:1px solid #eee;border-radius:5px;min-height:80px;overflow-x:hidden;overflow-y:hidden}.flexcolumn,.has2ScrollZone2 .flexcolumn{max-height:calc(100vh - 180px)}.headerNoBorder>th{border:none!important;border-bottom:1px solid #eee!important}.cellNoBorder table tr td{border:0!important}.layout-wrapper .layout-main{overflow:hidden;padding:60px 0 0}div.circleButton{border-radius:50%;display:inline-block;height:32px;line-height:32px;margin-bottom:4px;margin-top:4px;overflow:hidden;position:relative;text-align:center;transform:perspective(1px);width:32px}div.circleButton>a{line-height:32px;padding:0!important}div.circleButton>a>i{width:24px!important}div.circleButton:before{background:#e6e6e6;border-radius:50%;bottom:0;content:\"\";left:0;position:absolute;right:0;top:0;transform:scale(0);transition:all .3s cubic-bezier(.4,.34,.01,.97);z-index:-1}div.circleButton:hover:before{transform:scale(1)}.message-notice{background:#e0e0e0;text-align:center}.message-created-by{color:#888;font-size:.82em;font-weight:400;margin-bottom:3px;margin-left:45px;margin-top:5px}.message-created{color:#495057;display:inline-block;font-size:.82em;margin-bottom:0;margin-top:0}.message-own .message-created{padding-left:10px;padding-right:6px}.message-from .message-created{padding-left:6px;padding-right:10px}.message-content{color:#000;line-height:20px;margin-bottom:6px;margin-top:3px;position:relative}.message-content i{display:none}.message-content:hover i{display:block}.message-content:hover{padding-right:20px!important}.chat-box-content{max-height:500px}.attachment-list .attachment-item{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;background:#f1f1f1;border:1px solid #ccc;border-radius:8px;box-shadow:1px 2px 3px rgba(0,0,0,.06);float:left;height:84px;margin:8px;overflow:hidden;position:relative;text-align:center;user-select:none;width:84px}.attachment-list .attachment-item img{height:100%;width:100%}.attachment-list .attachment-item span{left:0;padding:5px;position:absolute;top:25px;width:100%;word-break:break-all}.clearfix{clear:both}.dashboard .chat ul li img.message-img{float:none;height:120px;margin-left:0;width:auto}.message-attachment{cursor:pointer;font-size:1.5em;margin:0 5px 0 0;position:relative}.hidden{display:none}.message-input{width:100%}.message-input label{font-size:1.2rem}.remove-file-attachment{background:#495057;border-radius:50%;color:#fff;cursor:pointer;font-size:20px;position:absolute;right:5px;top:5px}.attachment-list{background:#fff;bottom:51px;box-shadow:0 -2px 3px -3px rgba(0,0,0,.21176470588235294);display:none;height:100px;left:-15px;position:absolute;width:calc(100% + 30px)}.attachment-list.attached-file{display:block}.dashboard{margin-bottom:-15px;margin-top:-5px}.dashboard .timeline>.ui-g .ui-g-9 .event-text{color:#555;white-space:nowrap}.dashboard .timeline>.ui-g .ui-g-9 .event-text.event-text2{line-height:18px;padding-left:30px;text-align:justify;white-space:pre-wrap}.dashboard .timeline>.ui-g .ui-g-9 .event-text.event-text2 i{left:20px;margin-top:3px;position:absolute}.new-message{align-items:center;justify-content:center}.dashboard .chat .new-message{border:0;display:flex;margin:0;padding:0;text-align:left}.dashboard .chat .new-message i{color:#495057}.dashboard .chat .new-message .message-attachment{border:0}.dashboard .chat .new-message .button-send{display:inline-block;line-height:40px;position:relative}.dashboard .chat .new-message .button-send .p-button-label{text-align:center}.dashboard .chat .new-message .message-emotion{display:inline-block;height:100%;line-height:40px;text-align:center;width:40px}.dashboard .chat .new-message .message-emotion i{font-size:24px;line-height:inherit}.dashboard .chat .new-message .message-input{width:calc(100% - 155px)}.dashboard .chat ul li.message-from,.dashboard .chat ul li.message-own{padding:0}.dashboard .chat ul li.message-from>span{background-color:#f0e3fd;border:0;border-radius:2px 20px 20px 2px}.dashboard .chat ul li.message-from>.first,.dashboard .chat ul li.message-from>.middle{margin-left:45px!important}.dashboard .chat ul li.message-from>.last{border-radius:2px 20px 20px 20px;margin-left:45px!important}.dashboard .chat ul li.message-from>img{border-radius:50%;margin-top:5px;position:absolute;width:36px}.dashboard .chat ul li.message-own>span{background-color:#def6f8;border:0;border-radius:20px 2px 2px 20px;text-align:right}.dashboard .chat ul li.message-own>span.sending{background-color:#eee}.dashboard .chat ul li.message-own>span.last{border-radius:20px 2px 20px 20px}.dashboard .chat ul li.message-own .attachment span.attachment-item{background-color:#f1f1f1!important;border:0!important;padding-left:0;padding-right:0}.dashboard .chat ul li.message-own .attachment span.attachment-item a{color:#555;cursor:pointer;display:inline-block;font-weight:700}.dashboard .chat ul li.message-own>div.file{background:#f1f1f1;border:1px solid #e4e4e4;border-radius:6px;display:inline-block;margin:1px;overflow:hidden;text-align:right}.dashboard .chat ul li.message-from .attachment span.attachment-item{background-color:#f1f1f1!important;border:0!important;padding-left:0;padding-right:0}.dashboard .chat ul li.message-from .attachment span.attachment-item a{color:#555;cursor:pointer;display:inline-block;font-weight:700}.dashboard .chat ul li.message-from .attachment span.attachment-item a img{margin-right:0}.dashboard .chat ul li.message-from>div.file{background:#f1f1f1;border:1px solid #e4e4e4;border-radius:6px;display:inline-block;margin:1px;overflow:hidden;text-align:left}.dashboard .chat ul li .attachment span.attachment-item a>i{padding-right:8px}.dashboard .chat ul li div.file p.attachment{display:inline-block;margin-bottom:5px}.dashboard .chat ul li.message-from{text-align:left}.dashboard .chat ul li.message-own{text-align:right}.dashboard .chat ul li>div.file.image{height:170px;max-width:100%;padding:15px;transition:width .15s linear;width:220px}.dashboard .chat ul li>div.file.image p.attachment{height:120px}.dashboard .chat ul li>div.file{padding:15px}.dashboard .chat ul li>div.file p,.dashboard .chat ul li>div.file span{display:inline-block;margin:0;padding:0}.visible{opacity:1;transition:opacity .15s linear;visibility:visible}.hidden{opacity:0;transition:visibility 0s .1s,opacity .1s linear;visibility:hidden}.visible2{opacity:1;transition:opacity .35s linear;visibility:visible}.hidden2{opacity:0;transition:visibility 0s .3s,opacity .3s linear;visibility:hidden}.dashboard .chat{position:relative}.dashboard .chat .scroll-to-bottom{bottom:6px;min-height:40px;padding-right:12px;position:sticky;text-align:right}.dashboard .chat .scroll-to-bottom span{background:#495057;border:2px solid #fff;border-radius:50%;box-shadow:0 0 10px rgba(0,0,0,.34901960784313724);color:#fff;cursor:pointer;display:inline-block;font-size:20px;height:35px;line-height:35px;overflow:hidden;text-align:center;width:35px}.dashboard .chat .group-info{line-height:30px;margin:-10px;padding:5px 10px;top:0;z-index:99}.dashboard .chat .group-info,.dashboard .chat .pin{background:#fff;box-shadow:0 0 3px -1px rgba(0,0,0,.21176470588235294);position:sticky}.dashboard .chat .pin{margin-bottom:10px;margin-left:-10px;top:40px;width:calc(100% + 20px);z-index:98}.dashboard .chat ul li.message-from.pin>span,.dashboard .chat ul li.message-own.pin>span{background-color:transparent}.dashboard .chat ul li.message-from.pin>span{margin-left:0}.dashboard .chat .message-content i{color:#495057;cursor:pointer;font-size:11px}.dashboard .chat .pin .message-content i{display:block}.dashboard .chat li.message-from .message-content{padding-left:6px}.dashboard .chat li.message-from .message-content i{padding:5px}.dashboard .chat li.message-own .message-content i{padding:5px;position:absolute;right:-15px}.dashboard .chat .group-info .circleButton{float:right;margin-bottom:0;margin-top:0}.dashboard .chat ul{margin-top:20px;padding:0}.dashboard .chat .new-message .message-input input.ui-inputtext:focus{box-shadow:none;outline:none}.dashboard .chat ul.hasPin{margin-top:10px}.dashboard .chat .group-info a{color:#495057}.normalHtml,.normalHtml b,.normalHtml strong{font-weight:400}.normalHtml{display:inline-block}.avatar-viewer .profile-image{border:1px solid #fff;border-radius:50%;height:40px;margin-top:-6px;width:40px}a.button>i{margin-right:5px}.dashboard .timeline{padding-top:20px}.ui-inputgroup .ui-inputtext{padding-right:0}.new-message .ui-inputtext{width:100%}.full-screen,.full-screen>.p-dialog{height:100%!important;left:0!important;max-height:100%;min-height:unset!important;min-width:100%!important;top:0!important;width:100%!important}#image-view-list.image-gallery-2{background-color:rgba(0,0,0,.4);height:calc(100vh - 41px);margin:-14px auto 0;touch-action:none;width:100%}#image-view-list.image-gallery-2 .image-container{background-color:transparent;border:0;bottom:0;height:85%;margin:auto}#image-view-list.image-gallery-2 .image-container .iv-snap-view{bottom:20px;left:calc(50% - 75px);top:auto}#image-view-list.image-gallery-2 .image-container .iv-image-view img{touch-action:auto}#image-view-list .inline-icon{margin-top:-41px}#image-view-list .footer-info,#image-view-list .material-icons.next,#image-view-list .material-icons.prev{display:none}#image-view-list .options-image-viewer{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;margin-right:37px;user-select:none}.mobile-image-viewer-close{color:#fff;cursor:pointer;font-size:x-large;height:42px;line-height:42px;padding-right:7px;padding-top:2px;position:absolute;right:0;text-align:center;top:0;vertical-align:middle;width:37px}.mobile-image-viewer-close:hover{color:#feca37!important}.hide-holder{padding:0}.file-ex-name{word-break:break-all}.box-function{background:#fff;border-radius:0 0 5px 5px;border-top:1px solid #e8e8e8;bottom:0;left:0;padding:8px 30px;position:absolute;text-align:right;width:100%}.box-function button{margin-left:5px}.quick-note-button-holder{bottom:40px;display:none;height:50px;position:absolute;right:50px;width:50px;z-index:99}.quick-note-button{background:#ffc107;border:2px solid #fff;border-radius:50%;box-shadow:0 2px 5px 0 #b9b9b9;color:#fff;display:block;font-size:2em;height:50px;line-height:50px;outline:none;text-align:center;width:50px}.quick-note-button:hover{color:#fff}.all-note-button{background:#ffd24b;border:2px solid #fff;border-radius:50%;box-shadow:0 2px 5px 0 #b9b9b9;color:#fff;display:block;font-size:1.5em;height:40px;line-height:40px;outline:none;position:absolute;right:5px;text-align:center;top:5px;transition:right;transition-duration:.16s;transition-timing-function:ease-in;width:40px;z-index:-1}.all-note-button:hover{color:#fff}.setting-note-button{background:#ffd24b;border:2px solid #fff;border-radius:50%;box-shadow:0 2px 5px 0 #b9b9b9;color:#fff;display:block;font-size:1.5em;height:40px;line-height:40px;outline:none;position:absolute;right:5px;text-align:center;top:5px;transition:right;transition-duration:.16s;transition-timing-function:ease-in;width:40px;z-index:-1}.setting-note-button:hover{color:#fff}.pinned-notes-holder{bottom:20px;display:none;left:20px;position:absolute;width:250px;z-index:98}.pinned-notes{background:transparent;display:block;outline:none;padding:0}.pinned-notes-header{font-size:1rem;font-weight:700}.pinned-notes-setting{position:absolute;right:.5rem}.pinned-note{background-color:#fff1ac;box-shadow:1px 2px 3px rgba(185,139,6,.6313725490196078);font-size:.8rem;margin-bottom:10px;padding:0;position:relative}.pinned-note:last-child{margin-bottom:0}.pinned-notes-minimize-button{background:#ffc003;border:1px solid #fff;border-radius:50%;box-shadow:1px 2px 3px rgba(185,139,6,.6313725490196078);color:#fff;cursor:pointer;height:25px;padding-top:5px;position:absolute;right:-15px;text-align:center;top:-15px;width:25px;z-index:1}.pinned-note-header-line{border:1px solid #fff;box-shadow:1px 1px 2px rgba(0,0,0,.4);height:calc(100% - 1rem);left:3px;margin-bottom:.5rem;margin-top:.5rem;max-height:20px;position:absolute;width:13px}.pinned-note-header-right{cursor:pointer;float:right;margin-left:3px;width:32px}.pinned-note-header-time{font-size:.6rem}.pinned-note-header-button-unpin{display:none;float:left;height:14px;margin-right:2px;opacity:.8;width:14px}.pinned-note-header-button-complete{display:none;padding-top:2px}.pinned-note-body{float:right;padding:.5rem .5rem .5rem 25px;width:100%}.pinned-note-body:hover{background-color:#feeb82}.pinned-note-body:hover .pinned-note-header-time{display:none}.pinned-note-body:hover .pinned-note-header-button-complete,.pinned-note-body:hover .pinned-note-header-button-unpin{display:block}.pinned-note-line-title{color:#333;display:block;font-weight:700;padding-bottom:6px}.pinned-note-line{display:block}.view-port{border-radius:5px;box-shadow:0 0 0 9999px rgba(0,0,0,.5882352941176471);display:none;height:0;width:0;z-index:999}.view-port,.view-port-mask{background:transparent;position:absolute}.view-port-mask{display:block;height:100%;left:0;top:0;width:100%;z-index:9998}.tinymce-control{border:1px solid #ccc;display:none;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-size:14px;width:100%}.input-tab-trap{filter:alpha(opacity=0)!important;opacity:0!important;overflow:hidden!important;width:0!important}.color-value input{font-size:.8em;line-height:16px}.dialog-material.mobile{width:100%!important}audio,audio:focus,video,video:focus{outline:none}.iv-image-view img.iv-image{-webkit-animation:fadein .5s;animation:fadein .5s;visibility:hidden!important}@-webkit-keyframes fadein{0%{opacity:0}to{opacity:1}}@keyframes fadein{0%{opacity:0}to{opacity:1}}.iv-image-view img.iv-image.show{visibility:visible!important}.row-line{padding-bottom:0;padding-top:0}.fc-ltr{padding-bottom:7px}.padding-bottom-5px{padding-bottom:5px}.no-margin{margin:0!important}.no-padding{padding:0}.no-padding-left{padding-left:0}.float-left{float:left}body .fc .fc-toolbar .fc-button{background-color:#007ad9;border:1px solid #007ad9;border-radius:3px;color:#fff;font-size:14px;transition:background-color .2s,box-shadow .2s}body .fc .fc-toolbar .fc-button:enabled:hover{background-color:#116fbf;border-color:#116fbf;color:#fff}body .fc .fc-toolbar .fc-button:focus{box-shadow:0 0 0 .2em #8dcdff;outline:0 none;outline-offset:0}body .fc .fc-toolbar .fc-button-group .fc-button{border-radius:0}body .fc .fc-toolbar .fc-button-group .fc-button:first-child{border-bottom-left-radius:3px;border-top-left-radius:3px}body .fc .fc-toolbar .fc-button-group .fc-button:last-child{border-bottom-right-radius:3px;border-top-right-radius:3px}body .fc .fc-toolbar .fc-right .fc-button{border-radius:0}body .fc .fc-toolbar .fc-right .fc-button:first-child{border-bottom-left-radius:3px;border-top-left-radius:3px}body .fc .fc-toolbar .fc-right .fc-button:last-child{border-bottom-right-radius:3px;border-top-right-radius:3px}.fc-toolbar>*>:not(:first-child){margin-left:0}.fc-axis,.fc-dayGridMonth-button,.fc-timeGridDay-button,.fc-timeGridWeek-button,.old-content{line-height:0;text-indent:-9999px}.fc-axis:after,.fc-dayGridMonth-button:after,.fc-timeGridDay-button:after,.fc-timeGridWeek-button:after,.new-content{display:block;line-height:normal;text-indent:0}.fc-dayGridMonth-button:after{content:\"Th\u00E1ng\";padding:.2em}.fc-timeGridWeek-button:after{content:\"Tu\u1EA7n\";padding:.2em}.fc-timeGridDay-button:after{content:\"Ng\u00E0y\";padding:.2em}body .fc th{background-color:#f4f4f4;border:1px solid #c8c8c8;color:#333;padding:.571em 1em}.ui-fluid .button-group button,.ui-fluid .button-group p-button{margin-right:.5em!important;text-align:left;width:auto}.layout-wrapper .layout-menu-container{z-index:97}.base-status,.base-status-aborted,.base-status-approved,.base-status-completed,.base-status-create-new,.base-status-ended,.base-status-high,.base-status-immediately,.base-status-low,.base-status-medium,.base-status-on-conducting,.base-status-on-going,.base-status-pending,.base-status-rejected,.base-status-returned,.base-status-urgent{border-radius:.25em;color:#fff;font-size:.8em;padding:3px;text-align:center}.base-status-create-new{background-color:#f2f2f2;color:#666}.base-status-on-conducting,.base-status-on-going{background-color:#337ab7}.base-status-pending{background-color:#ffba01}.base-status-approved{background-color:#34a835}.base-status-returned{background-color:#ffba01}.base-status-rejected{background-color:#d9534f}.base-status-completed{background-color:#34a835}.base-status-aborted{background-color:#ffba01}.base-status-ended{background-color:#34a835}.base-status-low,.base-status-medium{background-color:#f2f2f2;color:#666}.base-status-high{background-color:#ffba01}.base-status-immediately,.base-status-urgent{background-color:#d9534f}.text-align-center{text-align:center}.font-weight-bold{font-weight:700}.landing-body .landing-menu li a:hover{border-bottom:none}.landing-body .landing-menu li:first-child{margin-left:8px}.crud-form .label-control p{margin:0;padding:0}.crud-form .tn-check-box-list .p-row{display:block;padding:.5em;width:100%}.crud-form dropdown,.crud-form tn-mask{width:100%}.crud-form .tn-dropdown{min-height:32px}.crud-form .tn-dropdown.free-text.horizontal{display:flex}.crud-form .tn-dropdown.free-text.horizontal>div{flex-grow:1;padding-left:.5em;padding-right:.5em}.crud-form .tn-dropdown.free-text.horizontal>div:first-child{padding-left:0}.crud-form .tn-dropdown.free-text.horizontal>div:last-child{padding-right:0}.crud-form .tn-dropdown.free-text.vertical input.ui-inputtext.input-free-text{margin-top:.5em}.crud-form.assessment .label-control{font-weight:700}.crud-form.assessment .label-control.haveIndex{display:block;margin-bottom:5px;padding-left:20px;position:relative}.crud-form.assessment .label-control.haveIndex:before{content:\" \" attr(label-index) \".\";left:0;position:absolute;top:0}.crud-form.assessment .ViewMode{border-bottom:none}.crud-form.assessment .ViewMode .label-control{margin-bottom:0}body .ui-inputtext.min-width{padding:6px}.ps__rail-x,.ps__rail-y{z-index:2}.zIndex5 .ps__rail-x,.zIndex5 .ps__rail-y{z-index:5}.table-sticky table{border-collapse:separate;border-spacing:0}.table-sticky tr td,.table-sticky tr th{border:1px solid #eee!important;border-left:none!important;border-top:none!important}.table-sticky tr td:first-child,.table-sticky tr th:first-child{border-left:1px solid #eee!important}.table-sticky tr td:last-child,.table-sticky tr th:last-child{border-right:none!important}.table-sticky tr:first-child th{border-top:1px solid #eee!important}.table-sticky th{background:#eee}.table-sticky tbody td.disabled{background:#eee!important}.table-sticky tbody td.disabled:not(:last-child){border-right:1px solid #fff!important}.table-sticky.fix-height tr:first-child th{position:sticky;top:0;z-index:2}.container-flex{align-items:center;display:flex}.container-flex>div:first-child{flex:0 0 auto;margin-right:.5em}.container-flex>div:last-child{flex-grow:1}.container-control{display:flex}.container-control>span.label{flex:0 0 auto;padding-right:.5em;padding-top:.5em}.container-control>span.label+*{flex-grow:1;flex-shrink:1;position:relative}.container-control>span.label+* .tn-dropdown,.container-control>span.label+* .ui-autocomplete-multiple,.container-control>span.label+* .ui-inputgroup .ui-inputtext{width:100%}.container-control>span.label+* .validation-container{margin-top:3px}.container-control>span.label+* .validation-container .validate-item{white-space:unset}.container-control>span.label+*>div{left:0;position:absolute;top:0;width:100%}.container-control.no-label>span.label{display:none}.container-control.inline{display:inline-flex}.align-flex-center{align-items:center;display:flex;justify-content:center}@media print{.isPrinting>*{display:none}.isPrinting app-print-layout{display:block}}.layout-wrapper .topbar .topbar-left,.layout-wrapper .topbar .topbar-right{background:#397ac3}#searchResultPanel-holder{padding:0 .5em}.cus-dropdown{line-height:normal;margin-right:1em}.tn-thumbnail{padding:.5rem}.tn-thumbnail.tn-thumbnail.tn-thumbnail{box-sizing:border-box}.fa-10:before{content:\"A+\";font-family:cursive;font-weight:700}.layout-wrapper .topbar .topbar-right #menu-button i{font-size:20px;margin-top:4px}.layout-wrapper .layout-menu li a i.menuitem-toggle-icon{font-size:15px;margin-left:auto}.flex-container-main-content{display:flex;flex-direction:column}.flex-container-main-content>div:last-child{background-color:#f4f4f4;display:flex;flex:1 1;overflow:hidden;position:relative}.flex-container-main-content>div:last-child>div{height:100%;left:0;overflow:hidden;padding-top:.5em;position:absolute;top:0;width:100%}.flex-container-main-content .block-with-button-search{display:flex;justify-content:flex-end}.flex-container-main-content .block-with-button-search>*{margin-left:.5em}.flex-container-main-content .block-with-button-search>input{height:26px;margin-left:0;max-width:200px;width:100%}.flex-container-main-content .block-with-button-search>dropdown{max-width:140px;width:100%}.flex-container-main-content .title-main-component{border-bottom:2px solid #1ca7ff}.clickable-table.clickable-table{cursor:pointer}.main-crud-container{height:calc(100vh - 76px)}.flex-container-fit-child{display:flex;flex-direction:column;height:100%;overflow:hidden}.flex-container-fit-child>div.fit-content{flex:1 1;position:relative}.flex-container-fit-child>div.fit-content>div{height:100%;overflow:auto;position:absolute;width:100%}.waiting-box{display:none;height:100%;left:0;position:fixed;top:0;width:100%;z-index:9999}.waiting-box .overlay{background-color:red;background-color:hsla(0,0%,42.7%,.5019607843137255);height:100%;width:100%}.waiting-box .content-loading{left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}.waiting-box.show{display:block}.function-topbar>*{vertical-align:top}.function-topbar button{width:auto}.function-topbar p-fileUpload{margin-right:1em}.function-topbar .container-control{display:inline-flex;line-height:normal}.function-topbar .container-control dropdown{width:100%}:focus{outline-color:#a6d5fa!important}address{font-style:normal}body .p-toast .p-toast-message{border-radius:0;border-width:0 0 0 4px!important}.__status span,.status span{font-size:.8rem}p-table.single-check .p-datatable .p-datatable-tbody>tr{cursor:pointer}p-table.single-check .p-datatable .p-datatable-tbody>tr.ui-state-highlight{background:#e3f2fd!important;outline:2px solid #a6d5fa}p-table.single-check .p-datatable .p-datatable-tbody>tr td.sticky .fix-sticky.top{display:none}p-table.multi-check .p-datatable .p-datatable-tbody>tr.ui-state-highlight{background:#e3f2fd!important}p-table.multi-check .p-datatable .p-datatable-tbody>tr.ui-state-highlight td{border-color:#fff}p-table.multi-check .p-datatable .p-datatable-tbody>tr.ui-state-highlight td .fix-sticky{background-color:#fff}.tn-animated-left-arrow-icon,.tn-animated-right-arrow-icon{height:32px;position:relative;width:14px;z-index:10}.tn-animated-right-arrow-icon{-webkit-animation:arrowBounceToRight .8s ease-in-out infinite alternate;animation:arrowBounceToRight .8s ease-in-out infinite alternate}.tn-animated-left-arrow-icon{-webkit-animation:arrowBounceToLeft .8s ease-in-out infinite alternate;animation:arrowBounceToLeft .8s ease-in-out infinite alternate}.tn-animated-left-arrow-icon:after,.tn-animated-left-arrow-icon:before,.tn-animated-right-arrow-icon:after,.tn-animated-right-arrow-icon:before{background-color:#88b0dd;content:\"\";display:block;height:20px;position:absolute;width:5px}.tn-animated-right-arrow-icon:before{left:4px;top:0;transform:rotate(-35deg)}.tn-animated-right-arrow-icon:after{left:4px;top:14px;transform:rotate(35deg)}.tn-animated-left-arrow-icon:before{right:4px;top:0;transform:rotate(35deg)}.tn-animated-left-arrow-icon:after{right:4px;top:14px;transform:rotate(-35deg)}@-webkit-keyframes arrowBounceToLeft{0%{transform:translateX(-3px)}to{transform:translateX(3px)}}@keyframes arrowBounceToLeft{0%{transform:translateX(-3px)}to{transform:translateX(3px)}}@-webkit-keyframes arrowBounceToRight{0%{transform:translateX(3px)}to{transform:translateX(-3px)}}@keyframes arrowBounceToRight{0%{transform:translateX(3px)}to{transform:translateX(-3px)}}.pass{color:#49c949}.not-pass,.pass{margin:5px;text-align:center}.not-pass{color:red}"]
43067
+ },] }
43068
+ ];
43069
+ ChatBoxComponent.ctorParameters = () => [
43070
+ { type: Injector },
43071
+ { type: ChatService },
43072
+ { type: MessageBoardService },
43073
+ { type: UserService },
43074
+ { type: CheckControlVisibleService },
43075
+ { type: SignalRService },
43076
+ { type: FileExplorerService },
43077
+ { type: CrudService },
43078
+ { type: NotifierService },
43079
+ { type: ModuleConfigService }
43080
+ ];
43081
+ ChatBoxComponent.propDecorators = {
43082
+ taskId: [{ type: Input }],
43083
+ serviceCode: [{ type: Input }],
43084
+ entity: [{ type: Input }],
43085
+ users: [{ type: Input }],
43086
+ showSendMessageBox: [{ type: Input }],
43087
+ input: [{ type: ViewChild, args: ['input',] }],
43088
+ fileElement: [{ type: ViewChild, args: ['fileElement',] }]
43089
+ };
43090
+
43091
+ // fix for prod build
43092
+ // const objectToFormData = objectToFormData_;
43093
+ class ChatSendMessageBoxComponent extends ComponentBase {
43094
+ constructor(injector, _chatService, _checkControlVisible, _fileExplorerNewService, _notifierService) {
43095
+ super(injector);
43096
+ this._chatService = _chatService;
43097
+ this._checkControlVisible = _checkControlVisible;
43098
+ this._fileExplorerNewService = _fileExplorerNewService;
43099
+ this._notifierService = _notifierService;
43100
+ this.model.driveFileDialog = { popupSize: {} };
43101
+ }
43102
+ ngOnInit() {
43103
+ console.log('inside ChatSendMessageBoxComponent');
43104
+ this.model.dataSource = [];
43105
+ this.model.correlationIds = [];
43106
+ this.model.attachments = [];
43107
+ this.model.maxFileSize = 3000000;
43108
+ this.model.fileViewer = {};
43109
+ this._checkControlVisible.checkDisplayStatus(this.input.nativeElement).then(rs => {
43110
+ this.input.nativeElement.focus();
43111
+ });
43112
+ this.rootContext.subscribe(ComCtxConstants.ROOT.CHAT_INSTANCE_ID_LOADED, data => {
43113
+ if (data) {
43114
+ this.model.id = data;
43115
+ this.chatInstanceId = data;
43116
+ this.notifiUserOnline(this.model.id);
43117
+ }
43118
+ });
43119
+ this.rootContext.subscribe(ComCtxConstants.ROOT.CHAT_MOUSE_UP, data => {
43120
+ if (data) {
43121
+ this.onMouseUp(null);
43122
+ }
43123
+ });
43124
+ this.rootContext.subscribe('DRIVE_FILE_DIALOG.CLOSE_POPUP', response => {
43125
+ if (response != null) {
43126
+ const type = this._commonService.isImage(response.name) ? 'image' : 'file';
43127
+ const attachmentItem = {
43128
+ type: type,
43129
+ fileId: response.id,
43130
+ fileName: response.name
43131
+ };
43132
+ if (attachmentItem.type == 'image') {
43133
+ // Get preview url
43134
+ this._fileExplorerNewService.getImageFileBase64(response.id).then(result => {
43135
+ attachmentItem.url = result;
43136
+ });
43137
+ }
43138
+ this.model.attachments.push(attachmentItem);
43139
+ this.input.nativeElement.focus();
43140
+ this.model.classHasAttachment = 'attached-file';
43141
+ this.rootContext.fireEvent(ComCtxConstants.ROOT.CHAT_MESSAGE_ATTACH_FILE, true);
43142
+ }
43143
+ this.model.driveFileDialog.show = false;
43144
+ });
43145
+ this.rootContext.subscribe(ComCtxConstants.ROOT.DESTROY_TASK_DETAIL_COMPONENT, data => {
43146
+ if (this.model.userOnlineId) {
43147
+ this.removeUserOnline(this.model.userOnlineId);
43148
+ }
43149
+ });
43150
+ }
43151
+ browseFileFromPersonal() {
43152
+ this.model.driveFileDialog = {
43153
+ show: true
43154
+ };
43155
+ }
43156
+ onSendMessage(message) {
43157
+ if ((!message || message.trim() == '') && this.model.attachments.length === 0) {
43158
+ return;
43159
+ }
43160
+ if (!message) {
43161
+ message = '';
43162
+ }
43163
+ message = message.trim();
43164
+ const objToSend = {
43165
+ chatId: this.model.id,
43166
+ messageContent: message,
43167
+ correlationId: this._commonService.guid()
43168
+ };
43169
+ const formData = new FormData();
43170
+ for (const key in objToSend) {
43171
+ formData.append(key, objToSend[key]);
43172
+ }
43173
+ for (const item of this.model.attachments) {
43174
+ // const item = this.model.attachments[itejm];
43175
+ if (item.fileId != null) {
43176
+ formData.append('fileId', item.fileId);
43177
+ }
43178
+ else {
43179
+ if (item.type == 'image') {
43180
+ formData.append('files', item.data, item.fileName);
43181
+ }
43182
+ else {
43183
+ formData.append('files', item.data);
43184
+ }
43185
+ }
43186
+ }
43187
+ this.rootContext.fireEvent(ComCtxConstants.ROOT.CHAT_MESSAGE_SENDING, {
43188
+ message: objToSend,
43189
+ attachments: this.model.attachments
43190
+ });
43191
+ // reset attachment list
43192
+ this.model.attachments.length = 0;
43193
+ this.model.content = '';
43194
+ this.rootContext.fireEvent(ComCtxConstants.ROOT.CHAT_MESSAGE_ATTACH_FILE, false);
43195
+ this.model.classHasAttachment = '';
43196
+ this._chatService.sendMessage(formData).then(rs => {
43197
+ this.rootContext.fireEvent(ComCtxConstants.ROOT.CHAT_MESSAGE_SENT, { message: objToSend, status: true });
43198
+ }).catch((err) => {
43199
+ this.rootContext.fireEvent(ComCtxConstants.ROOT.CHAT_MESSAGE_SENT, {
43200
+ message: objToSend,
43201
+ status: false,
43202
+ error: err.error
43203
+ });
43204
+ this._notifierService.showWarningByResponse(err);
43205
+ });
43206
+ }
43207
+ handlePaste(event) {
43208
+ // console.log(event.clipboardData);
43209
+ const objectData = this.getImageClipboardData(event);
43210
+ if (objectData) {
43211
+ this.model.attachments.push({
43212
+ type: 'image',
43213
+ url: objectData.url,
43214
+ data: objectData.blob, fileName: this._commonService.guid() + '.png'
43215
+ });
43216
+ this.rootContext.fireEvent(ComCtxConstants.ROOT.CHAT_MESSAGE_ATTACH_FILE, true);
43217
+ this.model.classHasAttachment = 'attached-file';
43218
+ }
43219
+ }
43220
+ getImageClipboardData(e) {
43221
+ for (let i = 0; i < e.clipboardData.items.length; i++) {
43222
+ const item = e.clipboardData.items[i];
43223
+ if (item.type.indexOf('image') != -1) {
43224
+ const imageObj = item.getAsFile();
43225
+ if (imageObj.size < this.model.maxFileSize) {
43226
+ return { url: URL.createObjectURL(imageObj), blob: imageObj };
43227
+ }
43228
+ else {
43229
+ return null;
43230
+ }
43231
+ }
43232
+ }
43233
+ return null;
43234
+ }
43235
+ browseFileFromComputer() {
43236
+ this.fileElement.advancedFileInput.nativeElement.click();
43237
+ }
43238
+ onSelectFileFromComputer(evt) {
43239
+ try {
43240
+ if (evt.files && evt.files.length > 0) {
43241
+ for (let index = 0; index < evt.files.length; index++) {
43242
+ const fileName = evt.files[index].name;
43243
+ const type = this._commonService.isImage(fileName) ? 'image' : 'file';
43244
+ const attachmentItem = {
43245
+ type: type,
43246
+ data: evt.files[index], fileName: fileName
43247
+ };
43248
+ if (attachmentItem.type == 'image') {
43249
+ attachmentItem.url = evt.files[index].objectURL.changingThisBreaksApplicationSecurity;
43250
+ }
43251
+ this.model.attachments.push(attachmentItem);
43252
+ }
43253
+ this.input.nativeElement.focus();
43254
+ this.model.classHasAttachment = 'attached-file';
43255
+ this.rootContext.fireEvent(ComCtxConstants.ROOT.CHAT_MESSAGE_ATTACH_FILE, true);
43256
+ }
43257
+ }
43258
+ catch (e) {
43259
+ console.error('error on process select file computer', e);
43260
+ }
43261
+ this.fileElement.clear();
43262
+ }
43263
+ removeAttachment(item) {
43264
+ const attachments = this.model.attachments;
43265
+ const index = attachments.findIndex(x => x.url == item.url);
43266
+ this.model.attachments.splice(index, 1);
43267
+ if (this.model.attachments.length === 0) {
43268
+ this.model.classHasAttachment = '';
43269
+ this.rootContext.fireEvent(ComCtxConstants.ROOT.CHAT_MESSAGE_ATTACH_FILE, false);
43270
+ }
43271
+ }
43272
+ onMouseUp($event) {
43273
+ this.input.nativeElement.focus();
43274
+ }
43275
+ cancelBlur(event) {
43276
+ event.preventDefault();
43277
+ }
43278
+ ngOnDestroy() {
43279
+ this.rootContext.unSubscribe(ComCtxConstants.ROOT.CHAT_INSTANCE_ID_LOADED);
43280
+ this.rootContext.unSubscribe(ComCtxConstants.ROOT.CHAT_MOUSE_UP);
43281
+ }
43282
+ notifiUserOnline(chatId) {
43283
+ this._chatService.insertUserOnline(chatId).then(rs => {
43284
+ if (rs.success) {
43285
+ this.model.userOnlineId = rs.data;
43286
+ }
43287
+ });
43288
+ }
43289
+ removeUserOnline(userOnlineId) {
43290
+ this.chatInstanceId = '';
43291
+ this._chatService.removeUserOnline(userOnlineId).then(rs => {
43292
+ if (rs.success) {
43293
+ this._notifierService.showWarning('Đã bỏ người dùng thành công');
43294
+ }
43295
+ });
43296
+ }
43297
+ clickInputText() {
43298
+ if (this.model.instanceId) {
43299
+ this._chatService.markAsReadAllContents(this.model.id).then(rs => {
43300
+ console.log('markAsReadAllContents');
43301
+ });
43302
+ }
43303
+ }
43304
+ }
43305
+ ChatSendMessageBoxComponent.decorators = [
43306
+ { type: Component, args: [{
43307
+ selector: 'chat-send-message-box',
43308
+ template: "<div class=\"dashboard\" (mouseup)=\"onMouseUp($event)\">\r\n <div class=\"chat\">\r\n <div class=\"new-message\">\r\n <div class=\"message-emotion\">\r\n <i class=\"far fa-smile\" style=\"color: gray;\" disabled=\"true\"></i>\r\n </div>\r\n <div class=\"message-attachment\" pTooltip=\"\u0110\u00EDnh k\u00E8m file\" tooltipPosition=\"top\" (click)=\"op.toggle($event)\">\r\n <i class=\"fas fa-paperclip\"></i>\r\n </div>\r\n <p-overlayPanel #op [dismissable]=\"true\" [appendTo]=\"'body'\" [styleClass]=\"'paging-advance-overlay'\"\r\n (mouseup)=\"onMouseUp($event)\">\r\n <ul class=\"paging-advance\">\r\n <li (click)=\"browseFileFromPersonal()\">T\u1EEB file c\u00E1 nh\u00E2n</li>\r\n <li (click)=\"browseFileFromComputer()\">T\u1EA3i l\u00EAn t\u1EEB m\u00E1y t\u00EDnh</li>\r\n </ul>\r\n </p-overlayPanel>\r\n <div class=\"message-input p-float-label\">\r\n <input #input pInputText\r\n id=\"message\"\r\n autocomplete=\"off\" autocorrect=\"off\"\r\n spellcheck=\"false\" class=\"ui-inputtext\"\r\n type=\"text\" placeholder=\"N\u1ED9i dung tin nh\u1EAFn\"\r\n [(ngModel)]=\"model.content\"\r\n (keyup.enter)=\"onSendMessage($event.target.value)\" (keydown.shift.tab)=\"cancelBlur($event)\"\r\n (keydown.tab)=\"cancelBlur($event)\" (paste)=\"handlePaste($event)\" (click)=\"clickInputText()\"/>\r\n </div>\r\n <div>\r\n <button pButton class=\"p-button-danger\" icon=\"fas fa-send\" type=\"button\" label=\"G\u1EEDi\"\r\n (click)=\"onSendMessage(model.content)\">\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"attachment-list\" [ngClass]=\"model.classHasAttachment\">\r\n <tn-custom-scrollbar #scrollbar [style]=\"{'height': '100px'}\">\r\n <div *ngFor=\"let item of model.attachments\" class=\"attachment-item\">\r\n <img *ngIf=\"item.type == 'image'\" [src]=\"item.url | safeUrl\"/>\r\n <span *ngIf=\"item.type == 'file'\">{{item.fileName}}</span>\r\n <i class=\"far fa-times-circle label-danger remove-file-attachment\"\r\n (click)=\"removeAttachment(item)\"></i>\r\n </div>\r\n </tn-custom-scrollbar>\r\n <!-- <div class=\"clearfix\"></div>-->\r\n </div>\r\n </div>\r\n</div>\r\n<p-fileUpload [ngStyle]=\"{'display': 'none'}\" #fileElement (onSelect)=\"onSelectFileFromComputer($event)\"\r\n multiple=\"multiple\" name=\"fileUpload\" [maxFileSize]=\"model.maxFileSize\" auto=\"false\">\r\n</p-fileUpload>\r\n\r\n<!-- <app-drive-file-dialog *ngIf=\"model.driveFileDialog.show\" [parentDataContext]=\"dataContext\"\r\n []=\"model.driveFileDialog\" #driveFileDialog>\r\n</app-drive-file-dialog> -->\r\n",
43309
+ providers: [ComponentContextService],
43310
+ styles: ["", "@charset \"UTF-8\";@import url(C:\\Users\\vietp\\source\\repos\\5.1\\shared\\AppSharedV5\\node_modules\\@angular\\material\\prebuilt-themes\\indigo-pink.css);@import url(C:\\Users\\vietp\\source\\repos\\5.1\\shared\\AppSharedV5\\node_modules\\jsoneditor\\dist\\jsoneditor.min.css);.flex{display:flex}.flex .fit{flex:1 1}.flex.flex-column{flex-direction:column}.flex.flex-wrap{flex-wrap:wrap}.flex.center-v{align-items:center}.flex.center-all,.flex.center-h{justify-content:center}.flex.center-all{align-items:center}.validate-item{color:#e00000;display:inline-block;font-size:.9em;white-space:nowrap}.tn-scroll-bar.bgWhite>div,.validate-item{background-color:#fff}.label-primary{background-color:#1ab394;padding:2px}.label-danger,.label-primary{border-radius:.25em;color:#fff;display:inline-block;font-size:12px;margin-left:3px;margin-right:3px;min-width:60px}.label-danger{background-color:#ed5565;padding:2px 5px}.label-warning{background-color:#b8860b}.label-secondary,.label-warning{border-radius:.25em;color:#fff;display:inline-block;font-size:12px;margin-left:3px;margin-right:3px;min-width:60px;padding:2px}.label-secondary{background-color:#a9a9a9}.label-done{background-color:#3b1ef7;border-radius:.25em;color:#fff;display:inline-block;font-size:12px;margin-left:3px;margin-right:3px;min-width:60px;padding:2px}.text-navy{color:#1ab394!important}.text-danger{color:red!important}.fa-user-edit{font-size:14px}.flexcolumn{border:1px solid #eee;border-radius:5px;min-height:80px;overflow-x:hidden;overflow-y:hidden}.flexcolumn,.has2ScrollZone2 .flexcolumn{max-height:calc(100vh - 180px)}.headerNoBorder>th{border:none!important;border-bottom:1px solid #eee!important}.cellNoBorder table tr td{border:0!important}.layout-wrapper .layout-main{overflow:hidden;padding:60px 0 0}div.circleButton{border-radius:50%;display:inline-block;height:32px;line-height:32px;margin-bottom:4px;margin-top:4px;overflow:hidden;position:relative;text-align:center;transform:perspective(1px);width:32px}div.circleButton>a{line-height:32px;padding:0!important}div.circleButton>a>i{width:24px!important}div.circleButton:before{background:#e6e6e6;border-radius:50%;bottom:0;content:\"\";left:0;position:absolute;right:0;top:0;transform:scale(0);transition:all .3s cubic-bezier(.4,.34,.01,.97);z-index:-1}div.circleButton:hover:before{transform:scale(1)}.message-notice{background:#e0e0e0;text-align:center}.message-created-by{color:#888;font-size:.82em;font-weight:400;margin-bottom:3px;margin-left:45px;margin-top:5px}.message-created{color:#495057;display:inline-block;font-size:.82em;margin-bottom:0;margin-top:0}.message-own .message-created{padding-left:10px;padding-right:6px}.message-from .message-created{padding-left:6px;padding-right:10px}.message-content{color:#000;line-height:20px;margin-bottom:6px;margin-top:3px;position:relative}.message-content i{display:none}.message-content:hover i{display:block}.message-content:hover{padding-right:20px!important}.chat-box-content{max-height:500px}.attachment-list .attachment-item{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;background:#f1f1f1;border:1px solid #ccc;border-radius:8px;box-shadow:1px 2px 3px rgba(0,0,0,.06);float:left;height:84px;margin:8px;overflow:hidden;position:relative;text-align:center;user-select:none;width:84px}.attachment-list .attachment-item img{height:100%;width:100%}.attachment-list .attachment-item span{left:0;padding:5px;position:absolute;top:25px;width:100%;word-break:break-all}.clearfix{clear:both}.dashboard .chat ul li img.message-img{float:none;height:120px;margin-left:0;width:auto}.message-attachment{cursor:pointer;font-size:1.5em;margin:0 5px 0 0;position:relative}.hidden{display:none}.message-input{width:100%}.message-input label{font-size:1.2rem}.remove-file-attachment{background:#495057;border-radius:50%;color:#fff;cursor:pointer;font-size:20px;position:absolute;right:5px;top:5px}.attachment-list{background:#fff;bottom:51px;box-shadow:0 -2px 3px -3px rgba(0,0,0,.21176470588235294);display:none;height:100px;left:-15px;position:absolute;width:calc(100% + 30px)}.attachment-list.attached-file{display:block}.dashboard{margin-bottom:-15px;margin-top:-5px}.dashboard .timeline>.ui-g .ui-g-9 .event-text{color:#555;white-space:nowrap}.dashboard .timeline>.ui-g .ui-g-9 .event-text.event-text2{line-height:18px;padding-left:30px;text-align:justify;white-space:pre-wrap}.dashboard .timeline>.ui-g .ui-g-9 .event-text.event-text2 i{left:20px;margin-top:3px;position:absolute}.new-message{align-items:center;justify-content:center}.dashboard .chat .new-message{border:0;display:flex;margin:0;padding:0;text-align:left}.dashboard .chat .new-message i{color:#495057}.dashboard .chat .new-message .message-attachment{border:0}.dashboard .chat .new-message .button-send{display:inline-block;line-height:40px;position:relative}.dashboard .chat .new-message .button-send .p-button-label{text-align:center}.dashboard .chat .new-message .message-emotion{display:inline-block;height:100%;line-height:40px;text-align:center;width:40px}.dashboard .chat .new-message .message-emotion i{font-size:24px;line-height:inherit}.dashboard .chat .new-message .message-input{width:calc(100% - 155px)}.dashboard .chat ul li.message-from,.dashboard .chat ul li.message-own{padding:0}.dashboard .chat ul li.message-from>span{background-color:#f0e3fd;border:0;border-radius:2px 20px 20px 2px}.dashboard .chat ul li.message-from>.first,.dashboard .chat ul li.message-from>.middle{margin-left:45px!important}.dashboard .chat ul li.message-from>.last{border-radius:2px 20px 20px 20px;margin-left:45px!important}.dashboard .chat ul li.message-from>img{border-radius:50%;margin-top:5px;position:absolute;width:36px}.dashboard .chat ul li.message-own>span{background-color:#def6f8;border:0;border-radius:20px 2px 2px 20px;text-align:right}.dashboard .chat ul li.message-own>span.sending{background-color:#eee}.dashboard .chat ul li.message-own>span.last{border-radius:20px 2px 20px 20px}.dashboard .chat ul li.message-own .attachment span.attachment-item{background-color:#f1f1f1!important;border:0!important;padding-left:0;padding-right:0}.dashboard .chat ul li.message-own .attachment span.attachment-item a{color:#555;cursor:pointer;display:inline-block;font-weight:700}.dashboard .chat ul li.message-own>div.file{background:#f1f1f1;border:1px solid #e4e4e4;border-radius:6px;display:inline-block;margin:1px;overflow:hidden;text-align:right}.dashboard .chat ul li.message-from .attachment span.attachment-item{background-color:#f1f1f1!important;border:0!important;padding-left:0;padding-right:0}.dashboard .chat ul li.message-from .attachment span.attachment-item a{color:#555;cursor:pointer;display:inline-block;font-weight:700}.dashboard .chat ul li.message-from .attachment span.attachment-item a img{margin-right:0}.dashboard .chat ul li.message-from>div.file{background:#f1f1f1;border:1px solid #e4e4e4;border-radius:6px;display:inline-block;margin:1px;overflow:hidden;text-align:left}.dashboard .chat ul li .attachment span.attachment-item a>i{padding-right:8px}.dashboard .chat ul li div.file p.attachment{display:inline-block;margin-bottom:5px}.dashboard .chat ul li.message-from{text-align:left}.dashboard .chat ul li.message-own{text-align:right}.dashboard .chat ul li>div.file.image{height:170px;max-width:100%;padding:15px;transition:width .15s linear;width:220px}.dashboard .chat ul li>div.file.image p.attachment{height:120px}.dashboard .chat ul li>div.file{padding:15px}.dashboard .chat ul li>div.file p,.dashboard .chat ul li>div.file span{display:inline-block;margin:0;padding:0}.visible{opacity:1;transition:opacity .15s linear;visibility:visible}.hidden{opacity:0;transition:visibility 0s .1s,opacity .1s linear;visibility:hidden}.visible2{opacity:1;transition:opacity .35s linear;visibility:visible}.hidden2{opacity:0;transition:visibility 0s .3s,opacity .3s linear;visibility:hidden}.dashboard .chat{position:relative}.dashboard .chat .scroll-to-bottom{bottom:6px;min-height:40px;padding-right:12px;position:sticky;text-align:right}.dashboard .chat .scroll-to-bottom span{background:#495057;border:2px solid #fff;border-radius:50%;box-shadow:0 0 10px rgba(0,0,0,.34901960784313724);color:#fff;cursor:pointer;display:inline-block;font-size:20px;height:35px;line-height:35px;overflow:hidden;text-align:center;width:35px}.dashboard .chat .group-info{line-height:30px;margin:-10px;padding:5px 10px;top:0;z-index:99}.dashboard .chat .group-info,.dashboard .chat .pin{background:#fff;box-shadow:0 0 3px -1px rgba(0,0,0,.21176470588235294);position:sticky}.dashboard .chat .pin{margin-bottom:10px;margin-left:-10px;top:40px;width:calc(100% + 20px);z-index:98}.dashboard .chat ul li.message-from.pin>span,.dashboard .chat ul li.message-own.pin>span{background-color:transparent}.dashboard .chat ul li.message-from.pin>span{margin-left:0}.dashboard .chat .message-content i{color:#495057;cursor:pointer;font-size:11px}.dashboard .chat .pin .message-content i{display:block}.dashboard .chat li.message-from .message-content{padding-left:6px}.dashboard .chat li.message-from .message-content i{padding:5px}.dashboard .chat li.message-own .message-content i{padding:5px;position:absolute;right:-15px}.dashboard .chat .group-info .circleButton{float:right;margin-bottom:0;margin-top:0}.dashboard .chat ul{margin-top:20px;padding:0}.dashboard .chat .new-message .message-input input.ui-inputtext:focus{box-shadow:none;outline:none}.dashboard .chat ul.hasPin{margin-top:10px}.dashboard .chat .group-info a{color:#495057}.normalHtml,.normalHtml b,.normalHtml strong{font-weight:400}.normalHtml{display:inline-block}.avatar-viewer .profile-image{border:1px solid #fff;border-radius:50%;height:40px;margin-top:-6px;width:40px}a.button>i{margin-right:5px}.dashboard .timeline{padding-top:20px}.ui-inputgroup .ui-inputtext{padding-right:0}.new-message .ui-inputtext{width:100%}.full-screen,.full-screen>.p-dialog{height:100%!important;left:0!important;max-height:100%;min-height:unset!important;min-width:100%!important;top:0!important;width:100%!important}#image-view-list.image-gallery-2{background-color:rgba(0,0,0,.4);height:calc(100vh - 41px);margin:-14px auto 0;touch-action:none;width:100%}#image-view-list.image-gallery-2 .image-container{background-color:transparent;border:0;bottom:0;height:85%;margin:auto}#image-view-list.image-gallery-2 .image-container .iv-snap-view{bottom:20px;left:calc(50% - 75px);top:auto}#image-view-list.image-gallery-2 .image-container .iv-image-view img{touch-action:auto}#image-view-list .inline-icon{margin-top:-41px}#image-view-list .footer-info,#image-view-list .material-icons.next,#image-view-list .material-icons.prev{display:none}#image-view-list .options-image-viewer{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;margin-right:37px;user-select:none}.mobile-image-viewer-close{color:#fff;cursor:pointer;font-size:x-large;height:42px;line-height:42px;padding-right:7px;padding-top:2px;position:absolute;right:0;text-align:center;top:0;vertical-align:middle;width:37px}.mobile-image-viewer-close:hover{color:#feca37!important}.hide-holder{padding:0}.file-ex-name{word-break:break-all}.box-function{background:#fff;border-radius:0 0 5px 5px;border-top:1px solid #e8e8e8;bottom:0;left:0;padding:8px 30px;position:absolute;text-align:right;width:100%}.box-function button{margin-left:5px}.quick-note-button-holder{bottom:40px;display:none;height:50px;position:absolute;right:50px;width:50px;z-index:99}.quick-note-button{background:#ffc107;border:2px solid #fff;border-radius:50%;box-shadow:0 2px 5px 0 #b9b9b9;color:#fff;display:block;font-size:2em;height:50px;line-height:50px;outline:none;text-align:center;width:50px}.quick-note-button:hover{color:#fff}.all-note-button{background:#ffd24b;border:2px solid #fff;border-radius:50%;box-shadow:0 2px 5px 0 #b9b9b9;color:#fff;display:block;font-size:1.5em;height:40px;line-height:40px;outline:none;position:absolute;right:5px;text-align:center;top:5px;transition:right;transition-duration:.16s;transition-timing-function:ease-in;width:40px;z-index:-1}.all-note-button:hover{color:#fff}.setting-note-button{background:#ffd24b;border:2px solid #fff;border-radius:50%;box-shadow:0 2px 5px 0 #b9b9b9;color:#fff;display:block;font-size:1.5em;height:40px;line-height:40px;outline:none;position:absolute;right:5px;text-align:center;top:5px;transition:right;transition-duration:.16s;transition-timing-function:ease-in;width:40px;z-index:-1}.setting-note-button:hover{color:#fff}.pinned-notes-holder{bottom:20px;display:none;left:20px;position:absolute;width:250px;z-index:98}.pinned-notes{background:transparent;display:block;outline:none;padding:0}.pinned-notes-header{font-size:1rem;font-weight:700}.pinned-notes-setting{position:absolute;right:.5rem}.pinned-note{background-color:#fff1ac;box-shadow:1px 2px 3px rgba(185,139,6,.6313725490196078);font-size:.8rem;margin-bottom:10px;padding:0;position:relative}.pinned-note:last-child{margin-bottom:0}.pinned-notes-minimize-button{background:#ffc003;border:1px solid #fff;border-radius:50%;box-shadow:1px 2px 3px rgba(185,139,6,.6313725490196078);color:#fff;cursor:pointer;height:25px;padding-top:5px;position:absolute;right:-15px;text-align:center;top:-15px;width:25px;z-index:1}.pinned-note-header-line{border:1px solid #fff;box-shadow:1px 1px 2px rgba(0,0,0,.4);height:calc(100% - 1rem);left:3px;margin-bottom:.5rem;margin-top:.5rem;max-height:20px;position:absolute;width:13px}.pinned-note-header-right{cursor:pointer;float:right;margin-left:3px;width:32px}.pinned-note-header-time{font-size:.6rem}.pinned-note-header-button-unpin{display:none;float:left;height:14px;margin-right:2px;opacity:.8;width:14px}.pinned-note-header-button-complete{display:none;padding-top:2px}.pinned-note-body{float:right;padding:.5rem .5rem .5rem 25px;width:100%}.pinned-note-body:hover{background-color:#feeb82}.pinned-note-body:hover .pinned-note-header-time{display:none}.pinned-note-body:hover .pinned-note-header-button-complete,.pinned-note-body:hover .pinned-note-header-button-unpin{display:block}.pinned-note-line-title{color:#333;display:block;font-weight:700;padding-bottom:6px}.pinned-note-line{display:block}.view-port{border-radius:5px;box-shadow:0 0 0 9999px rgba(0,0,0,.5882352941176471);display:none;height:0;width:0;z-index:999}.view-port,.view-port-mask{background:transparent;position:absolute}.view-port-mask{display:block;height:100%;left:0;top:0;width:100%;z-index:9998}.tinymce-control{border:1px solid #ccc;display:none;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-size:14px;width:100%}.input-tab-trap{filter:alpha(opacity=0)!important;opacity:0!important;overflow:hidden!important;width:0!important}.color-value input{font-size:.8em;line-height:16px}.dialog-material.mobile{width:100%!important}audio,audio:focus,video,video:focus{outline:none}.iv-image-view img.iv-image{-webkit-animation:fadein .5s;animation:fadein .5s;visibility:hidden!important}@-webkit-keyframes fadein{0%{opacity:0}to{opacity:1}}@keyframes fadein{0%{opacity:0}to{opacity:1}}.iv-image-view img.iv-image.show{visibility:visible!important}.row-line{padding-bottom:0;padding-top:0}.fc-ltr{padding-bottom:7px}.padding-bottom-5px{padding-bottom:5px}.no-margin{margin:0!important}.no-padding{padding:0}.no-padding-left{padding-left:0}.float-left{float:left}body .fc .fc-toolbar .fc-button{background-color:#007ad9;border:1px solid #007ad9;border-radius:3px;color:#fff;font-size:14px;transition:background-color .2s,box-shadow .2s}body .fc .fc-toolbar .fc-button:enabled:hover{background-color:#116fbf;border-color:#116fbf;color:#fff}body .fc .fc-toolbar .fc-button:focus{box-shadow:0 0 0 .2em #8dcdff;outline:0 none;outline-offset:0}body .fc .fc-toolbar .fc-button-group .fc-button{border-radius:0}body .fc .fc-toolbar .fc-button-group .fc-button:first-child{border-bottom-left-radius:3px;border-top-left-radius:3px}body .fc .fc-toolbar .fc-button-group .fc-button:last-child{border-bottom-right-radius:3px;border-top-right-radius:3px}body .fc .fc-toolbar .fc-right .fc-button{border-radius:0}body .fc .fc-toolbar .fc-right .fc-button:first-child{border-bottom-left-radius:3px;border-top-left-radius:3px}body .fc .fc-toolbar .fc-right .fc-button:last-child{border-bottom-right-radius:3px;border-top-right-radius:3px}.fc-toolbar>*>:not(:first-child){margin-left:0}.fc-axis,.fc-dayGridMonth-button,.fc-timeGridDay-button,.fc-timeGridWeek-button,.old-content{line-height:0;text-indent:-9999px}.fc-axis:after,.fc-dayGridMonth-button:after,.fc-timeGridDay-button:after,.fc-timeGridWeek-button:after,.new-content{display:block;line-height:normal;text-indent:0}.fc-dayGridMonth-button:after{content:\"Th\u00E1ng\";padding:.2em}.fc-timeGridWeek-button:after{content:\"Tu\u1EA7n\";padding:.2em}.fc-timeGridDay-button:after{content:\"Ng\u00E0y\";padding:.2em}body .fc th{background-color:#f4f4f4;border:1px solid #c8c8c8;color:#333;padding:.571em 1em}.ui-fluid .button-group button,.ui-fluid .button-group p-button{margin-right:.5em!important;text-align:left;width:auto}.layout-wrapper .layout-menu-container{z-index:97}.base-status,.base-status-aborted,.base-status-approved,.base-status-completed,.base-status-create-new,.base-status-ended,.base-status-high,.base-status-immediately,.base-status-low,.base-status-medium,.base-status-on-conducting,.base-status-on-going,.base-status-pending,.base-status-rejected,.base-status-returned,.base-status-urgent{border-radius:.25em;color:#fff;font-size:.8em;padding:3px;text-align:center}.base-status-create-new{background-color:#f2f2f2;color:#666}.base-status-on-conducting,.base-status-on-going{background-color:#337ab7}.base-status-pending{background-color:#ffba01}.base-status-approved{background-color:#34a835}.base-status-returned{background-color:#ffba01}.base-status-rejected{background-color:#d9534f}.base-status-completed{background-color:#34a835}.base-status-aborted{background-color:#ffba01}.base-status-ended{background-color:#34a835}.base-status-low,.base-status-medium{background-color:#f2f2f2;color:#666}.base-status-high{background-color:#ffba01}.base-status-immediately,.base-status-urgent{background-color:#d9534f}.text-align-center{text-align:center}.font-weight-bold{font-weight:700}.landing-body .landing-menu li a:hover{border-bottom:none}.landing-body .landing-menu li:first-child{margin-left:8px}.crud-form .label-control p{margin:0;padding:0}.crud-form .tn-check-box-list .p-row{display:block;padding:.5em;width:100%}.crud-form dropdown,.crud-form tn-mask{width:100%}.crud-form .tn-dropdown{min-height:32px}.crud-form .tn-dropdown.free-text.horizontal{display:flex}.crud-form .tn-dropdown.free-text.horizontal>div{flex-grow:1;padding-left:.5em;padding-right:.5em}.crud-form .tn-dropdown.free-text.horizontal>div:first-child{padding-left:0}.crud-form .tn-dropdown.free-text.horizontal>div:last-child{padding-right:0}.crud-form .tn-dropdown.free-text.vertical input.ui-inputtext.input-free-text{margin-top:.5em}.crud-form.assessment .label-control{font-weight:700}.crud-form.assessment .label-control.haveIndex{display:block;margin-bottom:5px;padding-left:20px;position:relative}.crud-form.assessment .label-control.haveIndex:before{content:\" \" attr(label-index) \".\";left:0;position:absolute;top:0}.crud-form.assessment .ViewMode{border-bottom:none}.crud-form.assessment .ViewMode .label-control{margin-bottom:0}body .ui-inputtext.min-width{padding:6px}.ps__rail-x,.ps__rail-y{z-index:2}.zIndex5 .ps__rail-x,.zIndex5 .ps__rail-y{z-index:5}.table-sticky table{border-collapse:separate;border-spacing:0}.table-sticky tr td,.table-sticky tr th{border:1px solid #eee!important;border-left:none!important;border-top:none!important}.table-sticky tr td:first-child,.table-sticky tr th:first-child{border-left:1px solid #eee!important}.table-sticky tr td:last-child,.table-sticky tr th:last-child{border-right:none!important}.table-sticky tr:first-child th{border-top:1px solid #eee!important}.table-sticky th{background:#eee}.table-sticky tbody td.disabled{background:#eee!important}.table-sticky tbody td.disabled:not(:last-child){border-right:1px solid #fff!important}.table-sticky.fix-height tr:first-child th{position:sticky;top:0;z-index:2}.container-flex{align-items:center;display:flex}.container-flex>div:first-child{flex:0 0 auto;margin-right:.5em}.container-flex>div:last-child{flex-grow:1}.container-control{display:flex}.container-control>span.label{flex:0 0 auto;padding-right:.5em;padding-top:.5em}.container-control>span.label+*{flex-grow:1;flex-shrink:1;position:relative}.container-control>span.label+* .tn-dropdown,.container-control>span.label+* .ui-autocomplete-multiple,.container-control>span.label+* .ui-inputgroup .ui-inputtext{width:100%}.container-control>span.label+* .validation-container{margin-top:3px}.container-control>span.label+* .validation-container .validate-item{white-space:unset}.container-control>span.label+*>div{left:0;position:absolute;top:0;width:100%}.container-control.no-label>span.label{display:none}.container-control.inline{display:inline-flex}.align-flex-center{align-items:center;display:flex;justify-content:center}@media print{.isPrinting>*{display:none}.isPrinting app-print-layout{display:block}}.layout-wrapper .topbar .topbar-left,.layout-wrapper .topbar .topbar-right{background:#397ac3}#searchResultPanel-holder{padding:0 .5em}.cus-dropdown{line-height:normal;margin-right:1em}.tn-thumbnail{padding:.5rem}.tn-thumbnail.tn-thumbnail.tn-thumbnail{box-sizing:border-box}.fa-10:before{content:\"A+\";font-family:cursive;font-weight:700}.layout-wrapper .topbar .topbar-right #menu-button i{font-size:20px;margin-top:4px}.layout-wrapper .layout-menu li a i.menuitem-toggle-icon{font-size:15px;margin-left:auto}.flex-container-main-content{display:flex;flex-direction:column}.flex-container-main-content>div:last-child{background-color:#f4f4f4;display:flex;flex:1 1;overflow:hidden;position:relative}.flex-container-main-content>div:last-child>div{height:100%;left:0;overflow:hidden;padding-top:.5em;position:absolute;top:0;width:100%}.flex-container-main-content .block-with-button-search{display:flex;justify-content:flex-end}.flex-container-main-content .block-with-button-search>*{margin-left:.5em}.flex-container-main-content .block-with-button-search>input{height:26px;margin-left:0;max-width:200px;width:100%}.flex-container-main-content .block-with-button-search>dropdown{max-width:140px;width:100%}.flex-container-main-content .title-main-component{border-bottom:2px solid #1ca7ff}.clickable-table.clickable-table{cursor:pointer}.main-crud-container{height:calc(100vh - 76px)}.flex-container-fit-child{display:flex;flex-direction:column;height:100%;overflow:hidden}.flex-container-fit-child>div.fit-content{flex:1 1;position:relative}.flex-container-fit-child>div.fit-content>div{height:100%;overflow:auto;position:absolute;width:100%}.waiting-box{display:none;height:100%;left:0;position:fixed;top:0;width:100%;z-index:9999}.waiting-box .overlay{background-color:red;background-color:hsla(0,0%,42.7%,.5019607843137255);height:100%;width:100%}.waiting-box .content-loading{left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}.waiting-box.show{display:block}.function-topbar>*{vertical-align:top}.function-topbar button{width:auto}.function-topbar p-fileUpload{margin-right:1em}.function-topbar .container-control{display:inline-flex;line-height:normal}.function-topbar .container-control dropdown{width:100%}:focus{outline-color:#a6d5fa!important}address{font-style:normal}body .p-toast .p-toast-message{border-radius:0;border-width:0 0 0 4px!important}.__status span,.status span{font-size:.8rem}p-table.single-check .p-datatable .p-datatable-tbody>tr{cursor:pointer}p-table.single-check .p-datatable .p-datatable-tbody>tr.ui-state-highlight{background:#e3f2fd!important;outline:2px solid #a6d5fa}p-table.single-check .p-datatable .p-datatable-tbody>tr td.sticky .fix-sticky.top{display:none}p-table.multi-check .p-datatable .p-datatable-tbody>tr.ui-state-highlight{background:#e3f2fd!important}p-table.multi-check .p-datatable .p-datatable-tbody>tr.ui-state-highlight td{border-color:#fff}p-table.multi-check .p-datatable .p-datatable-tbody>tr.ui-state-highlight td .fix-sticky{background-color:#fff}.tn-animated-left-arrow-icon,.tn-animated-right-arrow-icon{height:32px;position:relative;width:14px;z-index:10}.tn-animated-right-arrow-icon{-webkit-animation:arrowBounceToRight .8s ease-in-out infinite alternate;animation:arrowBounceToRight .8s ease-in-out infinite alternate}.tn-animated-left-arrow-icon{-webkit-animation:arrowBounceToLeft .8s ease-in-out infinite alternate;animation:arrowBounceToLeft .8s ease-in-out infinite alternate}.tn-animated-left-arrow-icon:after,.tn-animated-left-arrow-icon:before,.tn-animated-right-arrow-icon:after,.tn-animated-right-arrow-icon:before{background-color:#88b0dd;content:\"\";display:block;height:20px;position:absolute;width:5px}.tn-animated-right-arrow-icon:before{left:4px;top:0;transform:rotate(-35deg)}.tn-animated-right-arrow-icon:after{left:4px;top:14px;transform:rotate(35deg)}.tn-animated-left-arrow-icon:before{right:4px;top:0;transform:rotate(35deg)}.tn-animated-left-arrow-icon:after{right:4px;top:14px;transform:rotate(-35deg)}@-webkit-keyframes arrowBounceToLeft{0%{transform:translateX(-3px)}to{transform:translateX(3px)}}@keyframes arrowBounceToLeft{0%{transform:translateX(-3px)}to{transform:translateX(3px)}}@-webkit-keyframes arrowBounceToRight{0%{transform:translateX(3px)}to{transform:translateX(-3px)}}@keyframes arrowBounceToRight{0%{transform:translateX(3px)}to{transform:translateX(-3px)}}.pass{color:#49c949}.not-pass,.pass{margin:5px;text-align:center}.not-pass{color:red}"]
43311
+ },] }
43312
+ ];
43313
+ ChatSendMessageBoxComponent.ctorParameters = () => [
43314
+ { type: Injector },
43315
+ { type: ChatService },
43316
+ { type: CheckControlVisibleService },
43317
+ { type: FileExplorerNewService },
43318
+ { type: NotifierService }
43319
+ ];
43320
+ ChatSendMessageBoxComponent.propDecorators = {
43321
+ fileElement: [{ type: ViewChild, args: ['fileElement', { static: false },] }],
43322
+ input: [{ type: ViewChild, args: ['input', { static: true },] }],
43323
+ driveFileDialog: [{ type: ViewChild, args: ['driveFileDialog', { static: false },] }]
43324
+ };
43325
+
43326
+ class UserPickerDialogComponent extends DataListBase {
43327
+ constructor(_userService, _injector) {
43328
+ super(_injector);
43329
+ this._userService = _userService;
43330
+ this.STORAGE_KEY_USER_PICKER_NAME = 'user_picker_storage_name';
43331
+ this.STORAGE_KEY_USER_PICKER_ID_USER = 'user_picker_storage_id_user';
43332
+ this.STORAGE_KEY_USER_PICKER_SEARCH_KEY = 'user_picker_storage_search_key';
43333
+ this.STORAGE_KEY_USER_PICKER_NODE_SELECTED = 'user_picker_storage_node';
43334
+ this.rootTreeNode = [
43335
+ {
43336
+ label: '',
43337
+ data: '-1',
43338
+ expandedIcon: 'pi pi-folder-open',
43339
+ collapsedIcon: 'pi pi-folder',
43340
+ children: []
43341
+ }
43342
+ ];
43343
+ this.multiple = false;
43344
+ this.enableCaching = true;
43345
+ this.isFirstLoad = true;
43346
+ this.rootFilter = {};
43347
+ }
43348
+ ngOnInit() {
43349
+ this.setting.baseService = this._userService;
43350
+ super.ngOnInit();
43351
+ }
43352
+ }
43353
+ UserPickerDialogComponent.decorators = [
43354
+ { type: Component, args: [{
43355
+ selector: 'app-user-picker-dialog',
43356
+ template: "<p>\r\n user-picker-dialog works!\r\n</p>\r\n",
43357
+ providers: [ComponentContextService],
43358
+ styles: [""]
43359
+ },] }
43360
+ ];
43361
+ UserPickerDialogComponent.ctorParameters = () => [
43362
+ { type: UserService },
43363
+ { type: Injector }
43364
+ ];
43365
+ UserPickerDialogComponent.propDecorators = {
43366
+ dialog: [{ type: ViewChild, args: ['dialog',] }],
43367
+ multiple: [{ type: Input }],
43368
+ enableCaching: [{ type: Input }],
43369
+ control: [{ type: Input }]
43370
+ };
43371
+
41818
43372
  function coreDeclaration() {
41819
43373
  return [
41820
43374
  AddressComponent,
@@ -41890,6 +43444,7 @@ function coreDeclaration() {
41890
43444
  StartWorkflowComponent,
41891
43445
  WorkflowPickerComponent,
41892
43446
  WorkflowSettingNewComponent,
43447
+ PermissionSharingComponent,
41893
43448
  TnDialogComponent,
41894
43449
  TnColorPickerComponent,
41895
43450
  TnCustomScrollbarComponent,
@@ -41956,7 +43511,10 @@ function coreDeclaration() {
41956
43511
  AddNewsComponent,
41957
43512
  CommonDashboardComponent,
41958
43513
  NotFoundComponent,
41959
- UniversalLinkProcessorComponent
43514
+ UniversalLinkProcessorComponent,
43515
+ ChatBoxComponent,
43516
+ ChatSendMessageBoxComponent,
43517
+ UserPickerDialogComponent
41960
43518
  ];
41961
43519
  }
41962
43520
  function coreModuleImport() {
@@ -43122,61 +44680,6 @@ EformService.ctorParameters = () => [
43122
44680
  { type: ModuleConfigService }
43123
44681
  ];
43124
44682
 
43125
- class CheckControlVisibleService {
43126
- constructor() { }
43127
- checkDisplayStatus(elem) {
43128
- return new Promise((resolve, reject) => {
43129
- this.doCheck(resolve, elem);
43130
- });
43131
- }
43132
- doCheck(resolve, elem) {
43133
- let timeoutCheckDisplayStatus;
43134
- timeoutCheckDisplayStatus = setTimeout(() => {
43135
- this.doCheck(resolve, elem);
43136
- }, 100);
43137
- var newStatus = this.isVisible(elem);
43138
- if (newStatus) {
43139
- setTimeout(() => {
43140
- // show control
43141
- resolve(true);
43142
- });
43143
- clearTimeout(timeoutCheckDisplayStatus);
43144
- }
43145
- }
43146
- isVisible(elem) {
43147
- const style = getComputedStyle(elem);
43148
- if (style.display === 'none')
43149
- return false;
43150
- if (style.visibility !== 'visible')
43151
- return false;
43152
- if (+style.opacity < 0.1)
43153
- return false;
43154
- if (elem.offsetWidth + elem.offsetHeight + elem.getBoundingClientRect().height +
43155
- elem.getBoundingClientRect().width === 0) {
43156
- return false;
43157
- }
43158
- const elemCenter = {
43159
- x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
43160
- y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
43161
- };
43162
- let pointContainer = document.elementFromPoint(elemCenter.x, elemCenter.y);
43163
- if (pointContainer) {
43164
- do {
43165
- if (pointContainer === elem)
43166
- return true;
43167
- } while (pointContainer = pointContainer.parentNode);
43168
- }
43169
- return false;
43170
- }
43171
- }
43172
- CheckControlVisibleService.ɵprov = ɵɵdefineInjectable({ factory: function CheckControlVisibleService_Factory() { return new CheckControlVisibleService(); }, token: CheckControlVisibleService, providedIn: "root" });
43173
- CheckControlVisibleService.decorators = [
43174
- { type: Injectable, args: [{
43175
- providedIn: 'root'
43176
- },] }
43177
- ];
43178
- CheckControlVisibleService.ctorParameters = () => [];
43179
-
43180
44683
  class ImageService {
43181
44684
  constructor(_moduleConfigService) {
43182
44685
  this._moduleConfigService = _moduleConfigService;
@@ -43738,5 +45241,5 @@ DynamicComponentService.ctorParameters = () => [
43738
45241
  * Generated bundle index. Do not edit.
43739
45242
  */
43740
45243
 
43741
- export { AccessDeniedComponent, Action, AddressControlSchema, AddressService, AdvanceSearchData, AdvanceSearchSetting, AppComponentBase, AppListService, ApplicationContextService, ApprovalPipe, ArrayPair, AtLeastOneRowTableValidator, AuthenService, AuthorizeDirective, AutoCompleteControlSchema, AutoCompletePickerControlSchema, AutocompleteDatasourceComponent, AvatarUploaderComponent, BaseCauHinhWorkflowComponent, BaseCongViecComponent, BaseCongViecFormComponent, BaseDmLoaiCongViecComponent, BaseDmPriorityComponent, BaseMenuService, BaseModule, BaseService, BooleanFormatPipe, ButtonControlSchema, CONFIG_CALENDAR_VIETNAMESE, CalculationEngineService, CanBoHoSoService, CauHinhWorkflowService, CellExcel, CheckBoxListControlSchema, CheckControlVisibleService, CheckDuplicateFieldsValidator, CheckDuplicateValidator, CheckboxControlSchema, ClientV5Service, CoCauToChucControlSchema, CoCauToChucPickerComponent, CoCauToChucPickerControlSchema, CoCauToChucService, ColorBlack, ColorControlSchema, ColorPickerControlSchema, ColorWhite, Column, ColumnSchemaBase, ColumnSetting, ColumnSettingDetail, ComCtxConstants, CommandType, CommonAppComponentComponent, CommonDashboardComponent, CommonErrorCode, CommonService, CompareValidator, ComponentBase, ComponentConstants, ComponentContextService, ConditionalBuilderService, CongViecLienQuanService, CongViecPickerControlSchema, CongViecService$1 as CongViecService, ContainerSchema, ControlTreeNode, ControlType, ConvertMoneyToWordPipe, CoreConfigService, CrudBase, CrudFormComponent, CrudFormCustomFunction, CrudFormData, CrudFormSetting, CrudListComponent, CrudListConfig, CrudListCustomFunction, CrudListData, CrudListHelper, CrudListSetting, CrudService, CustomControlSchema, CustomRouterService, DanhmucApiService, DataExcel, DataFormBase, DataListBase, DataSourceControlSchema, DataSourceStateType, DataSourceTargetType, DataSourceUserRule, DataSourceUserSender, DataSourceWorkflowCoreStatus, DataType, DateCompareValidator, DateTimeControlSchema, DateTimeRangeControlSchema, DbOrganizationOrganizationService, DbOrganizationPositionService, Deadline, DeadlineType, DhvinhGuardService, DialogModel, DmLoaiCongViecService, DmPriorityService, DomService, DownloadLinkService, DropdownComponent, DropdownControlSchema, DropdownOptions, DynamicComponentService, ENUM_DON_VI_HANH_CHINH, EXPLORER_TYPES, EXPORT_VERSION_V4, EXPORT_VERSION_V5, EditFileCommand, EditorControlSchema, EformService, EmailValidator, EntityMedataDataSetting, EntityMetadataService, EntityPickerColumn, EntityPickerControlSchema, EntityWorkflowType, EnumActionType, EnumControlPickerType, EnumFileLayout, EnumGetRefType, EnumLoaiDanhSachCongViec, EnumStateByMenuCongViec, EnumStateType, EnumTargetType, EnumTypeSplash, EnumUserRule, EnumWFNhomTrangThai, EnumWorkflowCoreCodeSettingKey, EnumWorkflowHistoryStatus, ErrorType, EventData, ExactOneValueInTableValidator, ExportAllMode, ExportItem, ExportItemType, ExportItemsMode, ExportManyModel, ExportManyResultModel, ExportModel, ExportService, ExportWithoutTemplateModel, Extension, FILE_TYPES, FieldDefineIsTaskFormControl, FieldDefineIsWorkflowControl, FileDataService, FileExplorerService, FileManagerComponent, FileManagerControlSchema, FileManagerMode, FileObjectService, FilePickerDialogComponent, FileUploadComponent, FileUploadControlSchema, FileUploadMode, FileV4Service, Filter, FolderService, FormControlBase, FormControlBaseWithService, FormSchemaBase, FormSchemaBaseWithService, FormState, Gender, GenerateLinkDownloadDTO, GenericGuardService, GetRefDataSchema, GlobalService, GmailCorrector, GridInfo, GuardService, GuardSvService, HeightType, HighPerformanceService, HighlightPipe, HtmlFormatPipe, ImageService, KeyFieldGetRefType, KeyFilterStateByMenuCongViec, KeyFlashShow, KeyValueComponent, KeyValueControlSchema, LabelSchema, LabelWFNhomTrangThai, LabelWorkflowCoreStatus, LengthValidator, ListHelperService, LoaiPhieuDeXuat, LocalCacheService, LowerCorrector, MA_THONG_BAO_PHAN_HE, ManagerType, MaskControlSchema, MasterDataItem, MasterDataPipe, MasterDataService, MenuService, MethodResult, ModelSchema, ModuleConfigService, MultiTranslateHttpLoader, MultipleReferenceDataFormatPipe, NodeService, NotificationObjectType, NotificationService, NotifierService, NumberCompareValidator, NumberOnlyValidator, NumberRangeControlSchema, Operator, OrganizationFormatPipe, OrganizationNameFormatPipe, OrganizationPickerControlSchema, OrganizationService, OrganizationsFormatPipe, PageInfo, PageSetting, Pair, Pattern, PercentControlSchema, PermissionBase, PermissionConstant, PermissionService, PermissionStorage, PermissionTypes, PermissionUtilsComponent, PersonalSetting, PhoneNumberValidator, PhoneValidator, PopupSize, PositionService, PrintService, PublicFunction, QueryBuilderComponent, QueryBuilderGroupComponent, QueryBuilderRuleComponent, QueryGroup, QueryRule, RadioButtonListControlSchema, RandomDataService, RefField, ReferenceDataFormatPipe, RegexSplitFieldByItem, RequiredFieldsValidator, RequiredValidator, RowColorOption, RowExcel, SHARE_COMPONENT_ID, SHARE_EVENT, SafeHtmlPipe, SafeStylePipe, SafeUrlPipe, SameValueValidator, SchemaBase, SecurePipe, ServiceFileUploadComponent, SessionTypes, SharedFolderType, SignalRService, SimpleDicItem, SimpleDictionary, Sort, SortDirs, SpanControlSchema, SplashComponentComponent, StartupBusinessComponentBase, StateComponent, StateMachineTopic, StateMachinesConnectionMetadataComponent, StateMachinesDesignerComponent, StateMachinesService, StateMetadataComponent, Status, StatusAction, StatusGroup, StatusOption, StatusOrg, StatusUser, StorageService, StorageUpdatedService, StringFormatPipe, SummaryPipe, SwitchControlSchema, TBL_DM_COSODAOTAO_CONSTS, TBL_DM_PHONGHOC_CONSTS, TBL_KTX_NGUOITHUE_HOSO, TBL_TS_PHIEUDEXUAT, TBL_TS_TAISANCODINH_CONSTS, TableSchema, TagSeparator, TemplateConstant, TemplateControlSchema, TemplateInstanceService, TemplateService, TemplateTextItem, TemplateTextMany, TemplateTextV4Service, TemplateType, TemplateV4Service, TenContainer, TextAlign, TextAreaControlSchema, TextControlSchema, TextControlSchemaWithService, TitleSchema, TnClientCommand, TnClientService, TnComponentConfig, TnCustomScrollbarComponent, TnDatePipe, TnReorderableColumnDirective, TnReorderableRowDirective, TnSortIcon, TnSortableColumnDirective, TnUser, TnxSharedModule, TopicReloadCongViecV5, TopicReloadNotification, TrangThaiMasterData, TrangThais, TreeDataOption, TrimCorrector, TrimEndCorrector, TrimStartCorrector, TypeDanhMucAPI, UniqueFieldInTableValidator, UniqueNumberService, UpperCorrector, UserFormatPipe, UserGroupService, UserPickerControlSchema, UserService, UserV5Service, UsersFormatPipe, Validation, VanBanPickerControlSchema, VirtualBaseService, WorkflowConfigAdvance, WorkflowCoreStatusEnum, WorkflowFieldStateCode, WorkflowPermissionDetailService, WorkflowPickerComponent, WorkflowService, WorkflowSetting, WorkflowSettingNew, WrapPickerControlSchema, addDay, addZero, appendDefaultFilter, clearAll, clone, cloneOld, coreDeclaration, coreModuleImport, coreProvider, createJsPlumnInstance, createOrgPickerControl, createRolePickerControl, createUserGroupPickerControl, createUserPickerControl, dataSourceIcon$1 as dataSourceIcon, dateDiff, genQueryFromFilters, getDateFromStringDateVN, getDayOfWeek, getEnvironmentByName, getEnvironmentData, getListMenuByName, getMenuData, getMonday, getStringDate, getStringDateTime, getStringDateVN, getStringDateVNLocal, getTimeSpan, isArray, isBoolean, isDate, isFunction, isLiteralObject, isNumber, isObjectOld, isRegular, isSimpleType, isString, isValidDate, keyUserSurveyLocal, maximumPageSize, mergeJSON, mergeJSONOld, moduleConfigFunc, multipleSort, romanize, setMetadataConnection, translateStateMachine, ɵ0, ɵ1, ɵ10, ɵ2, ɵ3, ɵ4, ɵ5, ɵ6, ɵ7, ɵ8, ɵ9, AddressComponent as ɵa, DropdownService as ɵb, DynamicNodeComponent as ɵba, EntityPickerBoxComponent as ɵbb, EntityPickerDataComponent as ɵbc, EntityPickerSelectedComponent as ɵbd, EntityPickerComponent as ɵbe, EntityPickerDialogComponent as ɵbf, EntityPermissionComponent as ɵbg, DM_ChucVuService as ɵbh, RoleService as ɵbi, EntityPermissionService as ɵbj, EquationEditorComponent as ɵbk, MaskComponent as ɵbl, NumberPickerRangeComponent as ɵbm, PagingNextBackOnlyComponent as ɵbn, RadioButtonListComponent as ɵbo, VanBanPickerComponent as ɵbp, VanBanDenService as ɵbq, VanBanDiService as ɵbr, VanBanPickerDialogComponent as ɵbs, VanbanDiPickerComponent as ɵbt, VanbanDenPickerComponent as ɵbu, CongViecPickerComponent as ɵbv, CongViecService as ɵbw, TaskWorkflowHistoriesService as ɵbx, SettingsComponent as ɵby, SettingsRowComponent as ɵbz, EntityPickerService as ɵc, SettingsWorkflowComponent as ɵca, SettingsWorkflowNo1Component as ɵcb, SimpleWorkflowFormComponent as ɵcc, ProcessWorkflowFormComponent as ɵcd, WorkflowHistoryService as ɵce, ProcessWorkflowTargetComponent as ɵcf, ChoYKienFormComponent as ɵcg, SplashComponentV1Component as ɵch, StateMachinesConnectionReceiverComponent as ɵci, StateMachinesConnectionReceiverUserComponent as ɵcj, StateMachinesConnectionReceiverDepartmentComponent as ɵck, StateMachinesConnectionReceiverGroupComponent as ɵcl, StateMachinesConnectionReceiverRoleComponent as ɵcm, StateMachinesConnectionSenderComponent as ɵcn, StartWorkflowComponent as ɵco, WorkflowSettingsService as ɵcp, WorkflowSettingNewComponent as ɵcq, TnDialogComponent as ɵcr, TnColorPickerComponent as ɵcs, TnTinymceComponent as ɵct, TnTabViewComponent as ɵcu, TableDetailFormComponent as ɵcv, FileIconPipe as ɵcw, FileSizePipe as ɵcx, QuickAddFormComponent as ɵcy, PreventShiftTabDirective as ɵcz, ExceptionHandlerService as ɵd, TnTemplateDirective as ɵda, UserPickerComponent as ɵdb, UserPickerBoxComponent as ɵdc, TnAppHelpComponent as ɵdd, PathNameService as ɵde, HelperCurrentPageComponent as ɵdf, TnAppNotificationListComponent as ɵdg, TnAppNotificationComponent as ɵdh, MyDriveService as ɵdi, FileVersionService as ɵdj, FileExplorerNewService as ɵdk, FolderFormComponent as ɵdl, FileFormComponent as ɵdm, FileViewerComponent as ɵdn, FileVersionListComponent as ɵdo, WorkflowHistoryComponent as ɵdp, EntityWorkflowHistoryService as ɵdq, WorkflowHistoryDialogComponent as ɵdr, WorkflowHistoryNewComponent as ɵds, WorkflowSettingComponent as ɵdt, EntityWorkflowSettingService as ɵdu, WorkflowSettingDialogComponent as ɵdv, QrCodeGeneratorComponent as ɵdw, AccessDeniedV1Component as ɵdx, AddNewsComponent as ɵdy, ArticleService as ɵdz, CanBo_HoSoService as ɵe, NewsCategoryService as ɵea, NotFoundComponent as ɵeb, UniversalLinkProcessorComponent as ɵec, CheckReadyComponent as ɵed, SendAccessTokenInterceptor as ɵee, LogInterceptor as ɵef, PermissionUtilsInterceptor as ɵeg, AfterViewCheckedComponent as ɵf, AdvanceSearchComponent as ɵg, AppRootMenuComponent as ɵh, AppTopBarComponent as ɵi, AppTopBarV1Component as ɵj, AppProfileComponent as ɵk, AppSubMenuComponent as ɵl, AppMenuComponent as ɵm, AutoCompletePickerComponent as ɵn, CheckBoxListComponent as ɵo, ReportQueueComponent as ɵp, CoCauToChucPickerListComponent as ɵq, BaseCongViecTestComponent as ɵr, BaseCauHinhWorkflowDetailComponent as ɵs, BaseDmLoaiCongViecFormComponent as ɵt, BaseDmPriorityFormComponent as ɵu, BaseCongviecDinhkemComponent as ɵv, CongviecDinhkemService as ɵw, BaseCongviecDinhkemFormComponent as ɵx, DatetimePickerComponent as ɵy, DatetimePickerRangeComponent as ɵz };
45244
+ export { AccessDeniedComponent, Action, AddressControlSchema, AddressService, AdvanceSearchData, AdvanceSearchSetting, AppComponentBase, AppListService, ApplicationContextService, ApprovalPipe, ArrayPair, AtLeastOneRowTableValidator, AuthenService, AuthorizeDirective, AutoCompleteControlSchema, AutoCompletePickerControlSchema, AutocompleteDatasourceComponent, AvatarUploaderComponent, BaseCauHinhWorkflowComponent, BaseCongViecComponent, BaseCongViecFormComponent, BaseDmLoaiCongViecComponent, BaseDmPriorityComponent, BaseMenuService, BaseModule, BaseService, BooleanFormatPipe, ButtonControlSchema, CONFIG_CALENDAR_VIETNAMESE, CalculationEngineService, CanBoHoSoService, CauHinhWorkflowService, CellExcel, ChatBoxComponent, ChatSendMessageBoxComponent, CheckBoxListControlSchema, CheckControlVisibleService, CheckDuplicateFieldsValidator, CheckDuplicateValidator, CheckboxControlSchema, ClientV5Service, CoCauToChucControlSchema, CoCauToChucPickerComponent, CoCauToChucPickerControlSchema, CoCauToChucService, ColorBlack, ColorControlSchema, ColorPickerControlSchema, ColorWhite, Column, ColumnSchemaBase, ColumnSetting, ColumnSettingDetail, ComCtxConstants, CommandType, CommonAppComponentComponent, CommonDashboardComponent, CommonErrorCode, CommonService, CompareValidator, ComponentBase, ComponentConstants, ComponentContextService, ConditionalBuilderService, CongViecLienQuanService, CongViecPickerControlSchema, CongViecService$1 as CongViecService, ContainerSchema, ControlTreeNode, ControlType, ConvertMoneyToWordPipe, CoreConfigService, CrudBase, CrudFormComponent, CrudFormCustomFunction, CrudFormData, CrudFormSetting, CrudListComponent, CrudListConfig, CrudListCustomFunction, CrudListData, CrudListHelper, CrudListSetting, CrudService, CustomControlSchema, CustomRouterService, DanhmucApiService, DataExcel, DataFormBase, DataListBase, DataSourceControlSchema, DataSourceStateType, DataSourceTargetType, DataSourceUserRule, DataSourceUserSender, DataSourceWorkflowCoreStatus, DataType, DateCompareValidator, DateTimeControlSchema, DateTimeRangeControlSchema, DbOrganizationOrganizationService, DbOrganizationPositionService, Deadline, DeadlineType, DhvinhGuardService, DialogModel, DmLoaiCongViecService, DmPriorityService, DomService, DownloadLinkService, DropdownComponent, DropdownControlSchema, DropdownOptions, DynamicComponentService, ENUM_DON_VI_HANH_CHINH, EXPLORER_TYPES, EXPORT_VERSION_V4, EXPORT_VERSION_V5, EditFileCommand, EditorControlSchema, EformService, EmailValidator, EntityMedataDataSetting, EntityMetadataService, EntityPickerColumn, EntityPickerControlSchema, EntityWorkflowType, EnumActionType, EnumControlPickerType, EnumFileLayout, EnumGetRefType, EnumLoaiDanhSachCongViec, EnumPermissionType, EnumStateByMenuCongViec, EnumStateType, EnumTargetType, EnumTypeSplash, EnumUserRule, EnumWFNhomTrangThai, EnumWorkflowCoreCodeSettingKey, EnumWorkflowHistoryStatus, ErrorType, EventData, ExactOneValueInTableValidator, ExportAllMode, ExportItem, ExportItemType, ExportItemsMode, ExportManyModel, ExportManyResultModel, ExportModel, ExportService, ExportWithoutTemplateModel, Extension, FILE_TYPES, FieldDefineIsTaskFormControl, FieldDefineIsWorkflowControl, FileDataService, FileExplorerService, FileManagerComponent, FileManagerControlSchema, FileManagerMode, FileObjectService, FilePickerDialogComponent, FileUploadComponent, FileUploadControlSchema, FileUploadMode, FileV4Service, Filter, FolderService, FormControlBase, FormControlBaseWithService, FormSchemaBase, FormSchemaBaseWithService, FormState, Gender, GenerateLinkDownloadDTO, GenericGuardService, GetRefDataSchema, GlobalService, GmailCorrector, GridInfo, GuardService, GuardSvService, HeightType, HighPerformanceService, HighlightPipe, HtmlFormatPipe, ImageService, KeyFieldGetRefType, KeyFilterStateByMenuCongViec, KeyFlashShow, KeyValueComponent, KeyValueControlSchema, LabelSchema, LabelWFNhomTrangThai, LabelWorkflowCoreStatus, LengthValidator, ListHelperService, LoaiPhieuDeXuat, LocalCacheService, LowerCorrector, MA_THONG_BAO_PHAN_HE, ManagerType, MaskControlSchema, MasterDataItem, MasterDataPipe, MasterDataService, MenuService, MethodResult, ModelSchema, ModuleConfigService, MultiTranslateHttpLoader, MultipleReferenceDataFormatPipe, NodeService, NotificationObjectType, NotificationService, NotifierService, NumberCompareValidator, NumberOnlyValidator, NumberRangeControlSchema, Operator, OrganizationFormatPipe, OrganizationNameFormatPipe, OrganizationPickerControlSchema, OrganizationService, OrganizationsFormatPipe, PageInfo, PageSetting, Pair, Pattern, PercentControlSchema, PermissionBase, PermissionConstant, PermissionService, PermissionStorage, PermissionTypes, PermissionUtilsComponent, PersonalSetting, PhoneNumberValidator, PhoneValidator, PopupSize, PositionService, PrintService, PublicFunction, QueryBuilderComponent, QueryBuilderGroupComponent, QueryBuilderRuleComponent, QueryGroup, QueryRule, RadioButtonListControlSchema, RandomDataService, RefField, ReferenceDataFormatPipe, RegexSplitFieldByItem, RequiredFieldsValidator, RequiredValidator, RowColorOption, RowExcel, SHARE_COMPONENT_ID, SHARE_EVENT, SafeHtmlPipe, SafeStylePipe, SafeUrlPipe, SameValueValidator, SchemaBase, SecurePipe, ServiceFileUploadComponent, SessionTypes, SharedFolderType, SignalRService, SimpleDicItem, SimpleDictionary, Sort, SortDirs, SpanControlSchema, SplashComponentComponent, StartupBusinessComponentBase, StateComponent, StateMachineTopic, StateMachinesConnectionMetadataComponent, StateMachinesDesignerComponent, StateMachinesService, StateMetadataComponent, Status, StatusAction, StatusGroup, StatusOption, StatusOrg, StatusUser, StorageService, StorageUpdatedService, StringFormatPipe, SummaryPipe, SwitchControlSchema, TBL_DM_COSODAOTAO_CONSTS, TBL_DM_PHONGHOC_CONSTS, TBL_KTX_NGUOITHUE_HOSO, TBL_TS_PHIEUDEXUAT, TBL_TS_TAISANCODINH_CONSTS, TableSchema, TagSeparator, TemplateConstant, TemplateControlSchema, TemplateInstanceService, TemplateService, TemplateTextItem, TemplateTextMany, TemplateTextV4Service, TemplateType, TemplateV4Service, TenContainer, TextAlign, TextAreaControlSchema, TextControlSchema, TextControlSchemaWithService, TitleSchema, TnClientCommand, TnClientService, TnComponentConfig, TnCustomScrollbarComponent, TnDatePipe, TnReorderableColumnDirective, TnReorderableRowDirective, TnSortIcon, TnSortableColumnDirective, TnUser, TnxSharedModule, TopicReloadCongViecV5, TopicReloadNotification, TrangThaiMasterData, TrangThais, TreeDataOption, TrimCorrector, TrimEndCorrector, TrimStartCorrector, TypeDanhMucAPI, UniqueFieldInTableValidator, UniqueNumberService, UpperCorrector, UserFormatPipe, UserGroupService, UserPickerControlSchema, UserPickerDialogComponent, UserService, UserV5Service, UsersFormatPipe, Validation, VanBanPickerControlSchema, VirtualBaseService, WorkflowConfigAdvance, WorkflowCoreStatusEnum, WorkflowFieldStateCode, WorkflowPermissionDetailService, WorkflowPickerComponent, WorkflowService, WorkflowSetting, WorkflowSettingNew, WrapPickerControlSchema, addDay, addZero, appendDefaultFilter, clearAll, clone, cloneOld, coreDeclaration, coreModuleImport, coreProvider, createJsPlumnInstance, createOrgPickerControl, createRolePickerControl, createUserGroupPickerControl, createUserPickerControl, dataSourceIcon$1 as dataSourceIcon, dateDiff, genQueryFromFilters, getDateFromStringDateVN, getDayOfWeek, getEnvironmentByName, getEnvironmentData, getListMenuByName, getMenuData, getMonday, getStringDate, getStringDateTime, getStringDateVN, getStringDateVNLocal, getTimeSpan, isArray, isBoolean, isDate, isFunction, isLiteralObject, isNumber, isObjectOld, isRegular, isSimpleType, isString, isValidDate, keyUserSurveyLocal, maximumPageSize, mergeJSON, mergeJSONOld, moduleConfigFunc, multipleSort, romanize, setMetadataConnection, translateStateMachine, ɵ0, ɵ1, ɵ10, ɵ2, ɵ3, ɵ4, ɵ5, ɵ6, ɵ7, ɵ8, ɵ9, AddressComponent as ɵa, DropdownService as ɵb, DynamicNodeComponent as ɵba, EntityPickerBoxComponent as ɵbb, EntityPickerDataComponent as ɵbc, EntityPickerSelectedComponent as ɵbd, EntityPickerComponent as ɵbe, EntityPickerDialogComponent as ɵbf, EntityPermissionComponent as ɵbg, DM_ChucVuService as ɵbh, RoleService as ɵbi, EntityPermissionService as ɵbj, EquationEditorComponent as ɵbk, MaskComponent as ɵbl, NumberPickerRangeComponent as ɵbm, PagingNextBackOnlyComponent as ɵbn, RadioButtonListComponent as ɵbo, VanBanPickerComponent as ɵbp, VanBanDenService as ɵbq, VanBanDiService as ɵbr, VanBanPickerDialogComponent as ɵbs, VanbanDiPickerComponent as ɵbt, VanbanDenPickerComponent as ɵbu, CongViecPickerComponent as ɵbv, CongViecService as ɵbw, TaskWorkflowHistoriesService as ɵbx, SettingsComponent as ɵby, SettingsRowComponent as ɵbz, EntityPickerService as ɵc, SettingsWorkflowComponent as ɵca, SettingsWorkflowNo1Component as ɵcb, SimpleWorkflowFormComponent as ɵcc, ProcessWorkflowFormComponent as ɵcd, WorkflowHistoryService as ɵce, ProcessWorkflowTargetComponent as ɵcf, ChoYKienFormComponent as ɵcg, SplashComponentV1Component as ɵch, StateMachinesConnectionReceiverComponent as ɵci, StateMachinesConnectionReceiverUserComponent as ɵcj, StateMachinesConnectionReceiverDepartmentComponent as ɵck, StateMachinesConnectionReceiverGroupComponent as ɵcl, StateMachinesConnectionReceiverRoleComponent as ɵcm, StateMachinesConnectionSenderComponent as ɵcn, StartWorkflowComponent as ɵco, WorkflowSettingsService as ɵcp, WorkflowSettingNewComponent as ɵcq, PermissionSharingComponent as ɵcr, WorkflowPermissionService as ɵcs, TnDialogComponent as ɵct, TnColorPickerComponent as ɵcu, TnTinymceComponent as ɵcv, TnTabViewComponent as ɵcw, TableDetailFormComponent as ɵcx, FileIconPipe as ɵcy, FileSizePipe as ɵcz, ExceptionHandlerService as ɵd, QuickAddFormComponent as ɵda, PreventShiftTabDirective as ɵdb, TnTemplateDirective as ɵdc, UserPickerComponent as ɵdd, UserPickerBoxComponent as ɵde, TnAppHelpComponent as ɵdf, PathNameService as ɵdg, HelperCurrentPageComponent as ɵdh, TnAppNotificationListComponent as ɵdi, TnAppNotificationComponent as ɵdj, MyDriveService as ɵdk, FileVersionService as ɵdl, FileExplorerNewService as ɵdm, FolderFormComponent as ɵdn, FileFormComponent as ɵdo, FileViewerComponent as ɵdp, FileVersionListComponent as ɵdq, WorkflowHistoryComponent as ɵdr, EntityWorkflowHistoryService as ɵds, WorkflowHistoryDialogComponent as ɵdt, WorkflowHistoryNewComponent as ɵdu, WorkflowSettingComponent as ɵdv, EntityWorkflowSettingService as ɵdw, WorkflowSettingDialogComponent as ɵdx, QrCodeGeneratorComponent as ɵdy, AccessDeniedV1Component as ɵdz, CanBo_HoSoService as ɵe, AddNewsComponent as ɵea, ArticleService as ɵeb, NewsCategoryService as ɵec, NotFoundComponent as ɵed, UniversalLinkProcessorComponent as ɵee, ChatService as ɵef, ContentsService as ɵeg, StatusExtendsService as ɵeh, MessageBoardService as ɵei, CheckReadyComponent as ɵej, SendAccessTokenInterceptor as ɵek, LogInterceptor as ɵel, PermissionUtilsInterceptor as ɵem, AfterViewCheckedComponent as ɵf, AdvanceSearchComponent as ɵg, AppRootMenuComponent as ɵh, AppTopBarComponent as ɵi, AppTopBarV1Component as ɵj, AppProfileComponent as ɵk, AppSubMenuComponent as ɵl, AppMenuComponent as ɵm, AutoCompletePickerComponent as ɵn, CheckBoxListComponent as ɵo, ReportQueueComponent as ɵp, CoCauToChucPickerListComponent as ɵq, BaseCongViecTestComponent as ɵr, BaseCauHinhWorkflowDetailComponent as ɵs, BaseDmLoaiCongViecFormComponent as ɵt, BaseDmPriorityFormComponent as ɵu, BaseCongviecDinhkemComponent as ɵv, CongviecDinhkemService as ɵw, BaseCongviecDinhkemFormComponent as ɵx, DatetimePickerComponent as ɵy, DatetimePickerRangeComponent as ɵz };
43742
45245
  //# sourceMappingURL=tnx-shared.js.map