tnx-shared 5.1.417 → 5.1.418

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.
@@ -13,7 +13,7 @@ import { TranslateService, TranslateModule, TranslateLoader } from '@ngx-transla
13
13
  import { MessageService, ConfirmationService, PrimeNGConfig } from 'tn-custom-primeng/api';
14
14
  import { ActivatedRoute, Router, NavigationStart, NavigationEnd } from '@angular/router';
15
15
  import { HubConnectionBuilder } from '@aspnet/signalr';
16
- import { saveAs } from 'file-saver';
16
+ import FileSaver, { saveAs } from 'file-saver';
17
17
  import printJS$3 from 'print-js';
18
18
  import { FileUpload, FileUploadModule } from 'tn-custom-primeng/fileupload';
19
19
  import { DomSanitizer, BrowserModule, Title } from '@angular/platform-browser';
@@ -17328,7 +17328,6 @@ class ExportService {
17328
17328
  this._http = _http;
17329
17329
  this._injector = _injector;
17330
17330
  this._commonService = _commonService;
17331
- this._moduleConfigService = _moduleConfigService;
17332
17331
  this._moduleConfig = _moduleConfigService.getConfig();
17333
17332
  this.environment = this._moduleConfig.environment;
17334
17333
  this.serviceUri = `${this._moduleConfig.environment.apiDomain.templateEndpoint}/Export`;
@@ -17345,7 +17344,13 @@ class ExportService {
17345
17344
  const data = new Blob([buffer], {
17346
17345
  type: EXCEL_TYPE$1
17347
17346
  });
17348
- saveAs(data, fileName + '_' + new Date().getTime() + EXCEL_EXTENSION$1);
17347
+ FileSaver.saveAs(data, fileName + '_' + new Date().getTime() + EXCEL_EXTENSION$1);
17348
+ }
17349
+ saveSpreadSheet(buffer, fileName) {
17350
+ const data = new Blob([buffer], {
17351
+ type: EXCEL_TYPE$1
17352
+ });
17353
+ FileSaver.saveAs(data, new Date().getTime() + '_' + fileName);
17349
17354
  }
17350
17355
  }
17351
17356
  ExportService.ɵprov = ɵɵdefineInjectable({ factory: function ExportService_Factory() { return new ExportService(ɵɵinject(HttpClient), ɵɵinject(INJECTOR), ɵɵinject(CommonService), ɵɵinject(ModuleConfigService)); }, token: ExportService, providedIn: "root" });
@@ -23434,11 +23439,13 @@ class FileObjectService extends BaseService {
23434
23439
  super(http, injector, `${_moduleConfigService.getConfig().environment.apiDomain.fileEndpoint}/${_moduleConfigService.getConfig().environment.apiVersion}/FileObject`);
23435
23440
  this._moduleConfigService = _moduleConfigService;
23436
23441
  this.thumborEndpoint = '';
23442
+ this.fileWithThumborEndpoint = '';
23437
23443
  this.endPoint = _moduleConfigService.getConfig().environment.apiDomain.fileEndpoint;
23444
+ this.fileWithThumborEndpoint = _moduleConfigService.getConfig().environment.apiDomain.fileWithThumborEndpoint;
23438
23445
  this.thumborEndpoint = _moduleConfigService.getConfig().environment.apiDomain.thumbor;
23439
23446
  }
23440
23447
  getFileUrlWithThumbor(fileId, width = 0, height = 0) {
23441
- const url = `${this.thumborEndpoint}/unsafe/${width}x${height}/smart/${this.endPoint}/v5/FileObject/public/${fileId}/download`;
23448
+ const url = `${this.thumborEndpoint}/unsafe/${width}x${height}/smart/${this.fileWithThumborEndpoint}/v5/FileObject/public/${fileId}/download`;
23442
23449
  return url;
23443
23450
  }
23444
23451
  getUrlImage(fileId) {
@@ -23605,6 +23612,12 @@ class FileObjectService extends BaseService {
23605
23612
  }
23606
23613
  return result;
23607
23614
  }
23615
+ uploadWithByteArray(file) {
23616
+ const formData = new FormData();
23617
+ formData.append('files', file);
23618
+ const url = `${this.serviceUri}/UploadWithByteArray`;
23619
+ return this._http.post(url, formData, { responseType: 'text' }).toPromise();
23620
+ }
23608
23621
  }
23609
23622
  FileObjectService.ɵprov = ɵɵdefineInjectable({ factory: function FileObjectService_Factory() { return new FileObjectService(ɵɵinject(HttpClient), ɵɵinject(INJECTOR), ɵɵinject(ModuleConfigService)); }, token: FileObjectService, providedIn: "root" });
23610
23623
  FileObjectService.decorators = [
@@ -49399,11 +49412,12 @@ TnTemplateComponent.propDecorators = {
49399
49412
  };
49400
49413
 
49401
49414
  class TnTinymceComponent extends ComponentBase {
49402
- constructor(injector, _deviceDetectorService, _notifierService, _fileService) {
49415
+ constructor(injector, _deviceDetectorService, _notifierService, _fileService, _fileObjectService) {
49403
49416
  super(injector);
49404
49417
  this._deviceDetectorService = _deviceDetectorService;
49405
49418
  this._notifierService = _notifierService;
49406
49419
  this._fileService = _fileService;
49420
+ this._fileObjectService = _fileObjectService;
49407
49421
  this.mode = 'basic';
49408
49422
  this.disabled = false;
49409
49423
  this.required = false;
@@ -49536,19 +49550,35 @@ class TnTinymceComponent extends ComponentBase {
49536
49550
  }).on('focus', e => {
49537
49551
  editorHolder.classList.add('tinymce-focus');
49538
49552
  }).on('paste', (e) => {
49553
+ const begin = new Date();
49539
49554
  const types = e.originalEvent.clipboardData.types;
49540
- if (((types instanceof DOMStringList) && types.contains('text/html')) || (types.indexOf && types.indexOf('text/html') !== -1)) {
49555
+ if (((types instanceof DOMStringList) && types.contains('text/html')) || (types.indexOf && (types.indexOf('text/html') !== -1) || types.indexOf('Files') !== -1)) {
49556
+ this._notifierService.showSuccess('Đang tiến hành xử lý nội dung, vui lòng chờ trong giây lát!');
49541
49557
  e.originalEvent.stopPropagation();
49542
49558
  e.originalEvent.preventDefault();
49543
- this.handlePaste(e.originalEvent).then((content) => {
49544
- if (content) {
49545
- // content = content.replace(/<!\[if[\s\S]*?>/gm, '').replace(/<!\[endif[\s\S]*?>/gm, '');
49546
- content = this.normalizeHTML(content, '<![if !supportLists]>', '<![endif]>');
49547
- content = this.normalizeHTML(content, '<![if !msEquation]>', '<![endif]>');
49548
- editor.execCommand('mceInsertContent', false, content);
49559
+ const types = e.originalEvent.clipboardData.types;
49560
+ const files = e.originalEvent.clipboardData.files;
49561
+ let pastedData = '';
49562
+ let pastedRtfData = '';
49563
+ if ((e.originalEvent.clipboardData.types instanceof DOMStringList && e.originalEvent.clipboardData.types.contains('text/html')) || (e.originalEvent.clipboardData.types.indexOf && e.originalEvent.clipboardData.types.indexOf('text/html') !== -1)) {
49564
+ pastedData = e.originalEvent.clipboardData.getData('text/html');
49565
+ if (((e.originalEvent.clipboardData.types instanceof DOMStringList) && e.originalEvent.clipboardData.types.contains('text/rtf')) || (e.originalEvent.clipboardData.types.indexOf && e.originalEvent.clipboardData.types.indexOf('text/rtf') !== -1)) {
49566
+ pastedRtfData = e.originalEvent.clipboardData.getData('text/rtf');
49549
49567
  }
49550
- });
49551
- return false;
49568
+ }
49569
+ setTimeout(() => {
49570
+ this.handlePaste(types, pastedData, pastedRtfData, files).then((content) => {
49571
+ const end = new Date();
49572
+ console.log('Time to run handlePaste is ' + (end.getTime() - begin.getTime()) + 'ms');
49573
+ if (content) {
49574
+ // content = content.replace(/<!\[if[\s\S]*?>/gm, '').replace(/<!\[endif[\s\S]*?>/gm, '');
49575
+ content = this.normalizeHTML(content, '<![if !supportLists]>', '<![endif]>');
49576
+ content = this.normalizeHTML(content, '<![if !msEquation]>', '<![endif]>');
49577
+ editor.execCommand('mceInsertContent', false, content);
49578
+ }
49579
+ });
49580
+ return false;
49581
+ }, 500);
49552
49582
  }
49553
49583
  }).on('keydown', (e) => {
49554
49584
  if (e.ctrlKey || e.metaKey) {
@@ -49670,9 +49700,9 @@ class TnTinymceComponent extends ComponentBase {
49670
49700
  this.editor.focus();
49671
49701
  }
49672
49702
  }
49673
- handlePaste(e) {
49703
+ handlePaste(types, pastedData, pastedRtfData, files) {
49674
49704
  return __awaiter(this, void 0, void 0, function* () {
49675
- return new Promise((resolve) => {
49705
+ return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
49676
49706
  const images = [];
49677
49707
  let oldLegacyValue = false;
49678
49708
  const settings = {
@@ -49695,19 +49725,19 @@ class TnTinymceComponent extends ComponentBase {
49695
49725
  }
49696
49726
  }
49697
49727
  };
49698
- const types = e.clipboardData.types;
49699
- if (((types instanceof DOMStringList) && types.contains('text/html')) || (types.indexOf && types.indexOf('text/html') !== -1)) {
49700
- let pastedData = e.clipboardData.getData('text/html');
49728
+ if (types.indexOf('text/html') !== -1) {
49701
49729
  if (pastedData.indexOf('<v:imagedata ') == -1) {
49702
49730
  resolve(pastedData);
49703
49731
  }
49704
49732
  else {
49705
- if (((types instanceof DOMStringList) && types.contains('text/rtf')) || (types.indexOf && types.indexOf('text/rtf') !== -1)) {
49706
- const pastedRtfData = e.clipboardData.getData('text/rtf');
49733
+ if (types.indexOf('text/rtf') !== -1) {
49707
49734
  const doc = new RTFJS.Document(this._commonService.stringToArrayBuffer(pastedRtfData), settings);
49708
- doc.render().then((htmlElements) => {
49735
+ doc.render().then((htmlElements) => __awaiter(this, void 0, void 0, function* () {
49709
49736
  let index = pastedData.indexOf('<v:imagedata ');
49710
49737
  let i = 0;
49738
+ const imageUploaded = [];
49739
+ let docm = new DOMParser().parseFromString(pastedData, 'text/html');
49740
+ let img = docm.getElementsByTagName('img');
49711
49741
  while (index > -1) {
49712
49742
  const p1 = pastedData.substring(0, index);
49713
49743
  const index2 = pastedData.indexOf('/>', index);
@@ -49715,27 +49745,67 @@ class TnTinymceComponent extends ComponentBase {
49715
49745
  break;
49716
49746
  else {
49717
49747
  const p2 = pastedData.substring(index2 + 2);
49718
- let imageStr = '';
49719
49748
  if (images.length > i) {
49720
- imageStr = images[i];
49749
+ const indexImg = images[i].indexOf('<img src=');
49750
+ if (indexImg !== -1) {
49751
+ images[i] = images[i].substring(indexImg + 10, images[i].length - 2);
49752
+ }
49753
+ const imageType = images[i].substring(5, images[i].indexOf(';'));
49754
+ const base64 = images[i].substring(images[i].indexOf('base64,') + 7);
49755
+ const imageBlob = this.dataURItoBlob(base64, imageType);
49756
+ const srcArr = img[i].src.split('/');
49757
+ const fileName = srcArr[srcArr.length - 1];
49758
+ const file = new File([imageBlob], fileName, { type: imageType });
49759
+ const uploadImage = yield this._fileObjectService.uploadWithByteArray(file);
49760
+ if (typeof uploadImage == 'string') {
49761
+ imageUploaded.push(this._fileObjectService.getUrlImage(uploadImage));
49762
+ }
49763
+ else {
49764
+ this._notifierService.showWarning('Upload file thất bại');
49765
+ }
49721
49766
  }
49722
- pastedData = p1 + imageStr + p2;
49767
+ pastedData = p1 + '<img src=' + imageUploaded[i] + '/>' + p2;
49723
49768
  index = pastedData.indexOf('<v:imagedata ');
49724
49769
  i++;
49725
49770
  }
49726
49771
  }
49727
- resolve(pastedData);
49728
- }).catch(err => {
49772
+ docm = new DOMParser().parseFromString(pastedData, 'text/html');
49773
+ img = docm.getElementsByTagName('img');
49774
+ for (let i = 0; i < images.length; i++) {
49775
+ if (imageUploaded[i]) {
49776
+ img[i].src = imageUploaded[i];
49777
+ img[i].alt = imageUploaded[i];
49778
+ }
49779
+ }
49780
+ let result = '';
49781
+ result = new XMLSerializer().serializeToString(docm);
49782
+ resolve(result);
49783
+ })).catch(err => {
49729
49784
  console.error(err);
49730
49785
  resolve(null);
49731
49786
  });
49732
49787
  }
49733
49788
  }
49734
49789
  }
49790
+ else if (types.indexOf('Files') !== -1) {
49791
+ let result = '';
49792
+ if (files.length > 0) {
49793
+ for (const item of files) {
49794
+ const uploadImage = yield this._fileObjectService.uploadWithByteArray(item);
49795
+ if (typeof uploadImage == 'string') {
49796
+ result += '<img src=' + this._fileObjectService.getUrlImage(uploadImage) + '/>';
49797
+ }
49798
+ else {
49799
+ this._notifierService.showWarning('Upload file thất bại');
49800
+ }
49801
+ }
49802
+ }
49803
+ resolve(result);
49804
+ }
49735
49805
  else {
49736
49806
  resolve(null);
49737
49807
  }
49738
- });
49808
+ }));
49739
49809
  });
49740
49810
  }
49741
49811
  openFileManager() {
@@ -49762,11 +49832,21 @@ class TnTinymceComponent extends ComponentBase {
49762
49832
  this.showTemplate = false;
49763
49833
  this.editor.insertContent(evt);
49764
49834
  }
49835
+ dataURItoBlob(dataURI, fileType) {
49836
+ const byteString = window.atob(dataURI);
49837
+ const arrayBuffer = new ArrayBuffer(byteString.length);
49838
+ const int8Array = new Uint8Array(arrayBuffer);
49839
+ for (let i = 0; i < byteString.length; i++) {
49840
+ int8Array[i] = byteString.charCodeAt(i);
49841
+ }
49842
+ const blob = new Blob([int8Array], { type: fileType });
49843
+ return blob;
49844
+ }
49765
49845
  }
49766
49846
  TnTinymceComponent.decorators = [
49767
49847
  { type: Component, args: [{
49768
49848
  selector: 'tn-tinymce',
49769
- template: "<input *ngIf=\"!_deviceDetectorService.isDesktop()\" class=\"input-tab-trap\" (focus)=\"focusTrap($event)\" />\r\n<textarea class=\"tinymce-control\" id={{id}} [ngStyle]=\"{height: height+'px'}\">\r\n</textarea>\r\n<tn-dialog #dialog *ngIf=\"equationFormModel.show\" [closeOnEscape]=\"false\"\r\n [header]=\"'C\u00F4ng th\u1EE9c to\u00E1n h\u1ECDc (d\u00F9ng laTex)' | translate\" [popupSize]=\"popupSize\">\r\n <tn-custom-scrollbar #scrollbar>\r\n <equation-editor [data]=\"dataEquation\">\r\n </equation-editor>\r\n </tn-custom-scrollbar>\r\n <ng-template #footer>\r\n <button icon=\"fas fa-check\" [disabled]=\"model.submitting\" pButton type=\"button\" (click)=\"handleOk($event)\"\r\n [label]=\"'Ok' | translate\"></button>\r\n <button icon=\"fas fa-undo\" [disabled]=\"model.submitting\" pButton class=\"ui-button-secondary\" type=\"button\"\r\n (click)=\"equationFormModel.show = false\" [label]=\"'FORM.CANCEL' | translate\"></button>\r\n </ng-template>\r\n</tn-dialog>\r\n\r\n<tn-dialog *ngIf=\"isAddNews\" #dialog [styleClass]=\"'address-form'\" [header]=\"header | translate\" [popupSize]=\"popupSize\"\r\n (onHide)=\"isAddNews = false\">\r\n <add-news #listBase [languageCode]=\"languageCode\" (showChange)=\"showChanged($event)\"></add-news>\r\n</tn-dialog>\r\n\r\n<tn-dialog *ngIf=\"showTemplate\" #dialog [styleClass]=\"'address-form'\" [header]=\"header | translate\" [popupSize]=\"popupSize\"\r\n (onHide)=\"showTemplate = false\">\r\n <tn-template (onChanged)=\"addTemplate($event)\"></tn-template>\r\n</tn-dialog>\r\n\r\n<tn-dialog *ngIf=\"isAddFile\" #dialog [styleClass]=\"'address-form'\" [header]=\"header | translate\" [popupSize]=\"popupSize\"\r\n (onHide)=\"isAddFile = false\">\r\n <file-picker-dialog #formBase [parentModel]=\" model\" [parentContext]=\"context\" (closeForm)=\"isAddFile = false\"\r\n (onCancel)=\"handleRFCancel($event)\" (onChanged)=\"showChanged($event)\">\r\n </file-picker-dialog>\r\n</tn-dialog>\r\n",
49849
+ template: "<input *ngIf=\"!_deviceDetectorService.isDesktop()\" class=\"input-tab-trap\" (focus)=\"focusTrap($event)\" />\r\n<textarea class=\"tinymce-control\" id={{id}} [ngStyle]=\"{height: height+'px'}\"></textarea>\r\n<tn-dialog #dialog *ngIf=\"equationFormModel.show\" [closeOnEscape]=\"false\"\r\n [header]=\"'C\u00F4ng th\u1EE9c to\u00E1n h\u1ECDc (d\u00F9ng laTex)' | translate\" [popupSize]=\"popupSize\">\r\n <tn-custom-scrollbar #scrollbar>\r\n <equation-editor [data]=\"dataEquation\">\r\n </equation-editor>\r\n </tn-custom-scrollbar>\r\n <ng-template #footer>\r\n <button icon=\"fas fa-check\" [disabled]=\"model.submitting\" pButton type=\"button\" (click)=\"handleOk($event)\"\r\n [label]=\"'Ok' | translate\"></button>\r\n <button icon=\"fas fa-undo\" [disabled]=\"model.submitting\" pButton class=\"ui-button-secondary\" type=\"button\"\r\n (click)=\"equationFormModel.show = false\" [label]=\"'FORM.CANCEL' | translate\"></button>\r\n </ng-template>\r\n</tn-dialog>\r\n\r\n<tn-dialog *ngIf=\"isAddNews\" #dialog [styleClass]=\"'address-form'\" [header]=\"header | translate\" [popupSize]=\"popupSize\"\r\n (onHide)=\"isAddNews = false\">\r\n <add-news #listBase [languageCode]=\"languageCode\" (showChange)=\"showChanged($event)\"></add-news>\r\n</tn-dialog>\r\n\r\n<tn-dialog *ngIf=\"showTemplate\" #dialog [styleClass]=\"'address-form'\" [header]=\"header | translate\"\r\n [popupSize]=\"popupSize\" (onHide)=\"showTemplate = false\">\r\n <tn-template (onChanged)=\"addTemplate($event)\"></tn-template>\r\n</tn-dialog>\r\n\r\n<tn-dialog *ngIf=\"isAddFile\" #dialog [styleClass]=\"'address-form'\" [header]=\"header | translate\" [popupSize]=\"popupSize\"\r\n (onHide)=\"isAddFile = false\">\r\n <file-picker-dialog #formBase [parentModel]=\" model\" [parentContext]=\"context\" (closeForm)=\"isAddFile = false\"\r\n (onCancel)=\"handleRFCancel($event)\" (onChanged)=\"showChanged($event)\">\r\n </file-picker-dialog>\r\n</tn-dialog>",
49770
49850
  providers: [
49771
49851
  {
49772
49852
  provide: NG_VALUE_ACCESSOR,
@@ -49782,7 +49862,8 @@ TnTinymceComponent.ctorParameters = () => [
49782
49862
  { type: Injector },
49783
49863
  { type: DeviceDetectorService },
49784
49864
  { type: NotifierService },
49785
- { type: FileExplorerService }
49865
+ { type: FileExplorerService },
49866
+ { type: FileObjectService }
49786
49867
  ];
49787
49868
  TnTinymceComponent.propDecorators = {
49788
49869
  equationForm: [{ type: ViewChild, args: [EquationEditorComponent,] }],