tnx-shared 5.3.424 → 5.3.426

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 (35) hide show
  1. package/bundles/tnx-shared.umd.js +1688 -411
  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/list-component-base.d.ts.map +1 -1
  6. package/classes/form-schema.d.ts +2 -0
  7. package/classes/form-schema.d.ts.map +1 -1
  8. package/components/entity-picker/entity-picker-dialog/components/entity-picker-data/entity-picker-data.component.d.ts.map +1 -1
  9. package/components/entity-picker/entity-picker-dialog/components/entity-picker-search-form/entity-picker-search-form.component.d.ts.map +1 -1
  10. package/components/entity-picker/entity-picker.component.d.ts +1 -0
  11. package/components/entity-picker/entity-picker.component.d.ts.map +1 -1
  12. package/components/file-upload/file-upload.component.d.ts +31 -9
  13. package/components/file-upload/file-upload.component.d.ts.map +1 -1
  14. package/components/service-file-upload/service-file-upload.component.d.ts +28 -4
  15. package/components/service-file-upload/service-file-upload.component.d.ts.map +1 -1
  16. package/components/user-picker/models/user-picker-setting.d.ts +2 -0
  17. package/components/user-picker/models/user-picker-setting.d.ts.map +1 -1
  18. package/components/user-picker/user-picker-box/user-picker-box.component.d.ts +4 -1
  19. package/components/user-picker/user-picker-box/user-picker-box.component.d.ts.map +1 -1
  20. package/esm2015/classes/base/list-component-base.js +3 -2
  21. package/esm2015/classes/form-schema.js +2 -1
  22. package/esm2015/components/crud/crud-form/crud-form.component.js +2 -2
  23. package/esm2015/components/entity-picker/entity-picker-dialog/components/entity-picker-data/entity-picker-data.component.js +5 -2
  24. package/esm2015/components/entity-picker/entity-picker-dialog/components/entity-picker-search-form/entity-picker-search-form.component.js +4 -3
  25. package/esm2015/components/entity-picker/entity-picker.component.js +9 -1
  26. package/esm2015/components/file-upload/file-upload.component.js +543 -7
  27. package/esm2015/components/service-file-upload/service-file-upload.component.js +599 -63
  28. package/esm2015/components/user-picker/models/user-picker-setting.js +6 -6
  29. package/esm2015/components/user-picker/user-picker-box/user-picker-box.component.js +11 -3
  30. package/esm2015/tnx-shared.module.js +2 -1
  31. package/fesm2015/tnx-shared.js +1169 -78
  32. package/fesm2015/tnx-shared.js.map +1 -1
  33. package/package.json +2 -2
  34. package/tnx-shared.metadata.json +1 -1
  35. package/tnx-shared.module.d.ts.map +1 -1
@@ -1156,6 +1156,7 @@ class EntityPickerControlSchema extends FormControlBaseWithService {
1156
1156
  this.titleUnPicked = 'Danh sách các mục chưa chọn';
1157
1157
  this.titlePicked = 'Danh sách các mục đã chọn';
1158
1158
  this.fieldsPicked = null;
1159
+ this.datasourceFieldFilter = [];
1159
1160
  for (const key in init) {
1160
1161
  this[key] = init[key];
1161
1162
  }
@@ -15047,7 +15048,7 @@ class CrudFormComponent extends ComponentBase {
15047
15048
  CrudFormComponent.decorators = [
15048
15049
  { type: Component, args: [{
15049
15050
  selector: 'crud-form',
15050
- template: "<div [class]=\"_styleClass\">\n <form #formElement autocomplete=\"off\" autocorrect=\"off\" spellcheck=\"false\"\n [class]=\"'p-grid form-group crud-form' + (formClass ? ' ' + formClass : '')\"\n (keydown.shift.tab)=\"preventBlur($event)\">\n <div class=\"p-grid p-col-12\" [class.grid]=\"useGridTemplate\" style=\"margin: 0\">\n <ng-container *ngFor=\"let control of setting.schema\">\n <ng-container *ngTemplateOutlet=\"customControl; context: {\n control: control, data: _modelData, parentPath: '', path: control.field, showLabel: control.showLabel,\n mdWidth: control.mdWidth, rowSpan: control.rowSpan\n }\">\n </ng-container>\n </ng-container>\n </div>\n </form>\n</div>\n<p-contextMenu #contextMenu [appendTo]=\"'body'\" [model]=\"buttonContexts\">\n</p-contextMenu>\n<ng-template #customControl let-data=\"data\" let-control=\"control\" let-showLabel=\"showLabel\" let-mdWidth=\"mdWidth\"\n let-rowSpan=\"rowSpan\" let-rowIndex=\"index\" let-path=\"path\" let-parentPath=\"parentPath\" let-tablePath=\"tablePath\">\n <div *ngIf=\"!checkHidden(control, data, path)\" id=\"{{path}}-holder\"\n class=\"p-col-{{control.gWidth}} p-md-{{mdWidth}} row-span-{{rowSpan}} {{control.class}} crud-form-control type-{{control.dataType}}\"\n [class.error]=\"data._errors[control.field].length > 0\"\n [class.not-show-in-box-holder]=\"control.showInBox === false\"\n [class.show-in-box-holder]=\"control.showInBox === true\" [ngStyle]=\"control.style\">\n <div class=\"label\" *ngIf=\"showLabel\">\n <label *ngIf=\"control.label && !control.isHtmlLabel\" [pTooltip]=\"control.fullLabel\"\n tooltipPosition=\"top\">{{control.label}}\n <span *ngIf=\"control.required || control.showIconRequired\" class=\"star-required\">*</span>\n </label>\n <ng-container *ngIf=\"control.label && control.isHtmlLabel\">\n <label [innerHTML]=\"control.label | safeHtml\" [pTooltip]=\"control.fullLabel\" tooltipPosition=\"top\">\n </label>\n <span *ngIf=\"control.required || control.showIconRequired\" class=\"star-required\">*</span>\n </ng-container>\n <span *ngIf=\"control.description\" class=\"control-description\">({{control.description}})</span>\n </div>\n <ng-container [ngSwitch]=\"control.controlType\">\n <ng-container *ngSwitchCase=\"'label'\">\n <ng-container [ngTemplateOutlet]=\"labelControl\"\n [ngTemplateOutletContext]=\"{control: control, data: data}\">\n </ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'title'\">\n <label *ngIf=\"!control.isHtml\" [for]=\"control.for\">{{control.text | translate}}</label>\n <label *ngIf=\"control.isHtml\" [innerHTML]=\"control.text | safeHtml\"></label>\n </ng-container>\n <ng-container *ngSwitchCase=\"'text'\">\n <div class=\"p-inputgroup\" *ngIf=\"control.suffFix\">\n <input [placeholder]=\"control.placeholder\" [tooltipDisabled]=\"control.dataFormat == 'password'\"\n [required]=\"control.validators && control.validators.required\" [pTooltip]=\"data[control.field]\"\n tooltipPosition=\"top\" tooltipStyleClass=\"wrap\"\n [attr.disabled]=\" checkDisabled(data, control) ? true : null\" pInputText\n [type]=\"control.dataFormat\" [max]=\"control.max\" [min]=\"control.min\"\n [maxlength]=\"control.maxLength\" [(ngModel)]=\"data[control.field]\"\n (change)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (key.enter)=\"handleFieldValueChange(control, $event, eventType.ENTER, data, parentPath)\" />\n <span class=\"p-inputgroup-addon\">({{control.suffFix}})</span>\n </div>\n <input *ngIf=\"!control.suffFix\" [placeholder]=\"control.placeholder\"\n [tooltipDisabled]=\"control.dataFormat == 'password'\" [pTooltip]=\"data[control.field]\"\n tooltipPosition=\"top\" tooltipStyleClass=\"wrap\"\n [attr.disabled]=\"checkDisabled(data, control) ? true : null\" pInputText [type]=\"control.dataFormat\"\n [max]=\"control.max\" [min]=\"control.min\" [maxlength]=\"control.maxLength\"\n [(ngModel)]=\"data[control.field]\"\n (change)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (key.enter)=\"handleFieldValueChange(control, $event, eventType.ENTER, data, parentPath)\" />\n </ng-container>\n <ng-container *ngSwitchCase=\"'htmlPreview'\">\n <html-preview [control]=\"control\" [(ngModel)]=\"data[control.field]\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </html-preview>\n </ng-container>\n <ng-container *ngSwitchCase=\"'reference-text'\">\n <reference-textbox [control]=\"control\" [value]=\"data[control.field]\" [dataSource]=\"control.dataSource\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"></reference-textbox>\n </ng-container>\n <ng-container *ngSwitchCase=\"'template'\">\n <ng-container [ngTemplateOutlet]=\"control.template\"\n [ngTemplateOutletContext]=\"{$implicit: _rootNode, control: control, data: data, tablePath: tablePath, parentPath: parentPath, rowIndex: rowIndex, funcUpdateModel: updateModelFromExternal}\">\n </ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'content'\">\n <div class=\"control-content label\">\n <span [innerHTML]=\"data[control.field] ? (data[control.field] | safeHtml) : ''\">\n </span>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'mask'\">\n <tn-mask [prefix]=\"control.prefix\" [decimalPlaces]=\"control.decimalPlaces\" [suffix]=\"control.suffix\"\n [placeholder]=\"control.placeholder\" [disabled]=\"checkDisabled(data, control)\" tooltipPosition=\"top\"\n [tooltipDisabled]=\"control.dataFormat == 'password'\" [pTooltip]=\"data[control.field]\"\n [maskType]=\"control.maskType\" [autoFormat]=\"control.autoFormat\" [min]=\"control.min\"\n [max]=\"control.max\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </tn-mask>\n </ng-container>\n <ng-container *ngSwitchCase=\"'numberrange'\">\n <tn-number-picker-range [decimalPlaces]=\"control.decimalPlaces\"\n [disabled]=\"checkDisabled(data, control)\" [maskType]=\"control.maskType\" [min]=\"control.min\"\n [max]=\"control.max\" [placeholder]=\"control.placeholder\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (change)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (blur)=\"handleFieldValueChange(control, $event, eventType.BLUR, data, parentPath)\">\n </tn-number-picker-range>\n </ng-container>\n <ng-container *ngSwitchCase=\"'money'\">\n <input currencyMask [attr.disabled]=\"checkDisabled(data, control) ? true : null\" pInputText type=\"tel\"\n tooltipPosition=\"top\" [pTooltip]=\"data[control.field] | number: '1.0-0'\"\n [options]=\"{prefix: '', thousands: '.', decimal: ',',precision:control.dataFormat === 'money'?0:0 }\"\n [(ngModel)]=\"data[control.field]\"\n (ngModelChange)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\" />\n </ng-container>\n <ng-container *ngSwitchCase=\"'phoneOrfax'\">\n <input [placeholder]=\"control.dataFormat==='phone'?'(999) 999-9999':'999-999-9999'\"\n [attr.disabled]=\"checkDisabled(data, control) ? true : null\" type=\"tel\" pInputText\n [(ngModel)]=\"data[control.field]\"\n (change)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\" />\n </ng-container>\n <ng-container *ngSwitchCase=\"'textarea'\">\n <textarea pInputTextarea [rows]=\"control.rows ? control.rows : 5\"\n [attr.disabled]=\"checkDisabled(data, control) ? true : null\" [(ngModel)]=\"data[control.field]\"\n [placeholder]=\"control.placeholder\"\n (keyup)=\"handleKeyUp(control, $event, eventType.CHANGE, data, parentPath)\"\n (change)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"></textarea>\n </ng-container>\n <ng-container *ngSwitchCase=\"'editor'\">\n <tn-tinymce *ngIf=\"!checkDisabled(data, control)\"\n [required]=\"control.validators && control.validators.required\" [mode]=\"control.mode\"\n [height]=\"control.height ? control.height : 250\" [languageCode]=\"control.languageCode\"\n [control]=\"control\"\n [disabled]=\"control.disabled || (control.disableCheck && control.disableCheck(model))\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onKeyUp)=\"handleKeyUp(control, $event, eventType.CHANGE, data, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </tn-tinymce>\n <div *ngIf=\"checkDisabled(data, control)\" class=\"html-box\"\n [innerHTML]=\"data[control.field] ? (data[control.field] | safeHtml) : ''\">\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'datetime'\">\n <datetime-picker [disabled]=\"checkDisabled(data, control)\" [control]=\"control\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </datetime-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'autocomplete'\">\n <app-autocomplete-datasource [control]=\"control\"\n [suggestions]=\"data._source[control.field] || control.dataSource\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onValueChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </app-autocomplete-datasource>\n </ng-container>\n <ng-container *ngSwitchCase=\"'datetimerange'\">\n <tn-datetime-picker-range [disabled]=\"control.disabled\" [control]=\"control\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </tn-datetime-picker-range>\n </ng-container>\n <ng-container *ngSwitchCase=\"'dropdown'\">\n <dropdown [control]=\"control\" [dataSource]=\"getControlDataSource(control, data)\" [data]=\"data\"\n [(value)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleChangeDropdown(control, $event, eventType.CHANGE, data, parentPath)\"\n (onHideSmartEvent)=\"handleChangeDropdown(control, $event, eventType.HIDE, data, parentPath)\"\n (adjustValue)=\"handleAdjustValueDropdownEvent(control, parentPath)\"\n (onDataSourceLoaded)=\"handleDataSourceLoaded(control, parentPath, $event)\"\n (onReady)=\"handleControlReadyEvent(control, parentPath)\">\n </dropdown>\n </ng-container>\n <ng-container *ngSwitchCase=\"'imageuploader'\">\n <app-image-uploader [loadByEntityKey]=\"control.loadByEntityKey\" [entityKey]=\"control.entityKey\"\n [defaultNoImageUrl]=\"'/assets/images/no-image.jpg'\" [multiple]=\"control.multiple\"\n [disabled]=\"control.disabled\" [isAvatar]=\"control.isAvatar\" [(ngModel)]=\"data[control.field]\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\">\n <ng-template *ngIf=\"control.templateItems\" #items let-files>\n <ng-container *ngTemplateOutlet=\"control.templateItems; context: {\n $implicit: files\n }\"></ng-container>\n </ng-template>\n <ng-template *ngIf=\"control.templateItem\" #item let-file>\n <ng-container *ngTemplateOutlet=\"control.templateItem; context: {\n $implicit: file\n }\"></ng-container>\n </ng-template>\n </app-image-uploader>\n </ng-container>\n <ng-container *ngSwitchCase=\"'fileManager'\">\n <file-manager *ngIf=\"control.entityKey || data[control.entityKeyField] || control.rootFolderId\"\n [control]=\"control\" [serviceCode]=\"control.serviceCode\" [entity]=\"control.entity\"\n [hiddenCreateFolder]=\"control.hiddenCreateFolder\"\n [entityKey]=\"control.entityKey ? control.entityKey : data[control.entityKeyField]\"\n [readonly]=\"control.disabled\" [layout]=\"control.layout\" [rootFolderId]=\"control.rootFolderId\"\n [maxFileSize]=\"control.maxFileSize\" [inTaiLieu]=\"control.inTaiLieu\"\n [inTaiLieuChung]=\"control.inTaiLieuChung\" [copyToFolderId]=\"control.copyToFolderId\"\n [filePickerSetting]=\"control.filePickerSetting\" [dataForm]=\"data\"\n [invalidFileSizeMessageSummary]=\"control.invalidFileSizeMessageSummary\"\n [invalidFileSizeMessageDetail]=\"control.invalidFileSizeMessageDetail\"\n [invalidFileTypeMessageSummary]=\"control.invalidFileTypeMessageSummary\"\n [invalidFileTypeMessageDetail]=\"control.invalidFileTypeMessageDetail\"\n [invalidFileLimitMessageSummary]=\"control.invalidFileLimitMessageSummary\"\n [invalidFileLimitMessageDetail]=\"control.invalidFileLimitMessageDetail\" [parentSetting]=\"setting\"\n [noFileMessage]=\"control.noFileMessage\" [(value)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onSelected)=\"control.onSelected($event)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleControlReadyEvent(control, parentPath)\">\n </file-manager>\n </ng-container>\n <span *ngSwitchCase=\"'fileUpload'\">\n <file-upload [sharedFolderType]=\"control.sharedFolderType\" [maxFileSize]=\"control.maxFileSize\"\n [invalidFileSizeMessageSummary]=\"control.invalidFileSizeMessageSummary\"\n [invalidFileSizeMessageDetail]=\"control.invalidFileSizeMessageDetail\"\n [invalidFileTypeMessageSummary]=\"control.invalidFileTypeMessageSummary\"\n [invalidFileTypeMessageDetail]=\"control.invalidFileTypeMessageDetail\"\n [invalidFileLimitMessageSummary]=\"control.invalidFileLimitMessageSummary\"\n [invalidFileLimitMessageDetail]=\"control.invalidFileLimitMessageDetail\" [control]=\"control\"\n [showDeleteFile]=\"control.showDeleteFile\" [readonly]=\"control.readonly\" [accept]=\"control.accept\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onRemove)=\"handleFieldValueChange(control, $event, eventType.DELETED, data, parentPath)\">\n </file-upload>\n </span>\n <span *ngSwitchCase=\"'serviceFileUpload'\">\n <service-file-upload *ngIf=\"control.entityKey || data[control.entityKeyField] || control.rootFolderId\"\n [parentContext]=\"context\" [serviceCode]=\"control.serviceCode\" [entity]=\"control.entity\"\n [entityKey]=\"control.entityKey ? control.entityKey : data[control.entityKeyField]\"\n [control]=\"control\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onRemove)=\"handleFieldValueChange(control, $event, eventType.DELETED, data, parentPath)\">\n </service-file-upload>\n </span>\n <ng-container *ngSwitchCase=\"'user-picker'\">\n <user-picker [control]=\"control\" [disabled]=\"checkDisabled(data, control)\"\n [readOnlyValues]=\"data[control.field + '_readOnly']\" [multiple]=\"control.multiple\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleReadyControlPicker(control, parentPath)\">\n </user-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'switch'\">\n <p-inputSwitch [disabled]=\"checkDisabled(data, control)\" [(ngModel)]=\"data[control.field]\"\n (onChange)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </p-inputSwitch>\n </ng-container>\n <ng-container *ngSwitchCase=\"'checkbox'\">\n <div [class]=\"control.class\" role=\"checkbox-alone\">\n <p-checkbox [disabled]=\"checkDisabled(data, control)\" [binary]=\"true\"\n [label]=\"control.isCustomLabel ? control.displayLabel : (!control.hiddenLabel ? control.label : null)\"\n [(ngModel)]=\"data[control.field]\"\n (onChange)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </p-checkbox>\n <!-- <tn-checkbox [control]=\"control\" [disabled]=\"checkDisabled(data, control)\"\n [(ngModel)]=\"data[control.field]\"\n (onChange)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"></tn-checkbox> -->\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'button'\">\n <button type=\"button\" pButton [class]=\"control.btClass\" [icon]=\"control.icon\" [disabled]=\"control.disabled\"\n [label]=\"control.buttonText | translate\" [ngStyle]=\"control.btStyle\" [pTooltip]=\"control.fullLabel\"\n tooltipPosition=\"top\" (click)=\"handleButtonClick(control, $event, parentPath)\"></button>\n </ng-container>\n <ng-container *ngSwitchCase=\"'container'\">\n <div class=\"p-grid p-col-12\" style=\"margin: 0\" [class.not-show-in-box]=\"!control.showInBox\"\n [class.show-in-box]=\"control.showInBox\" [ngStyle]=\"control.boxStyle\">\n <ng-container *ngFor=\"let subControl of control.controls\">\n <ng-container *ngTemplateOutlet=\"customControl; context: {\n control: subControl,\n data: data[control.field],\n parentPath: path,\n rowIndex: rowIndex,\n path: path + '.' + subControl.field,\n showLabel: subControl.showLabel,\n mdWidth: subControl.mdWidth,\n rowSpan: subControl.rowSpan\n }\">\n </ng-container>\n </ng-container>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'checkboxlist'\">\n <check-box-list [control]=\"control\" [dataSource]=\"data._source[control.field] || control.dataSource\"\n [disabled]=\"checkDisabled(data, control)\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onSelect)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleControlReadyEvent(control, parentPath)\">\n </check-box-list>\n </ng-container>\n <ng-container *ngSwitchCase=\"'radiobuttonlist'\">\n <radio-button-list [control]=\"control\" [dataSource]=\"control.dataSource\"\n [disabled]=\"checkDisabled(data, control)\" [(value)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (adjustValue)=\"handleAdjustValueDropdownEvent(control, parentPath)\"\n (onReady)=\"handleReadyControlPicker(control, parentPath)\"\n (onDataSourceLoaded)=\"handleDataSourceLoaded(control, parentPath, $event)\">\n </radio-button-list>\n </ng-container>\n <ng-container *ngSwitchCase=\"'colorPicker'\">\n <tn-color-picker [disabled]=\"checkDisabled(data, control)\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (change)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </tn-color-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'spanControl'\">\n <span *ngIf=\"!control.ishtml\">{{data[control.field]}}</span>\n <span *ngIf=\"control.ishtml\" [innerHTML]=\"data[control.field]\"></span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'colorControl'\">\n <span class=\"show-color-control\" [ngStyle]=\"{ backgroundColor: data[control.sourceField]}\"></span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'address-new'\">\n <address-picker-new [control]=\"control\" [showSubLabel]=\"control.showSubLabel\"\n [disabled]=\"checkDisabled(data, control)\" [(data)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onSelect)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleControlReadyEvent(control, parentPath)\">\n </address-picker-new>\n </ng-container>\n <ng-container *ngSwitchCase=\"'address'\">\n <address-picker [control]=\"control\" [showSubLabel]=\"control.showSubLabel\"\n [disabled]=\"checkDisabled(data, control)\" [(data)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onSelect)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleControlReadyEvent(control, parentPath)\">\n </address-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'autocomplete-picker'\">\n <autocomplete-picker [control]=\"control\" [disabled]=\"checkDisabled(data, control)\"\n [required]=\"control.required\" [readOnlyValues]=\"data[control.field + '_readOnly']\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleReadyControlPicker(control, parentPath)\">\n </autocomplete-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'cocautochuc'\">\n <cocautochuc-picker [control]=\"control\" [parentOrgId]=\"control.parentOrgId\"\n [disabled]=\"checkDisabled(data, control)\" [parentOrgCode]=\"control.parentOrgCode\"\n [filter]=\"control.filter\" [multiple]=\"control.multiple\" [required]=\"control.required\"\n [isUsingId]=\"control.isUsingId\" [disabledParentItem]=\"control.disabledParentItem\"\n [rootParentId]=\"control.rootParentId\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </cocautochuc-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'cocautochuc-picker'\">\n <cocautochuc-picker-list [control]=\"control\" [disabled]=\"checkDisabled(data, control)\"\n [required]=\"control.required\" [readOnlyValues]=\"data[control.field + '_readOnly']\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleReadyControlPicker(control, parentPath)\">\n </cocautochuc-picker-list>\n </ng-container>\n <ng-container *ngSwitchCase=\"'cocautochuc-picker-new'\">\n <cocautochuc-picker-list-new [control]=\"control\" [disabled]=\"checkDisabled(data, control)\"\n [required]=\"control.required\" [readOnlyValues]=\"data[control.field + '_readOnly']\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleReadyControlPicker(control, parentPath)\">\n </cocautochuc-picker-list-new>\n </ng-container>\n <ng-container *ngSwitchCase=\"'vanban'\">\n <vanban-picker [control]=\"control\" [disabled]=\"checkDisabled(data, control)\"\n [required]=\"control.required\" [readOnly]=\"control.readOnly\" [loaiVanBan]=\"control.loaiVanBan\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </vanban-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'congviec'\">\n <div>\n <congviec-picker [control]=\"control\" [disabled]=\"checkDisabled(data, control)\"\n [required]=\"control.required\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </congviec-picker>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'percent'\">\n <div>\n <tn-mask [suffix]=\"'%'\" [placeholder]=\"control.placeholder\" [maskType]=\"'int'\"\n [autoFormat]=\"control.autoFormat\" [min]=\"0\" [max]=\"100\"\n [disabled]=\"checkDisabled(data, control)\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </tn-mask>\n <p-slider [step]=\"1\" [min]=\"0\" [max]=\"100\" [disabled]=\"checkDisabled(data, control)\"\n [(ngModel)]=\"data[control.field]\"\n (onSlideEnd)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </p-slider>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'chips'\">\n <p-chips [disabled]=\"checkDisabled(data, control)\" [(ngModel)]=\"data[control.field]\"\n [placeholder]=\"control.placeholder\"\n (onAdd)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onRemove)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"></p-chips>\n </ng-container>\n <ng-container *ngSwitchCase=\"'entity-picker'\">\n <entity-picker [control]=\"control\" [children]=\"children\" [disabled]=\"checkDisabled(data, control)\"\n [required]=\"control.required\" [readOnly]=\"control.readOnly\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </entity-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'table'\">\n <div [class]=\"control.class\">\n <tn-custom-scrollbar class=\"--has-border\" [showScrollHorizontal]=\"true\">\n <p-table class=\"new-table scr-table table-control\" [value]=\"data[control.field]\"\n [columns]=\"control.headerTemplate\" [responsive]=\"true\" [scrollable]=\"false\"\n [rowTrackBy]=\"trackByFuncId\"\n (onRowReorder)=\"handleRowOrdered(control, $event, eventType.ROW_REORDER, data, parentPath)\">\n <ng-template pTemplate=\"colgroup\">\n <colgroup>\n <col *ngIf=\"control.showNumber\" style=\"width: 40px\" />\n <ng-container *ngFor=\"let subControl of control.rowTemplate\">\n <col *ngIf=\"subControl && !subControl.hidden && subControl.visibleInList\"\n [style.width]=\"subControl.width\" />\n </ng-container>\n <col *ngIf=\"control.enableReorderRow\" style=\"width: 30px\" />\n <col *ngIf=\"control.showFunction\" [style.width]=\"control.widthFunctionColumn\" />\n </colgroup>\n </ng-template>\n <ng-template *ngIf=\"getComponentByType(_prefixCustomHeader + control.field)\"\n pTemplate=\"header\" let-columns>\n <ng-container\n *ngTemplateOutlet=\"getComponentByType(_prefixCustomHeader + control.field), context: {$implicit: control.headerTemplate, crudForm: this, containerSticky: containerSticky}\">\n </ng-container>\n </ng-template>\n <ng-template *ngIf=\"!getComponentByType(_prefixCustomHeader + control.field)\"\n pTemplate=\"header\" let-rowData let-columns>\n <tr>\n <th *ngIf=\"control.showNumber\" class=\"th-sticky stt\">\n {{ 'TT' |translate}}\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </th>\n <ng-container *ngFor=\"let subControl of control.rowTemplate\">\n <th *ngIf=\"subControl && !subControl.hidden && subControl.visibleInList\"\n [width]=\"subControl.width\"\n [pTooltip]=\"subControl.fullLabel || subControl.label\" tooltipPosition=\"top\"\n style=\"text-align: center;\">\n {{subControl.label}}\n <span *ngIf=\"subControl.required\" class=\"star-required\">*</span>\n <span *ngIf=\"subControl.description\"\n class=\"subControl-description\">({{subControl.description}})</span>\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </th>\n </ng-container>\n <th *ngIf=\"control.enableReorderRow\">\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </th>\n <th *ngIf=\"control.showFunction\" class=\"table-function column-function\">\n <div class=\"cell-header-function\"><span>{{'Ch\u1EE9c n\u0103ng'|translate}}</span></div>\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-rowData let-ri=\"rowIndex\">\n <tr [pReorderableRow]=\"ri\" [class]=\"rowData.class\"\n (click)=\"handleRowClick(rowData, control)\">\n <td *ngIf=\"control.showNumber\" class=\"stt th-sticky\"\n style=\"text-align: center; vertical-align: inherit\">\n <span>\n {{ri + 1}}\n </span>\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </td>\n <ng-container *ngFor=\"let subControl of control.rowTemplate; let i = index\">\n <td *ngIf=\"subControl && !subControl.hidden && subControl.visibleInList\"\n [class.control-inside]=\"true\" [class]=\"subControl.class\"\n [ngStyle]=\"{'text-align': getTextAlign(subControl.textAlign), 'vertical-align': 'inherit'}\">\n <span class=\"p-column-title\">{{subControl.label}}</span>\n <ng-template [ngIf]=\"getControlType(subControl) != 'column'\">\n <ng-container *ngTemplateOutlet=\"customControl; context: {\n control: subControl,\n data: rowData,\n index: ri,\n tablePath: path,\n parentPath: path + '[' + ri + ']',\n path: path + '[' + ri + '].' + subControl.field,\n showLabel: false,\n mdWidth: 12,\n rowSpan: 1\n }\">\n </ng-container>\n </ng-template>\n <ng-template [ngIf]=\"getControlType(subControl) == 'column'\">\n <span>{{_modelData[control.field][ri][subControl.field]}}</span>\n </ng-template>\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </td>\n </ng-container>\n <td *ngIf=\"control.enableReorderRow\" class=\"no-padding center v-center\">\n <i class=\"fas fa-arrows-alt\" style=\"cursor:pointer; padding: 8px; color: #555;\"\n pReorderableRowHandle></i>\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </td>\n <td *ngIf=\"control.showFunction\" style=\"text-align: center\"\n class=\"column-function text-center\">\n <div *ngIf=\"!control.rowButtonTemplate\"\n class=\"p-toolbar-group-center button-group\">\n <button *ngIf=\"control.showSave\" [disabled]=\"rowData._disableSave\"\n type=\"button\" pButton class=\"p-button-text p-button-rounded\"\n icon=\"pi pi-save\" [pTooltip]=\"'L\u01B0u' | translate\" tooltipPosition=\"top\"\n (click)=\"saveRow(ri, control, path)\"></button>\n <button *ngIf=\"control.showEdit\" [disabled]=\"rowData._disableEdit\"\n type=\"button\" pButton class=\"p-button-text p-button-rounded\"\n icon=\"pi pi-pencil\" [pTooltip]=\"'S\u1EEDa' | translate\" tooltipPosition=\"top\"\n (click)=\"editRow(ri, control, path)\"></button>\n <button *ngIf=\"control.showDelete\" [disabled]=\"rowData._disableDelete\"\n type=\"button\" pButton\n class=\"p-button-text p-button-danger p-button-rounded\"\n icon=\"pi pi-trash\" [pTooltip]=\"'X\u00F3a' | translate\" tooltipPosition=\"top\"\n (click)=\"deleteRow(ri, control, path)\"></button>\n <button *ngIf=\"control.rowButtons\" type=\"button\" pButton\n icon=\"pi pi-ellipsis-v\"\n class=\"link-or-action p-button-text p-button-rounded\"\n pTooltip=\"Ch\u1EE9c n\u0103ng kh\u00E1c\" tooltipPosition=\"top\"\n (click)=\"showContextMenu($event, rowData, control)\"></button>\n </div>\n <div *ngIf=\"control.rowButtonTemplate\"\n class=\"p-toolbar-group-center button-group\">\n <ng-container\n *ngTemplateOutlet=\"control.rowButtonTemplate; context: {rowData: _modelData[control.field][ri], rowIndex: ri, path: path, control: control}\">\n </ng-container>\n </div>\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </td>\n </tr>\n </ng-template>\n <ng-template *ngIf=\"control.summaryTemplate\" pTemplate=\"summary\" let-rowData>\n <ng-container *ngTemplateOutlet=\"control.summaryTemplate; context: {rowData: rowData}\">\n </ng-container>\n </ng-template>\n </p-table>\n </tn-custom-scrollbar>\n <div *ngIf=\"control.showFooter\" class=\"--table-schema-footer\">\n <button *ngIf=\"control.showAdd\" type=\"button\" pButton style=\"width:auto\" label=\"Th\u00EAm m\u1EDBi\"\n icon=\"pi pi-plus\" class=\"p-button-text\" (click)=\"addNewRow(control, path)\"></button>\n <span *ngIf=\"control.showDialog\" style=\"font-weight: normal;\">\n <p-checkbox label=\"M\u1EDF dialog\" [binary]=\"true\" [(ngModel)]=\"control.showEdit\">\n </p-checkbox>\n </span>\n <button *ngIf=\"control.enableAddMulti\" type=\"button\" pButton\n style=\"width:auto; margin-left:10px;\" label=\"Th\u00EAm nhi\u1EC1u\" icon=\"pi pi-clone\"\n class=\"p-button-text\" (click)=\"addMultiRow(control, 5, path)\"></button>\n <button *ngFor=\"let bt of control.footerButtons\" type=\"button\" pButton [class]=\"bt.class\"\n [icon]=\"bt.icon\" [label]=\"bt.label | translate\" style=\"width:auto; margin-left:10px;\"\n (click)=\"messageRow( -1, control, path)\"></button>\n </div>\n </div>\n </ng-container>\n <ng-container *ngSwitchDefault>\n <ng-container *ngIf=\"control.template\">\n <ng-container [ngTemplateOutlet]=\"control.template\" [ngTemplateOutletContext]=\"{\n crudForm: this, data: data, index: rowIndex, parentPath: parentPath, control: control, changeFunc: handleFieldValueChange\n }\">\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"!control.template\" [ngTemplateOutlet]=\"getComponentByType(control.field)\"\n [ngTemplateOutletContext]=\"{\n crudForm: this, data: data, index: rowIndex, parentPath: parentPath, control: control, changeFunc: handleFieldValueChange\n }\">\n </ng-container>\n </ng-container>\n <ng-container *ngTemplateOutlet=\"validation; context: {control: control, data: data}\">\n </ng-container>\n <div *ngIf=\"control.message\" class=\"control-message\">\n <span [class]=\"control.messageClass\">{{control.message}}</span>\n </div>\n </ng-container>\n </div>\n</ng-template>\n<ng-template #validation let-control=\"control\" let-data=\"data\">\n <ng-container *ngIf=\"data._errors[control.field].length > 0\">\n <div class=\"error-container\">\n <ng-container *ngFor=\"let error of data._errors[control.field]\">\n <div class=\"error-item\" *ngIf=\"error\">\n <ng-container [ngTemplateOutlet]=\"errorMessage\" [ngTemplateOutletContext]=\"{content: error}\">\n </ng-container>\n </div>\n </ng-container>\n </div>\n </ng-container>\n</ng-template>\n<ng-template #errorMessage let-content=\"content\">\n <div class=\"error-content\">\n <i class=\"pi pi-ban\"></i>\n <span> {{content}}</span>\n </div>\n</ng-template>\n<ng-template #labelControl let-control=\"control\">\n <ng-container>\n <label [class]=\"getLabelClass(control)\" *ngIf=\"!control.isHtml\" [attr.label-index]=\"control.indexLabel\"\n [pTooltip]=\"control.title\" tooltipPosition=\"top\" tooltipStyleClass=\"wrap\" [escape]=\"false\"\n [for]=\"control.for\">{{control.text | translate}}</label>\n <label [class]=\"getLabelClass(control)\" *ngIf=\"control.isHtml\" [innerHTML]=\"control.text | safeHtml\"\n [attr.label-index]=\"control.indexLabel\"></label>\n </ng-container>\n</ng-template>\n<ng-template #containerSticky>\n <span class=\"fix-sticky top\"></span>\n <span class=\"fix-sticky right\"></span>\n <span class=\"fix-sticky left\"></span>\n</ng-template>\n<!-- <ng-template #templateCongViecForm let-control=\"control\">\n <base-congviec-form [control]=\"control\" [parentSetting]=\"congViecSetting\" [tenCongViec]=\"control.data.tenCongViec\">\n </base-congviec-form>\n</ng-template> -->\n<tn-dialog *ngIf=\"tableFormDialogModel.showEditForm\" #dialog [styleClass]=\"'address-form'\"\n [header]=\"tableFormDialogModel.header | translate\" [popupSize]=\"tableFormDialogModel.popupSize\"\n (onHide)=\"tableFormDialogModel.showEditForm = false\">\n <table-detail-form #formBase [parentSetting]=\"setting\" [schema]=\"tableFormSchema\" [data]=\"tableFormDialogModel.data\"\n (onSaved)=\"handleSavedTableRow($event)\" (onCancel)=\"tableFormDialogModel.showEditForm = false\">\n </table-detail-form>\n</tn-dialog>",
15051
+ template: "<div [class]=\"_styleClass\">\n <form #formElement autocomplete=\"off\" autocorrect=\"off\" spellcheck=\"false\"\n [class]=\"'p-grid form-group crud-form' + (formClass ? ' ' + formClass : '')\"\n (keydown.shift.tab)=\"preventBlur($event)\">\n <div class=\"p-grid p-col-12\" [class.grid]=\"useGridTemplate\" style=\"margin: 0\">\n <ng-container *ngFor=\"let control of setting.schema\">\n <ng-container *ngTemplateOutlet=\"customControl; context: {\n control: control, data: _modelData, parentPath: '', path: control.field, showLabel: control.showLabel,\n mdWidth: control.mdWidth, rowSpan: control.rowSpan\n }\">\n </ng-container>\n </ng-container>\n </div>\n </form>\n</div>\n<p-contextMenu #contextMenu [appendTo]=\"'body'\" [model]=\"buttonContexts\">\n</p-contextMenu>\n<ng-template #customControl let-data=\"data\" let-control=\"control\" let-showLabel=\"showLabel\" let-mdWidth=\"mdWidth\"\n let-rowSpan=\"rowSpan\" let-rowIndex=\"index\" let-path=\"path\" let-parentPath=\"parentPath\" let-tablePath=\"tablePath\">\n <div *ngIf=\"!checkHidden(control, data, path)\" id=\"{{path}}-holder\"\n class=\"p-col-{{control.gWidth}} p-md-{{mdWidth}} row-span-{{rowSpan}} {{control.class}} crud-form-control type-{{control.dataType}}\"\n [class.error]=\"data._errors[control.field].length > 0\"\n [class.not-show-in-box-holder]=\"control.showInBox === false\"\n [class.show-in-box-holder]=\"control.showInBox === true\" [ngStyle]=\"control.style\">\n <div class=\"label\" *ngIf=\"showLabel\">\n <label *ngIf=\"control.label && !control.isHtmlLabel\" [pTooltip]=\"control.fullLabel\"\n tooltipPosition=\"top\">{{control.label}}\n <span *ngIf=\"control.required || control.showIconRequired\" class=\"star-required\">*</span>\n </label>\n <ng-container *ngIf=\"control.label && control.isHtmlLabel\">\n <label [innerHTML]=\"control.label | safeHtml\" [pTooltip]=\"control.fullLabel\" tooltipPosition=\"top\">\n </label>\n <span *ngIf=\"control.required || control.showIconRequired\" class=\"star-required\">*</span>\n </ng-container>\n <span *ngIf=\"control.description\" class=\"control-description\">({{control.description}})</span>\n </div>\n <ng-container [ngSwitch]=\"control.controlType\">\n <ng-container *ngSwitchCase=\"'label'\">\n <ng-container [ngTemplateOutlet]=\"labelControl\"\n [ngTemplateOutletContext]=\"{control: control, data: data}\">\n </ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'title'\">\n <label *ngIf=\"!control.isHtml\" [for]=\"control.for\">{{control.text | translate}}</label>\n <label *ngIf=\"control.isHtml\" [innerHTML]=\"control.text | safeHtml\"></label>\n </ng-container>\n <ng-container *ngSwitchCase=\"'text'\">\n <div class=\"p-inputgroup\" *ngIf=\"control.suffFix\">\n <input [placeholder]=\"control.placeholder\" [tooltipDisabled]=\"control.dataFormat == 'password'\"\n [required]=\"control.validators && control.validators.required\" [pTooltip]=\"data[control.field]\"\n tooltipPosition=\"top\" tooltipStyleClass=\"wrap\"\n [attr.disabled]=\" checkDisabled(data, control) ? true : null\" pInputText\n [type]=\"control.dataFormat\" [max]=\"control.max\" [min]=\"control.min\"\n [maxlength]=\"control.maxLength\" [(ngModel)]=\"data[control.field]\"\n (change)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (key.enter)=\"handleFieldValueChange(control, $event, eventType.ENTER, data, parentPath)\" />\n <span class=\"p-inputgroup-addon\">({{control.suffFix}})</span>\n </div>\n <input *ngIf=\"!control.suffFix\" [placeholder]=\"control.placeholder\"\n [tooltipDisabled]=\"control.dataFormat == 'password'\" [pTooltip]=\"data[control.field]\"\n tooltipPosition=\"top\" tooltipStyleClass=\"wrap\"\n [attr.disabled]=\"checkDisabled(data, control) ? true : null\" pInputText [type]=\"control.dataFormat\"\n [max]=\"control.max\" [min]=\"control.min\" [maxlength]=\"control.maxLength\"\n [(ngModel)]=\"data[control.field]\"\n (change)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (key.enter)=\"handleFieldValueChange(control, $event, eventType.ENTER, data, parentPath)\" />\n </ng-container>\n <ng-container *ngSwitchCase=\"'htmlPreview'\">\n <html-preview [control]=\"control\" [(ngModel)]=\"data[control.field]\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </html-preview>\n </ng-container>\n <ng-container *ngSwitchCase=\"'reference-text'\">\n <reference-textbox [control]=\"control\" [value]=\"data[control.field]\" [dataSource]=\"control.dataSource\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"></reference-textbox>\n </ng-container>\n <ng-container *ngSwitchCase=\"'template'\">\n <ng-container [ngTemplateOutlet]=\"control.template\"\n [ngTemplateOutletContext]=\"{$implicit: _rootNode, control: control, data: data, tablePath: tablePath, parentPath: parentPath, rowIndex: rowIndex, funcUpdateModel: updateModelFromExternal}\">\n </ng-container>\n </ng-container>\n <ng-container *ngSwitchCase=\"'content'\">\n <div class=\"control-content label\">\n <span [innerHTML]=\"data[control.field] ? (data[control.field] | safeHtml) : ''\">\n </span>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'mask'\">\n <tn-mask [prefix]=\"control.prefix\" [decimalPlaces]=\"control.decimalPlaces\" [suffix]=\"control.suffix\"\n [placeholder]=\"control.placeholder\" [disabled]=\"checkDisabled(data, control)\" tooltipPosition=\"top\"\n [tooltipDisabled]=\"control.dataFormat == 'password'\" [pTooltip]=\"data[control.field]\"\n [maskType]=\"control.maskType\" [autoFormat]=\"control.autoFormat\" [min]=\"control.min\"\n [max]=\"control.max\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </tn-mask>\n </ng-container>\n <ng-container *ngSwitchCase=\"'numberrange'\">\n <tn-number-picker-range [decimalPlaces]=\"control.decimalPlaces\"\n [disabled]=\"checkDisabled(data, control)\" [maskType]=\"control.maskType\" [min]=\"control.min\"\n [max]=\"control.max\" [placeholder]=\"control.placeholder\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (change)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (blur)=\"handleFieldValueChange(control, $event, eventType.BLUR, data, parentPath)\">\n </tn-number-picker-range>\n </ng-container>\n <ng-container *ngSwitchCase=\"'money'\">\n <input currencyMask [attr.disabled]=\"checkDisabled(data, control) ? true : null\" pInputText type=\"tel\"\n tooltipPosition=\"top\" [pTooltip]=\"data[control.field] | number: '1.0-0'\"\n [options]=\"{prefix: '', thousands: '.', decimal: ',',precision:control.dataFormat === 'money'?0:0 }\"\n [(ngModel)]=\"data[control.field]\"\n (ngModelChange)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\" />\n </ng-container>\n <ng-container *ngSwitchCase=\"'phoneOrfax'\">\n <input [placeholder]=\"control.dataFormat==='phone'?'(999) 999-9999':'999-999-9999'\"\n [attr.disabled]=\"checkDisabled(data, control) ? true : null\" type=\"tel\" pInputText\n [(ngModel)]=\"data[control.field]\"\n (change)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\" />\n </ng-container>\n <ng-container *ngSwitchCase=\"'textarea'\">\n <textarea pInputTextarea [rows]=\"control.rows ? control.rows : 5\"\n [attr.disabled]=\"checkDisabled(data, control) ? true : null\" [(ngModel)]=\"data[control.field]\"\n [placeholder]=\"control.placeholder\"\n (keyup)=\"handleKeyUp(control, $event, eventType.CHANGE, data, parentPath)\"\n (change)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"></textarea>\n </ng-container>\n <ng-container *ngSwitchCase=\"'editor'\">\n <tn-tinymce *ngIf=\"!checkDisabled(data, control)\"\n [required]=\"control.validators && control.validators.required\" [mode]=\"control.mode\"\n [height]=\"control.height ? control.height : 250\" [languageCode]=\"control.languageCode\"\n [control]=\"control\"\n [disabled]=\"control.disabled || (control.disableCheck && control.disableCheck(model))\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onKeyUp)=\"handleKeyUp(control, $event, eventType.CHANGE, data, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </tn-tinymce>\n <div *ngIf=\"checkDisabled(data, control)\" class=\"html-box\"\n [innerHTML]=\"data[control.field] ? (data[control.field] | safeHtml) : ''\">\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'datetime'\">\n <datetime-picker [disabled]=\"checkDisabled(data, control)\" [control]=\"control\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </datetime-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'autocomplete'\">\n <app-autocomplete-datasource [control]=\"control\"\n [suggestions]=\"data._source[control.field] || control.dataSource\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onValueChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </app-autocomplete-datasource>\n </ng-container>\n <ng-container *ngSwitchCase=\"'datetimerange'\">\n <tn-datetime-picker-range [disabled]=\"control.disabled\" [control]=\"control\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </tn-datetime-picker-range>\n </ng-container>\n <ng-container *ngSwitchCase=\"'dropdown'\">\n <dropdown [control]=\"control\" [dataSource]=\"getControlDataSource(control, data)\" [data]=\"data\"\n [(value)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleChangeDropdown(control, $event, eventType.CHANGE, data, parentPath)\"\n (onHideSmartEvent)=\"handleChangeDropdown(control, $event, eventType.HIDE, data, parentPath)\"\n (adjustValue)=\"handleAdjustValueDropdownEvent(control, parentPath)\"\n (onDataSourceLoaded)=\"handleDataSourceLoaded(control, parentPath, $event)\"\n (onReady)=\"handleControlReadyEvent(control, parentPath)\">\n </dropdown>\n </ng-container>\n <ng-container *ngSwitchCase=\"'imageuploader'\">\n <app-image-uploader [loadByEntityKey]=\"control.loadByEntityKey\" [entityKey]=\"control.entityKey\"\n [defaultNoImageUrl]=\"'/assets/images/no-image.jpg'\" [multiple]=\"control.multiple\"\n [disabled]=\"control.disabled\" [isAvatar]=\"control.isAvatar\" [(ngModel)]=\"data[control.field]\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\">\n <ng-template *ngIf=\"control.templateItems\" #items let-files>\n <ng-container *ngTemplateOutlet=\"control.templateItems; context: {\n $implicit: files\n }\"></ng-container>\n </ng-template>\n <ng-template *ngIf=\"control.templateItem\" #item let-file>\n <ng-container *ngTemplateOutlet=\"control.templateItem; context: {\n $implicit: file\n }\"></ng-container>\n </ng-template>\n </app-image-uploader>\n </ng-container>\n <ng-container *ngSwitchCase=\"'fileManager'\">\n <file-manager *ngIf=\"control.entityKey || data[control.entityKeyField] || control.rootFolderId\"\n [control]=\"control\" [serviceCode]=\"control.serviceCode\" [entity]=\"control.entity\"\n [hiddenCreateFolder]=\"control.hiddenCreateFolder\"\n [entityKey]=\"control.entityKey ? control.entityKey : data[control.entityKeyField]\"\n [readonly]=\"control.disabled\" [layout]=\"control.layout\" [rootFolderId]=\"control.rootFolderId\"\n [maxFileSize]=\"control.maxFileSize\" [inTaiLieu]=\"control.inTaiLieu\"\n [inTaiLieuChung]=\"control.inTaiLieuChung\" [copyToFolderId]=\"control.copyToFolderId\"\n [filePickerSetting]=\"control.filePickerSetting\" [dataForm]=\"data\"\n [invalidFileSizeMessageSummary]=\"control.invalidFileSizeMessageSummary\"\n [invalidFileSizeMessageDetail]=\"control.invalidFileSizeMessageDetail\"\n [invalidFileTypeMessageSummary]=\"control.invalidFileTypeMessageSummary\"\n [invalidFileTypeMessageDetail]=\"control.invalidFileTypeMessageDetail\"\n [invalidFileLimitMessageSummary]=\"control.invalidFileLimitMessageSummary\"\n [invalidFileLimitMessageDetail]=\"control.invalidFileLimitMessageDetail\" [parentSetting]=\"setting\"\n [noFileMessage]=\"control.noFileMessage\" [(value)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onSelected)=\"control.onSelected($event)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleControlReadyEvent(control, parentPath)\">\n </file-manager>\n </ng-container>\n <span *ngSwitchCase=\"'fileUpload'\">\n <file-upload [sharedFolderType]=\"control.sharedFolderType\" [maxFileSize]=\"control.maxFileSize\"\n [invalidFileSizeMessageSummary]=\"control.invalidFileSizeMessageSummary\"\n [invalidFileSizeMessageDetail]=\"control.invalidFileSizeMessageDetail\"\n [invalidFileTypeMessageSummary]=\"control.invalidFileTypeMessageSummary\"\n [invalidFileTypeMessageDetail]=\"control.invalidFileTypeMessageDetail\"\n [invalidFileLimitMessageSummary]=\"control.invalidFileLimitMessageSummary\"\n [invalidFileLimitMessageDetail]=\"control.invalidFileLimitMessageDetail\" [control]=\"control\"\n [showDeleteFile]=\"control.showDeleteFile\" [readonly]=\"control.readonly\" [accept]=\"control.accept\"\n [parentSetting]=\"setting\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onRemove)=\"handleFieldValueChange(control, $event, eventType.DELETED, data, parentPath)\">\n </file-upload>\n </span>\n <span *ngSwitchCase=\"'serviceFileUpload'\">\n <service-file-upload *ngIf=\"control.entityKey || data[control.entityKeyField] || control.rootFolderId\"\n [parentContext]=\"context\" [serviceCode]=\"control.serviceCode\" [entity]=\"control.entity\"\n [entityKey]=\"control.entityKey ? control.entityKey : data[control.entityKeyField]\"\n [control]=\"control\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n [parentSetting]=\"setting\"\n (onRemove)=\"handleFieldValueChange(control, $event, eventType.DELETED, data, parentPath)\">\n </service-file-upload>\n </span>\n <ng-container *ngSwitchCase=\"'user-picker'\">\n <user-picker [control]=\"control\" [disabled]=\"checkDisabled(data, control)\"\n [readOnlyValues]=\"data[control.field + '_readOnly']\" [multiple]=\"control.multiple\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleReadyControlPicker(control, parentPath)\">\n </user-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'switch'\">\n <p-inputSwitch [disabled]=\"checkDisabled(data, control)\" [(ngModel)]=\"data[control.field]\"\n (onChange)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </p-inputSwitch>\n </ng-container>\n <ng-container *ngSwitchCase=\"'checkbox'\">\n <div [class]=\"control.class\" role=\"checkbox-alone\">\n <p-checkbox [disabled]=\"checkDisabled(data, control)\" [binary]=\"true\"\n [label]=\"control.isCustomLabel ? control.displayLabel : (!control.hiddenLabel ? control.label : null)\"\n [(ngModel)]=\"data[control.field]\"\n (onChange)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </p-checkbox>\n <!-- <tn-checkbox [control]=\"control\" [disabled]=\"checkDisabled(data, control)\"\n [(ngModel)]=\"data[control.field]\"\n (onChange)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"></tn-checkbox> -->\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'button'\">\n <button type=\"button\" pButton [class]=\"control.btClass\" [icon]=\"control.icon\"\n [disabled]=\"control.disabled\" [label]=\"control.buttonText | translate\" [ngStyle]=\"control.btStyle\"\n [pTooltip]=\"control.fullLabel\" tooltipPosition=\"top\"\n (click)=\"handleButtonClick(control, $event, parentPath)\"></button>\n </ng-container>\n <ng-container *ngSwitchCase=\"'container'\">\n <div class=\"p-grid p-col-12\" style=\"margin: 0\" [class.not-show-in-box]=\"!control.showInBox\"\n [class.show-in-box]=\"control.showInBox\" [ngStyle]=\"control.boxStyle\">\n <ng-container *ngFor=\"let subControl of control.controls\">\n <ng-container *ngTemplateOutlet=\"customControl; context: {\n control: subControl,\n data: data[control.field],\n parentPath: path,\n rowIndex: rowIndex,\n path: path + '.' + subControl.field,\n showLabel: subControl.showLabel,\n mdWidth: subControl.mdWidth,\n rowSpan: subControl.rowSpan\n }\">\n </ng-container>\n </ng-container>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'checkboxlist'\">\n <check-box-list [control]=\"control\" [dataSource]=\"data._source[control.field] || control.dataSource\"\n [disabled]=\"checkDisabled(data, control)\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onSelect)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleControlReadyEvent(control, parentPath)\">\n </check-box-list>\n </ng-container>\n <ng-container *ngSwitchCase=\"'radiobuttonlist'\">\n <radio-button-list [control]=\"control\" [dataSource]=\"control.dataSource\"\n [disabled]=\"checkDisabled(data, control)\" [(value)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (adjustValue)=\"handleAdjustValueDropdownEvent(control, parentPath)\"\n (onReady)=\"handleReadyControlPicker(control, parentPath)\"\n (onDataSourceLoaded)=\"handleDataSourceLoaded(control, parentPath, $event)\">\n </radio-button-list>\n </ng-container>\n <ng-container *ngSwitchCase=\"'colorPicker'\">\n <tn-color-picker [disabled]=\"checkDisabled(data, control)\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (change)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </tn-color-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'spanControl'\">\n <span *ngIf=\"!control.ishtml\">{{data[control.field]}}</span>\n <span *ngIf=\"control.ishtml\" [innerHTML]=\"data[control.field]\"></span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'colorControl'\">\n <span class=\"show-color-control\" [ngStyle]=\"{ backgroundColor: data[control.sourceField]}\"></span>\n </ng-container>\n <ng-container *ngSwitchCase=\"'address-new'\">\n <address-picker-new [control]=\"control\" [showSubLabel]=\"control.showSubLabel\"\n [disabled]=\"checkDisabled(data, control)\" [(data)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onSelect)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleControlReadyEvent(control, parentPath)\">\n </address-picker-new>\n </ng-container>\n <ng-container *ngSwitchCase=\"'address'\">\n <address-picker [control]=\"control\" [showSubLabel]=\"control.showSubLabel\"\n [disabled]=\"checkDisabled(data, control)\" [(data)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onSelect)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleControlReadyEvent(control, parentPath)\">\n </address-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'autocomplete-picker'\">\n <autocomplete-picker [control]=\"control\" [disabled]=\"checkDisabled(data, control)\"\n [required]=\"control.required\" [readOnlyValues]=\"data[control.field + '_readOnly']\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleReadyControlPicker(control, parentPath)\">\n </autocomplete-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'cocautochuc'\">\n <cocautochuc-picker [control]=\"control\" [parentOrgId]=\"control.parentOrgId\"\n [disabled]=\"checkDisabled(data, control)\" [parentOrgCode]=\"control.parentOrgCode\"\n [filter]=\"control.filter\" [multiple]=\"control.multiple\" [required]=\"control.required\"\n [isUsingId]=\"control.isUsingId\" [disabledParentItem]=\"control.disabledParentItem\"\n [rootParentId]=\"control.rootParentId\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </cocautochuc-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'cocautochuc-picker'\">\n <cocautochuc-picker-list [control]=\"control\" [disabled]=\"checkDisabled(data, control)\"\n [required]=\"control.required\" [readOnlyValues]=\"data[control.field + '_readOnly']\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleReadyControlPicker(control, parentPath)\">\n </cocautochuc-picker-list>\n </ng-container>\n <ng-container *ngSwitchCase=\"'cocautochuc-picker-new'\">\n <cocautochuc-picker-list-new [control]=\"control\" [disabled]=\"checkDisabled(data, control)\"\n [required]=\"control.required\" [readOnlyValues]=\"data[control.field + '_readOnly']\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onReady)=\"handleReadyControlPicker(control, parentPath)\">\n </cocautochuc-picker-list-new>\n </ng-container>\n <ng-container *ngSwitchCase=\"'vanban'\">\n <vanban-picker [control]=\"control\" [disabled]=\"checkDisabled(data, control)\"\n [required]=\"control.required\" [readOnly]=\"control.readOnly\" [loaiVanBan]=\"control.loaiVanBan\"\n [(ngModel)]=\"data[control.field]\" (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </vanban-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'congviec'\">\n <div>\n <congviec-picker [control]=\"control\" [disabled]=\"checkDisabled(data, control)\"\n [required]=\"control.required\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </congviec-picker>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'percent'\">\n <div>\n <tn-mask [suffix]=\"'%'\" [placeholder]=\"control.placeholder\" [maskType]=\"'int'\"\n [autoFormat]=\"control.autoFormat\" [min]=\"0\" [max]=\"100\"\n [disabled]=\"checkDisabled(data, control)\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </tn-mask>\n <p-slider [step]=\"1\" [min]=\"0\" [max]=\"100\" [disabled]=\"checkDisabled(data, control)\"\n [(ngModel)]=\"data[control.field]\"\n (onSlideEnd)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </p-slider>\n </div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'chips'\">\n <p-chips [disabled]=\"checkDisabled(data, control)\" [(ngModel)]=\"data[control.field]\"\n [placeholder]=\"control.placeholder\"\n (onAdd)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"\n (onRemove)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\"></p-chips>\n </ng-container>\n <ng-container *ngSwitchCase=\"'entity-picker'\">\n <entity-picker [control]=\"control\" [children]=\"children\" [disabled]=\"checkDisabled(data, control)\"\n [required]=\"control.required\" [readOnly]=\"control.readOnly\" [(ngModel)]=\"data[control.field]\"\n (onInit)=\"handleLoadedControl($event, control, parentPath)\"\n (onChanged)=\"handleFieldValueChange(control, $event, eventType.CHANGE, data, parentPath)\">\n </entity-picker>\n </ng-container>\n <ng-container *ngSwitchCase=\"'table'\">\n <div [class]=\"control.class\">\n <tn-custom-scrollbar class=\"--has-border\" [showScrollHorizontal]=\"true\">\n <p-table class=\"new-table scr-table table-control\" [value]=\"data[control.field]\"\n [columns]=\"control.headerTemplate\" [responsive]=\"true\" [scrollable]=\"false\"\n [rowTrackBy]=\"trackByFuncId\"\n (onRowReorder)=\"handleRowOrdered(control, $event, eventType.ROW_REORDER, data, parentPath)\">\n <ng-template pTemplate=\"colgroup\">\n <colgroup>\n <col *ngIf=\"control.showNumber\" style=\"width: 40px\" />\n <ng-container *ngFor=\"let subControl of control.rowTemplate\">\n <col *ngIf=\"subControl && !subControl.hidden && subControl.visibleInList\"\n [style.width]=\"subControl.width\" />\n </ng-container>\n <col *ngIf=\"control.enableReorderRow\" style=\"width: 30px\" />\n <col *ngIf=\"control.showFunction\" [style.width]=\"control.widthFunctionColumn\" />\n </colgroup>\n </ng-template>\n <ng-template *ngIf=\"getComponentByType(_prefixCustomHeader + control.field)\"\n pTemplate=\"header\" let-columns>\n <ng-container\n *ngTemplateOutlet=\"getComponentByType(_prefixCustomHeader + control.field), context: {$implicit: control.headerTemplate, crudForm: this, containerSticky: containerSticky}\">\n </ng-container>\n </ng-template>\n <ng-template *ngIf=\"!getComponentByType(_prefixCustomHeader + control.field)\"\n pTemplate=\"header\" let-rowData let-columns>\n <tr>\n <th *ngIf=\"control.showNumber\" class=\"th-sticky stt\">\n {{ 'TT' |translate}}\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </th>\n <ng-container *ngFor=\"let subControl of control.rowTemplate\">\n <th *ngIf=\"subControl && !subControl.hidden && subControl.visibleInList\"\n [width]=\"subControl.width\"\n [pTooltip]=\"subControl.fullLabel || subControl.label\" tooltipPosition=\"top\"\n style=\"text-align: center;\">\n {{subControl.label}}\n <span *ngIf=\"subControl.required\" class=\"star-required\">*</span>\n <span *ngIf=\"subControl.description\"\n class=\"subControl-description\">({{subControl.description}})</span>\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </th>\n </ng-container>\n <th *ngIf=\"control.enableReorderRow\">\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </th>\n <th *ngIf=\"control.showFunction\" class=\"table-function column-function\">\n <div class=\"cell-header-function\"><span>{{'Ch\u1EE9c n\u0103ng'|translate}}</span></div>\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-rowData let-ri=\"rowIndex\">\n <tr [pReorderableRow]=\"ri\" [class]=\"rowData.class\"\n (click)=\"handleRowClick(rowData, control)\">\n <td *ngIf=\"control.showNumber\" class=\"stt th-sticky\"\n style=\"text-align: center; vertical-align: inherit\">\n <span>\n {{ri + 1}}\n </span>\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </td>\n <ng-container *ngFor=\"let subControl of control.rowTemplate; let i = index\">\n <td *ngIf=\"subControl && !subControl.hidden && subControl.visibleInList\"\n [class.control-inside]=\"true\" [class]=\"subControl.class\"\n [ngStyle]=\"{'text-align': getTextAlign(subControl.textAlign), 'vertical-align': 'inherit'}\">\n <span class=\"p-column-title\">{{subControl.label}}</span>\n <ng-template [ngIf]=\"getControlType(subControl) != 'column'\">\n <ng-container *ngTemplateOutlet=\"customControl; context: {\n control: subControl,\n data: rowData,\n index: ri,\n tablePath: path,\n parentPath: path + '[' + ri + ']',\n path: path + '[' + ri + '].' + subControl.field,\n showLabel: false,\n mdWidth: 12,\n rowSpan: 1\n }\">\n </ng-container>\n </ng-template>\n <ng-template [ngIf]=\"getControlType(subControl) == 'column'\">\n <span>{{_modelData[control.field][ri][subControl.field]}}</span>\n </ng-template>\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </td>\n </ng-container>\n <td *ngIf=\"control.enableReorderRow\" class=\"no-padding center v-center\">\n <i class=\"fas fa-arrows-alt\" style=\"cursor:pointer; padding: 8px; color: #555;\"\n pReorderableRowHandle></i>\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </td>\n <td *ngIf=\"control.showFunction\" style=\"text-align: center\"\n class=\"column-function text-center\">\n <div *ngIf=\"!control.rowButtonTemplate\"\n class=\"p-toolbar-group-center button-group\">\n <button *ngIf=\"control.showSave\" [disabled]=\"rowData._disableSave\"\n type=\"button\" pButton class=\"p-button-text p-button-rounded\"\n icon=\"pi pi-save\" [pTooltip]=\"'L\u01B0u' | translate\" tooltipPosition=\"top\"\n (click)=\"saveRow(ri, control, path)\"></button>\n <button *ngIf=\"control.showEdit\" [disabled]=\"rowData._disableEdit\"\n type=\"button\" pButton class=\"p-button-text p-button-rounded\"\n icon=\"pi pi-pencil\" [pTooltip]=\"'S\u1EEDa' | translate\" tooltipPosition=\"top\"\n (click)=\"editRow(ri, control, path)\"></button>\n <button *ngIf=\"control.showDelete\" [disabled]=\"rowData._disableDelete\"\n type=\"button\" pButton\n class=\"p-button-text p-button-danger p-button-rounded\"\n icon=\"pi pi-trash\" [pTooltip]=\"'X\u00F3a' | translate\" tooltipPosition=\"top\"\n (click)=\"deleteRow(ri, control, path)\"></button>\n <button *ngIf=\"control.rowButtons\" type=\"button\" pButton\n icon=\"pi pi-ellipsis-v\"\n class=\"link-or-action p-button-text p-button-rounded\"\n pTooltip=\"Ch\u1EE9c n\u0103ng kh\u00E1c\" tooltipPosition=\"top\"\n (click)=\"showContextMenu($event, rowData, control)\"></button>\n </div>\n <div *ngIf=\"control.rowButtonTemplate\"\n class=\"p-toolbar-group-center button-group\">\n <ng-container\n *ngTemplateOutlet=\"control.rowButtonTemplate; context: {rowData: _modelData[control.field][ri], rowIndex: ri, path: path, control: control}\">\n </ng-container>\n </div>\n <ng-container *ngTemplateOutlet=\"containerSticky\"></ng-container>\n </td>\n </tr>\n </ng-template>\n <ng-template *ngIf=\"control.summaryTemplate\" pTemplate=\"summary\" let-rowData>\n <ng-container *ngTemplateOutlet=\"control.summaryTemplate; context: {rowData: rowData}\">\n </ng-container>\n </ng-template>\n </p-table>\n </tn-custom-scrollbar>\n <div *ngIf=\"control.showFooter\" class=\"--table-schema-footer\">\n <button *ngIf=\"control.showAdd\" type=\"button\" pButton style=\"width:auto\" label=\"Th\u00EAm m\u1EDBi\"\n icon=\"pi pi-plus\" class=\"p-button-text\" (click)=\"addNewRow(control, path)\"></button>\n <span *ngIf=\"control.showDialog\" style=\"font-weight: normal;\">\n <p-checkbox label=\"M\u1EDF dialog\" [binary]=\"true\" [(ngModel)]=\"control.showEdit\">\n </p-checkbox>\n </span>\n <button *ngIf=\"control.enableAddMulti\" type=\"button\" pButton\n style=\"width:auto; margin-left:10px;\" label=\"Th\u00EAm nhi\u1EC1u\" icon=\"pi pi-clone\"\n class=\"p-button-text\" (click)=\"addMultiRow(control, 5, path)\"></button>\n <button *ngFor=\"let bt of control.footerButtons\" type=\"button\" pButton [class]=\"bt.class\"\n [icon]=\"bt.icon\" [label]=\"bt.label | translate\" style=\"width:auto; margin-left:10px;\"\n (click)=\"messageRow( -1, control, path)\"></button>\n </div>\n </div>\n </ng-container>\n <ng-container *ngSwitchDefault>\n <ng-container *ngIf=\"control.template\">\n <ng-container [ngTemplateOutlet]=\"control.template\" [ngTemplateOutletContext]=\"{\n crudForm: this, data: data, index: rowIndex, parentPath: parentPath, control: control, changeFunc: handleFieldValueChange\n }\">\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"!control.template\" [ngTemplateOutlet]=\"getComponentByType(control.field)\"\n [ngTemplateOutletContext]=\"{\n crudForm: this, data: data, index: rowIndex, parentPath: parentPath, control: control, changeFunc: handleFieldValueChange\n }\">\n </ng-container>\n </ng-container>\n <ng-container *ngTemplateOutlet=\"validation; context: {control: control, data: data}\">\n </ng-container>\n <div *ngIf=\"control.message\" class=\"control-message\">\n <span [class]=\"control.messageClass\">{{control.message}}</span>\n </div>\n </ng-container>\n </div>\n</ng-template>\n<ng-template #validation let-control=\"control\" let-data=\"data\">\n <ng-container *ngIf=\"data._errors[control.field].length > 0\">\n <div class=\"error-container\">\n <ng-container *ngFor=\"let error of data._errors[control.field]\">\n <div class=\"error-item\" *ngIf=\"error\">\n <ng-container [ngTemplateOutlet]=\"errorMessage\" [ngTemplateOutletContext]=\"{content: error}\">\n </ng-container>\n </div>\n </ng-container>\n </div>\n </ng-container>\n</ng-template>\n<ng-template #errorMessage let-content=\"content\">\n <div class=\"error-content\">\n <i class=\"pi pi-ban\"></i>\n <span> {{content}}</span>\n </div>\n</ng-template>\n<ng-template #labelControl let-control=\"control\">\n <ng-container>\n <label [class]=\"getLabelClass(control)\" *ngIf=\"!control.isHtml\" [attr.label-index]=\"control.indexLabel\"\n [pTooltip]=\"control.title\" tooltipPosition=\"top\" tooltipStyleClass=\"wrap\" [escape]=\"false\"\n [for]=\"control.for\">{{control.text | translate}}</label>\n <label [class]=\"getLabelClass(control)\" *ngIf=\"control.isHtml\" [innerHTML]=\"control.text | safeHtml\"\n [attr.label-index]=\"control.indexLabel\"></label>\n </ng-container>\n</ng-template>\n<ng-template #containerSticky>\n <span class=\"fix-sticky top\"></span>\n <span class=\"fix-sticky right\"></span>\n <span class=\"fix-sticky left\"></span>\n</ng-template>\n<!-- <ng-template #templateCongViecForm let-control=\"control\">\n <base-congviec-form [control]=\"control\" [parentSetting]=\"congViecSetting\" [tenCongViec]=\"control.data.tenCongViec\">\n </base-congviec-form>\n</ng-template> -->\n<tn-dialog *ngIf=\"tableFormDialogModel.showEditForm\" #dialog [styleClass]=\"'address-form'\"\n [header]=\"tableFormDialogModel.header | translate\" [popupSize]=\"tableFormDialogModel.popupSize\"\n (onHide)=\"tableFormDialogModel.showEditForm = false\">\n <table-detail-form #formBase [parentSetting]=\"setting\" [schema]=\"tableFormSchema\" [data]=\"tableFormDialogModel.data\"\n (onSaved)=\"handleSavedTableRow($event)\" (onCancel)=\"tableFormDialogModel.showEditForm = false\">\n </table-detail-form>\n</tn-dialog>",
15051
15052
  providers: [ComponentContextService],
15052
15053
  styles: [".label-only{font-weight:700;margin-bottom:1em}div.label{position:relative}div.label .star-required{color:red;position:absolute;padding-left:.2em;padding-top:.1em}th>span.star-required{color:red;padding-left:.2em;padding-top:.3em}div.type-container.not-show-in-box-holder{padding:0}.--table-schema-footer{display:flex;align-items:center;font-weight:600;padding:.5em;background:#f8f9fa;color:#495057;border:1px solid #e9ecef}.show-in-box{border:1px solid #ced4da;border-radius:5px}.not-show-in-box{padding:0}.view-mode div.label{padding-bottom:3px}.view-mode div.label label{font-weight:700;font-size:.85em}.view-mode>span:not(:empty){display:inline-block;width:100%;padding:5px 0}.view-mode.type-table div.label+div{padding:5px 0}td>.view-mode{display:inline-block;padding:.25rem .5rem}td>.view-mode .view-mode{padding:0}.crud-form-control div[role=checkbox-alone]{margin-top:24px}.crud-form-control div[role=checkbox-alone].mg-top-0{margin-top:0}.crud-form-control .label+div[role=checkbox-alone]{margin-top:11px}.crud-form-control.type-table div[role=checkbox-alone]{margin-top:6px;text-align:center}.crud-form-control.type-table div[role=checkbox-alone].mg-top-0{margin-top:0}.crud-form-control.type-table div[role=checkbox-alone].align-left{text-align:left}.crud-form-control.type-title{font-size:1.2rem;font-weight:700;color:#025ba7;border-bottom:1px solid #cfcfcf;text-transform:uppercase;padding:5px;margin-bottom:5px}.crud-form-control.type-title>.label{margin-bottom:0}.control-description,.crud-form-control .subControl-description{font-size:.8rem;font-weight:700;color:#007eff;margin-bottom:5px}.control-description{padding-left:.75rem}.th-sticky{text-align:center!important;z-index:2!important;position:sticky!important;top:0;background:inherit}.th-sticky.stt{left:0}.cell-header-function{display:flex;align-items:center}.cell-header-function>span{text-align:center;flex:1 1}.cell-header-function button{width:24px;height:24px;padding:0;margin:0}.no-value{font-size:.8em}@keyframes fadeIn{0%{opacity:0;top:-25px}to{opacity:1;top:0}}@keyframes shrink{0%{height:0}to{height:20px}}@media screen and (min-width:40.063em){.label-right{padding-left:2em}}::ng-deep crud-form .crud-form-control .tn-check-box-list{margin-top:5px}::ng-deep crud-form .crud-form-control>div.label{margin-bottom:5px;font-size:.9rem;height:1.15em}::ng-deep crud-form .crud-form-control>div.label+*{width:100%}::ng-deep crud-form .crud-form-control>.error-container .error-item{overflow:visible;animation:shrink .1s;min-height:20px;padding-top:5px}::ng-deep crud-form .crud-form-control>.error-container .error-item .error-content{display:flex;position:relative;color:red;font-size:.9em;animation:fadeIn .1s}::ng-deep crud-form .crud-form-control>.error-container .error-item .error-content i{font-size:.9em;display:flex;padding-top:1px}::ng-deep crud-form .crud-form-control>.error-container .error-item .error-content span{display:flex;padding-left:5px}::ng-deep crud-form .crud-form-control .control-message{margin-top:5px;font-size:.9rem}::ng-deep crud-form .crud-form-control .control-message .green{color:#00af00}::ng-deep crud-form .crud-form-control .control-message .red{color:red}::ng-deep crud-form .crud-form-control .control-message .blue{color:#0095ff}::ng-deep crud-form .crud-form-control.no-label>div.label{display:none}::ng-deep crud-form .crud-form-control.error .p-dropdown,::ng-deep crud-form .crud-form-control.error .p-inputtext,::ng-deep crud-form .crud-form-control.error .p-multiselect,::ng-deep crud-form .crud-form-control.error .tn-dropdown,::ng-deep crud-form .crud-form-control.error input,::ng-deep crud-form .crud-form-control.error select,::ng-deep crud-form .crud-form-control.error textarea{border-color:#ff5722!important}::ng-deep crud-form .crud-form-control.error .p-autocomplete-multiple-container:not(.p-disabled).p-focus,::ng-deep crud-form .crud-form-control.error .p-inputtext:enabled:focus,::ng-deep crud-form .crud-form-control.error .tn-dropdown:not(.p-disabled).p-focus{box-shadow:0 0 0 .2rem #ffc4b3}::ng-deep crud-form .crud-form-control.error div.crud-form-control:not(.error) .p-dropdown,::ng-deep crud-form .crud-form-control.error div.crud-form-control:not(.error) .p-inputtext,::ng-deep crud-form .crud-form-control.error div.crud-form-control:not(.error) .p-multiselect,::ng-deep crud-form .crud-form-control.error div.crud-form-control:not(.error) .tn-dropdown,::ng-deep crud-form .crud-form-control.error div.crud-form-control:not(.error) input,::ng-deep crud-form .crud-form-control.error div.crud-form-control:not(.error) select,::ng-deep crud-form .crud-form-control.error div.crud-form-control:not(.error) textarea{border-color:#ced4da!important}::ng-deep crud-form .crud-form-control.error div.crud-form-control:not(.error) .p-autocomplete-multiple-container:not(.p-disabled).p-focus,::ng-deep crud-form .crud-form-control.error div.crud-form-control:not(.error) .p-dropdown.tn-dropdown.p-focus,::ng-deep crud-form .crud-form-control.error div.crud-form-control:not(.error) .p-inputtext:enabled:focus{box-shadow:0 0 0 .2rem #a6d5fa}::ng-deep crud-form .crud-form-container{padding:.5rem .5rem 0}::ng-deep crud-form .p-datatable .p-datatable-tbody tr td.control-inside,::ng-deep crud-form .p-datatable .p-datatable-tbody tr td.control-inside .show-in-box:not(.crud-form-control),::ng-deep crud-form base-congviec-form crud-form>.crud-form-container{padding:0}@media screen and (min-width:768px){::ng-deep crud-form .grid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr))}::ng-deep crud-form .grid .p-md-1{width:unset;grid-column:span 1}::ng-deep crud-form .grid .p-md-2{width:unset;grid-column:span 2}::ng-deep crud-form .grid .p-md-3{width:unset;grid-column:span 3}::ng-deep crud-form .grid .p-md-4{width:unset;grid-column:span 4}::ng-deep crud-form .grid .p-md-5{width:unset;grid-column:span 5}::ng-deep crud-form .grid .p-md-6{width:unset;grid-column:span 6}::ng-deep crud-form .grid .p-md-7{width:unset;grid-column:span 7}::ng-deep crud-form .grid .p-md-8{width:unset;grid-column:span 8}::ng-deep crud-form .grid .p-md-9{width:unset;grid-column:span 9}::ng-deep crud-form .grid .p-md-10{width:unset;grid-column:span 10}::ng-deep crud-form .grid .p-md-11{width:unset;grid-column:span 11}::ng-deep crud-form .grid .p-md-12{width:unset;grid-column:span 12}::ng-deep crud-form .grid .row-span-1{grid-row:span 1}::ng-deep crud-form .grid .row-span-2{grid-row:span 2}::ng-deep crud-form .grid .row-span-3{grid-row:span 3}::ng-deep crud-form .grid .row-span-4{grid-row:span 4}::ng-deep crud-form .grid .row-span-5{grid-row:span 5}::ng-deep crud-form .grid .row-span-6{grid-row:span 6}::ng-deep crud-form .grid .row-span-7{grid-row:span 7}::ng-deep crud-form .grid .row-span-8{grid-row:span 8}::ng-deep crud-form .grid .row-span-9{grid-row:span 9}::ng-deep crud-form .grid .row-span-10{grid-row:span 10}::ng-deep crud-form .grid .row-span-11{grid-row:span 11}::ng-deep crud-form .grid .row-span-12{grid-row:span 12}::ng-deep crud-form .grid .row-span-13{grid-row:span 13}::ng-deep crud-form .grid .row-span-14{grid-row:span 14}::ng-deep crud-form .grid .row-span-15{grid-row:span 15}::ng-deep crud-form .grid .row-span-16{grid-row:span 16}::ng-deep crud-form .grid .row-span-17{grid-row:span 17}::ng-deep crud-form .grid .row-span-18{grid-row:span 18}::ng-deep crud-form .grid .row-span-19{grid-row:span 19}::ng-deep crud-form .grid .row-span-20{grid-row:span 20}::ng-deep crud-form .grid .row-span-21{grid-row:span 21}::ng-deep crud-form .grid .row-span-22{grid-row:span 22}::ng-deep crud-form .grid .row-span-23{grid-row:span 23}::ng-deep crud-form .grid .row-span-24{grid-row:span 24}::ng-deep crud-form .grid .row-span-25{grid-row:span 25}::ng-deep crud-form .grid .row-span-26{grid-row:span 26}::ng-deep crud-form .grid .row-span-27{grid-row:span 27}::ng-deep crud-form .grid .row-span-28{grid-row:span 28}::ng-deep crud-form .grid .row-span-29{grid-row:span 29}::ng-deep crud-form .grid .row-span-30{grid-row:span 30}::ng-deep crud-form .grid .row-span-31{grid-row:span 31}::ng-deep crud-form .grid .row-span-32{grid-row:span 32}::ng-deep crud-form .grid .row-span-33{grid-row:span 33}::ng-deep crud-form .grid .row-span-34{grid-row:span 34}::ng-deep crud-form .grid .row-span-35{grid-row:span 35}::ng-deep crud-form .grid .row-span-36{grid-row:span 36}::ng-deep crud-form .grid .row-span-37{grid-row:span 37}::ng-deep crud-form .grid .row-span-38{grid-row:span 38}::ng-deep crud-form .grid .row-span-39{grid-row:span 39}::ng-deep crud-form .grid .row-span-40{grid-row:span 40}::ng-deep crud-form .grid .row-span-41{grid-row:span 41}::ng-deep crud-form .grid .row-span-42{grid-row:span 42}::ng-deep crud-form .grid .row-span-43{grid-row:span 43}::ng-deep crud-form .grid .row-span-44{grid-row:span 44}::ng-deep crud-form .grid .row-span-45{grid-row:span 45}::ng-deep crud-form .grid .row-span-46{grid-row:span 46}::ng-deep crud-form .grid .row-span-47{grid-row:span 47}::ng-deep crud-form .grid .row-span-48{grid-row:span 48}::ng-deep crud-form .grid .row-span-49{grid-row:span 49}::ng-deep crud-form .grid .row-span-50{grid-row:span 50}}:host ::ng-deep .tox-tinymce{border:none;border-top:1px solid #ccc;overflow:unset}:host ::ng-deep .tox-tinymce .tox-editor-container{overflow:unset}:host ::ng-deep .tox-tinymce .tox-toolbar{border:1px solid #ccc;border-bottom:none}:host ::ng-deep .tox-tinymce .tox-edit-area{border:1px solid #ccc}:host ::ng-deep .tox-tinymce .tox-edit-area iframe{box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}:host ::ng-deep .tox-tinymce .tox-menubar{border:1px solid #ccc}:host ::ng-deep .tox .tox-edit-area.tinymce-focus{border:1px solid #66afe9;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 3px 0 #66afe9;transition:box-shadow .3s,border-color .3s;transition-property:box-shadow,border-color;transition-duration:.3s,.3s;transition-timing-function:ease,ease;transition-delay:0s,0s}:host ::ng-deep .rq .tox .tox-edit-area{border-left-color:#ff4c46}:host ::ng-deep .table-schema-paging{margin-bottom:40px;display:block}"]
15053
15054
  },] }
@@ -22184,7 +22185,8 @@ class ListComponentBase extends ComponentBase {
22184
22185
  if (itemWorkflowHistoryLast
22185
22186
  && itemWorkflowHistoryLast.actionCode != MaActionBatDauQuyTrinh
22186
22187
  && itemWorkflowHistoryLast.userIdCreated.toUpperCase() == userIdStringUpper
22187
- && this.setting.showButtonThuHoi) {
22188
+ && this.setting.showButtonThuHoi
22189
+ && !rowData.hiddenButtonThuHoi) {
22188
22190
  buttonContexts.push({
22189
22191
  icon: 'pi pi-replay',
22190
22192
  label: 'Thu hồi',
@@ -28289,13 +28291,15 @@ FileExplorerNewService.ctorParameters = () => [
28289
28291
  ];
28290
28292
 
28291
28293
  class FileUploadComponent extends ComponentBase {
28292
- constructor(_fileObjectService, _notifierService, _downloadLinkService, _moduleConfigService, _fileExplorerService, _injector) {
28294
+ constructor(_fileObjectService, _notifierService, _downloadLinkService, _moduleConfigService, _fileExplorerService, _deviceDetectorService, _userService, _injector) {
28293
28295
  super(_injector);
28294
28296
  this._fileObjectService = _fileObjectService;
28295
28297
  this._notifierService = _notifierService;
28296
28298
  this._downloadLinkService = _downloadLinkService;
28297
28299
  this._moduleConfigService = _moduleConfigService;
28298
28300
  this._fileExplorerService = _fileExplorerService;
28301
+ this._deviceDetectorService = _deviceDetectorService;
28302
+ this._userService = _userService;
28299
28303
  this.chooseLabel = 'Chọn';
28300
28304
  this.readonly = true;
28301
28305
  this.showDeleteFile = true;
@@ -28309,6 +28313,7 @@ class FileUploadComponent extends ComponentBase {
28309
28313
  this.invalidFileLimitMessageDetail = 'tối đa {0} file.';
28310
28314
  this.sharedFolderType = SharedFolderType.Tempt;
28311
28315
  this.control = new FileUploadControlSchema();
28316
+ this.parentSetting = new CrudFormSetting();
28312
28317
  this.onInit = new EventEmitter();
28313
28318
  this.onSelect = new EventEmitter();
28314
28319
  this.onRemove = new EventEmitter();
@@ -28329,7 +28334,27 @@ class FileUploadComponent extends ComponentBase {
28329
28334
  show: false,
28330
28335
  }
28331
28336
  };
28337
+ this.formIds = {
28338
+ createFolder: 'createFolder',
28339
+ renameFile: 'renameFile',
28340
+ shareFile: 'shareFile',
28341
+ shareFolder: 'shareFolder',
28342
+ fileViewer: 'fileViewer',
28343
+ fileVersionList: 'fileVersionList',
28344
+ signatureDetail: 'signatureDetail',
28345
+ kySoSim: 'kySoSim',
28346
+ viewDetail: 'viewDetail'
28347
+ };
28348
+ this.signatureFormModel = {
28349
+ formData: new CrudFormData(),
28350
+ show: false,
28351
+ popupSize: new PopupSize({
28352
+ width: 600,
28353
+ height: 400
28354
+ })
28355
+ };
28332
28356
  this.environment = this._moduleConfigService.getConfig().environment;
28357
+ this._moduleConfig = _moduleConfigService.getConfig();
28333
28358
  }
28334
28359
  writeValue(obj) {
28335
28360
  this.fileId = obj;
@@ -28348,6 +28373,10 @@ class FileUploadComponent extends ComponentBase {
28348
28373
  if (this.control.isPublic != null && this.control.isPublic != undefined) {
28349
28374
  this.isPublic = this.control.isPublic;
28350
28375
  }
28376
+ this.forms[this.formIds.signatureDetail] = {
28377
+ header: 'Thông tin chữ ký số',
28378
+ show: false,
28379
+ };
28351
28380
  this.onInit.emit(this);
28352
28381
  }
28353
28382
  getFile() {
@@ -28358,6 +28387,13 @@ class FileUploadComponent extends ComponentBase {
28358
28387
  const fileObject = (yield this._fileObjectService.getDetail(this.fileId)).data;
28359
28388
  if (fileObject) {
28360
28389
  this.selectedFileName = fileObject.name;
28390
+ this.selectedFile = fileObject;
28391
+ this._fileExplorerService.getSignatureInfoByFileId(this.fileId).then(rs => {
28392
+ var _a;
28393
+ if (rs.success && ((_a = rs.data) === null || _a === void 0 ? void 0 : _a.length)) {
28394
+ this.selectedFile.signatures = rs.data;
28395
+ }
28396
+ });
28361
28397
  this.hasFile = true;
28362
28398
  this.loading = false;
28363
28399
  this.notification = null;
@@ -28371,11 +28407,76 @@ class FileUploadComponent extends ComponentBase {
28371
28407
  });
28372
28408
  }
28373
28409
  setMenu() {
28374
- this.menu = [{
28410
+ this.menu = [
28411
+ {
28375
28412
  label: 'Tải về', icon: 'fas fa-download', command: () => {
28376
28413
  this.onDownloadFile();
28377
28414
  }
28378
- }];
28415
+ },
28416
+ {
28417
+ label: 'Ký số cá nhân (SIM)',
28418
+ icon: 'fas fa-sim-card',
28419
+ command: () => {
28420
+ this.signKySimFile(this.selectedFile);
28421
+ },
28422
+ visible: (this._fileObjectService.isTypeFileKySo(this.selectedFile.name)
28423
+ && !this.parentSetting.hiddenKySoSimCaNhan),
28424
+ },
28425
+ {
28426
+ label: 'Ký số SmartCA',
28427
+ icon: 'fas fa-signature',
28428
+ command: () => {
28429
+ this.signatureFormModel.show = true;
28430
+ },
28431
+ visible: (this._fileObjectService.isTypeFileKySo(this.selectedFile.name)
28432
+ && !this.parentSetting.hiddenKySoSmartCA),
28433
+ },
28434
+ {
28435
+ label: 'Ký số cá nhân (USB)', icon: 'fas fa-signature',
28436
+ command: () => {
28437
+ this.signFile(this.selectedFile);
28438
+ },
28439
+ visible: (this._fileObjectService.isTypeFileKySo(this.selectedFile.name)
28440
+ && this._deviceDetectorService.isDesktop()
28441
+ && !this.parentSetting.hiddenKySoUsbCaNhan),
28442
+ },
28443
+ {
28444
+ label: 'Ký số VNPTCA', icon: 'fas fa-signature',
28445
+ command: () => {
28446
+ this.signVNPTCA(this.selectedFile);
28447
+ },
28448
+ visible: (this._fileObjectService.isTypeFileKySo(this.selectedFile.name)
28449
+ && this._deviceDetectorService.isDesktop()
28450
+ && !this.parentSetting.hiddenKySoVNPTCA),
28451
+ },
28452
+ {
28453
+ label: 'Bút phê', icon: 'fas fa-comment-dots',
28454
+ command: () => {
28455
+ this.addComment(this.selectedFile);
28456
+ },
28457
+ visible: (this._fileObjectService.isTypeFileKySo(this.selectedFile.name)
28458
+ && this._deviceDetectorService.isDesktop()
28459
+ && !this.parentSetting.hiddenButPhe),
28460
+ },
28461
+ {
28462
+ label: 'Bút phê và ký', icon: 'fas fa-comment-medical',
28463
+ command: () => {
28464
+ this.addCommentAndSign(this.selectedFile);
28465
+ },
28466
+ visible: (this._fileObjectService.isTypeFileKySo(this.selectedFile.name)
28467
+ && this._deviceDetectorService.isDesktop()
28468
+ && !this.parentSetting.hiddenButPhe),
28469
+ },
28470
+ {
28471
+ label: 'Ký số đơn vị (USB)', icon: 'fas fa-signature',
28472
+ command: () => {
28473
+ this.signFileDonVi(this.selectedFile);
28474
+ },
28475
+ visible: (this._fileObjectService.isTypeFileKySo(this.selectedFile.name)
28476
+ && this._deviceDetectorService.isDesktop()
28477
+ && !this.parentSetting.hiddenKySoDonVi),
28478
+ },
28479
+ ];
28379
28480
  }
28380
28481
  showContextMenu(evt) {
28381
28482
  this.contextMenu.toggle(evt);
@@ -28386,6 +28487,11 @@ class FileUploadComponent extends ComponentBase {
28386
28487
  this.file.basicFileInput.nativeElement.click();
28387
28488
  }
28388
28489
  }
28490
+ viewListSign(e, signatures) {
28491
+ e.stopPropagation();
28492
+ this.forms[this.formIds.signatureDetail].show = true;
28493
+ this.model.advanceData = signatures;
28494
+ }
28389
28495
  onSelectFile(evt) {
28390
28496
  if (evt.errorFiles && evt.errorFiles.length > 0) {
28391
28497
  this.showNoti = true;
@@ -28414,6 +28520,12 @@ class FileUploadComponent extends ComponentBase {
28414
28520
  this.writeValue(rs.data);
28415
28521
  this.onChangeBase(rs.data);
28416
28522
  this.control.hasFile = this.hasFile;
28523
+ this._fileExplorerService.getSignatureInfoByFileId(rs.data).then(rs => {
28524
+ var _a;
28525
+ if (rs.success && ((_a = rs.data) === null || _a === void 0 ? void 0 : _a.length)) {
28526
+ this.selectedFile.signatures = rs.data;
28527
+ }
28528
+ });
28417
28529
  this.onSelect.emit();
28418
28530
  this.onChanged.emit(rs.data);
28419
28531
  }
@@ -28482,11 +28594,432 @@ class FileUploadComponent extends ComponentBase {
28482
28594
  this.forms.fileViewer.show = true;
28483
28595
  });
28484
28596
  }
28597
+ signFileSmartCA(dataKySo) {
28598
+ var _a;
28599
+ return __awaiter(this, void 0, void 0, function* () {
28600
+ this.signatureFormModel.show = false;
28601
+ let sourceFileId = this.selectedFile.id;
28602
+ if (this._fileExplorerService.needConvertBeforeSign(this.selectedFile.name)) {
28603
+ try {
28604
+ const rsConvert = yield this._fileExplorerService.convertDocumentToPdfAndSave({
28605
+ instanceId: sourceFileId,
28606
+ name: this._fileExplorerService.changeFileExtension(this.selectedFile.name, 'pdf'),
28607
+ folderInstanceId: (_a = this.selectedFile.parentFolderId) !== null && _a !== void 0 ? _a : this._commonService.guid(),
28608
+ ownerType: this._userService.getCurrentUser().userId.toString(),
28609
+ });
28610
+ if (!rsConvert || !rsConvert.success) {
28611
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${this.selectedFile.name} thành pdf để ký. Vui lòng thử lại sau`);
28612
+ return;
28613
+ }
28614
+ else {
28615
+ this._notifierService.showSuccess(`Chuyển đổi tài liệu ${this.selectedFile.name} thành pdf thành công`);
28616
+ sourceFileId = rsConvert.data;
28617
+ }
28618
+ }
28619
+ catch (e) {
28620
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${this.selectedFile.name} thành pdf để ký. Vui lòng thử lại sau`);
28621
+ return;
28622
+ }
28623
+ }
28624
+ if (!dataKySo) {
28625
+ this._notifierService.showWarning('Người dùng chưa cấu hình thông tin ký số');
28626
+ }
28627
+ debugger;
28628
+ this.forms.fileViewer.formData.data = {
28629
+ fileId: sourceFileId,
28630
+ isFileVersion: false,
28631
+ fileName: this.selectedFile.name,
28632
+ // service: this.serviceCode,
28633
+ // entity: this.entity,
28634
+ // entityKey: this.entityKey,
28635
+ fileBase64Content: dataKySo.fileBase64Content,
28636
+ userChuKySoId: dataKySo.id,
28637
+ showKySoButton: true,
28638
+ width: dataKySo.width,
28639
+ height: dataKySo.height,
28640
+ };
28641
+ this.forms.fileViewer.show = true;
28642
+ });
28643
+ }
28644
+ signKySimFile(file) {
28645
+ this.forms.kySoSim.show = true;
28646
+ this.model.advanceData = file;
28647
+ }
28648
+ signFile(file) {
28649
+ this._notifierService.showConfirm('Bạn có chắc chắn muốn ký số văn bản này?').then((rs) => __awaiter(this, void 0, void 0, function* () {
28650
+ if (rs) {
28651
+ let sourceFileId = file.id;
28652
+ let sourceFile = file;
28653
+ // Ký số file word - cần convert sang pdf trước
28654
+ if (this._fileExplorerService.needConvertBeforeSign(file.name)) {
28655
+ // convert file before sign
28656
+ try {
28657
+ const rsConvert = yield this._fileExplorerService.convertDocumentToPdfAndSave({
28658
+ instanceId: sourceFileId,
28659
+ name: this._fileExplorerService.changeFileExtension(file.name, 'pdf'),
28660
+ folderInstanceId: file.parentFolderId,
28661
+ ownerType: this._userService.getCurrentUser().userId.toString(),
28662
+ });
28663
+ if (!rsConvert || !rsConvert.success) {
28664
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
28665
+ return;
28666
+ }
28667
+ else {
28668
+ this._notifierService.showSuccess(`Chuyển đổi tài liệu ${file.name} thành pdf thành công`);
28669
+ sourceFileId = rsConvert.data;
28670
+ sourceFile = { id: sourceFileId };
28671
+ this.getFile();
28672
+ }
28673
+ }
28674
+ catch (e) {
28675
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
28676
+ return;
28677
+ }
28678
+ }
28679
+ this._fileExplorerService.generateLinkDownload({
28680
+ fileId: sourceFileId,
28681
+ }).then(rs => {
28682
+ const url = this._downloadLinkService.getDownloadForSignUrl(rs.data);
28683
+ const prms = {};
28684
+ prms['FileUploadHandler'] = `${this._moduleConfig.environment.apiDomain.fileEndpoint}/${this._moduleConfig.environment.apiVersion}/KySoFile/SavePhysicalSignedFile`;
28685
+ prms['SessionId'] = '';
28686
+ prms['FileName'] = url;
28687
+ // tslint:disable-next-line: variable-name
28688
+ const json_prms = JSON.stringify(prms);
28689
+ vgca_sign_approved(json_prms, (result) => {
28690
+ const resultObj = JSON.parse(result);
28691
+ if (resultObj.FileServer != '') {
28692
+ this._fileExplorerService.saveSignedFile({
28693
+ sourceFile: sourceFile,
28694
+ tempFileId: resultObj.FileServer,
28695
+ }).then(rss => {
28696
+ this.getFile();
28697
+ this._notifierService.showSuccess('Ký số thành công');
28698
+ });
28699
+ }
28700
+ });
28701
+ });
28702
+ }
28703
+ }));
28704
+ }
28705
+ signVNPTCA(item) {
28706
+ var _a;
28707
+ return __awaiter(this, void 0, void 0, function* () {
28708
+ let sourceFileId = item.id;
28709
+ if (this._fileExplorerService.needConvertBeforeSign(item.name)) {
28710
+ // convert file before sign
28711
+ try {
28712
+ const rsConvert = yield this._fileExplorerService.convertDocumentToPdfAndSave({
28713
+ instanceId: item.id,
28714
+ name: this._fileExplorerService.changeFileExtension(item.name, 'pdf'),
28715
+ folderInstanceId: (_a = item.parentFolderId) !== null && _a !== void 0 ? _a : this._commonService.guid(),
28716
+ ownerType: this._userService.getCurrentUser().userId.toString(),
28717
+ });
28718
+ if (!rsConvert || !rsConvert.success) {
28719
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${item.name} thành pdf để ký. Vui lòng thử lại sau`);
28720
+ return;
28721
+ }
28722
+ else {
28723
+ this._notifierService.showSuccess(`Chuyển đổi tài liệu ${item.name} thành pdf thành công`);
28724
+ sourceFileId = rsConvert.data;
28725
+ this.model.selectedItem.id = rsConvert.data;
28726
+ this.getFile();
28727
+ }
28728
+ }
28729
+ catch (e) {
28730
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${item.name} thành pdf để ký. Vui lòng thử lại sau`);
28731
+ return;
28732
+ }
28733
+ }
28734
+ const dataInput = (yield this._fileExplorerService.getBase64FromFileId(sourceFileId)).split(',')[1];
28735
+ const sigOptions = new PdfSigner();
28736
+ sigOptions.page = 1;
28737
+ sigOptions.AdvancedCustom = true;
28738
+ sigOptions.SigType = 1;
28739
+ const dataJS = {
28740
+ data: dataInput,
28741
+ type: 'pdf',
28742
+ sigOptions: JSON.stringify(sigOptions)
28743
+ };
28744
+ try {
28745
+ const data = yield vnpt_plugin.signArrDataAdvanced([JSON.stringify(dataJS)], "", false);
28746
+ this.handeResult(data);
28747
+ }
28748
+ catch (e) {
28749
+ console.log(e);
28750
+ }
28751
+ });
28752
+ }
28753
+ handeResult(data) {
28754
+ if (typeof JSON.parse(data).code !== 'undefined') {
28755
+ var jsOb = JSON.parse(data);
28756
+ }
28757
+ else {
28758
+ var jsOb = JSON.parse(JSON.parse(data)[0]);
28759
+ }
28760
+ switch (jsOb.code) {
28761
+ case 0:
28762
+ this._fileExplorerService.kySimSaveSignedFile({
28763
+ sourceFile: this.model.selectedItem,
28764
+ fileContents: jsOb.data,
28765
+ }).then((rss) => {
28766
+ this._notifierService.showSuccess("Ký thành công");
28767
+ this.getFile();
28768
+ });
28769
+ break;
28770
+ case 1:
28771
+ this._notifierService.showWarning("Dữ liệu đầu vào không đúng định dạng");
28772
+ break;
28773
+ case 2:
28774
+ this._notifierService.showWarning("Không lấy được thông tin chứng thư số");
28775
+ break;
28776
+ case 3:
28777
+ this._notifierService.showWarning("Có lỗi trong quá trình ký số");
28778
+ break;
28779
+ case 4:
28780
+ this._notifierService.showSuccess("Chứng thư số không có khóa bí mật");
28781
+ break;
28782
+ case 5:
28783
+ this._notifierService.showSuccess("Lỗi không xác định");
28784
+ break;
28785
+ case 6:
28786
+ this._notifierService.showSuccess("Ký pdf: không tìm thấy tham số số trang cần ký");
28787
+ break;
28788
+ case 7:
28789
+ this._notifierService.showSuccess("Ký pdf: trang đặt chữ ký không tồn tại");
28790
+ break;
28791
+ case 8:
28792
+ this._notifierService.showSuccess("Ký xml: không tìm thấy thẻ ký số");
28793
+ break;
28794
+ case 9:
28795
+ this._notifierService.showSuccess("Ký pdf: không tìm thấy id của thẻ ký số");
28796
+ break;
28797
+ case 10:
28798
+ this._notifierService.showSuccess("Dữ liệu ký đã chứa một hoặc nhiều chữ ký không hợp lệ");
28799
+ break;
28800
+ case 11:
28801
+ this._notifierService.showSuccess("Người dùng hủy bỏ");
28802
+ break;
28803
+ case 13:
28804
+ this._notifierService.showWarning("Dữ liệu ký rỗng");
28805
+ break;
28806
+ default:
28807
+ this._notifierService.showSuccess("Lỗi không xác định");
28808
+ break;
28809
+ }
28810
+ }
28811
+ addComment(file) {
28812
+ this._notifierService.showConfirm('Bạn có chắc chắn muốn bút phê văn bản này?').then((rs) => __awaiter(this, void 0, void 0, function* () {
28813
+ if (rs) {
28814
+ let sourceFileId = file.id;
28815
+ let sourceFile = file;
28816
+ // Ký số file word - cần convert sang pdf trước
28817
+ if (this._fileExplorerService.needConvertBeforeSign(file.name)) {
28818
+ // convert file before sign
28819
+ try {
28820
+ const rsConvert = yield this._fileExplorerService.convertDocumentToPdfAndSave({
28821
+ instanceId: sourceFileId,
28822
+ name: this._fileExplorerService.changeFileExtension(file.name, 'pdf'),
28823
+ folderInstanceId: file.parentFolderId,
28824
+ ownerType: this._userService.getCurrentUser().userId.toString(),
28825
+ });
28826
+ if (!rsConvert || !rsConvert.success) {
28827
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
28828
+ return;
28829
+ }
28830
+ else {
28831
+ this._notifierService.showSuccess(`Chuyển đổi tài liệu ${file.name} thành pdf thành công`);
28832
+ sourceFileId = rsConvert.data;
28833
+ sourceFile = { id: sourceFileId };
28834
+ this.getFile();
28835
+ }
28836
+ }
28837
+ catch (e) {
28838
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
28839
+ return;
28840
+ }
28841
+ }
28842
+ this._fileExplorerService.generateLinkDownload({
28843
+ fileId: sourceFileId,
28844
+ }).then(rs => {
28845
+ const url = this._downloadLinkService.getDownloadForSignUrl(rs.data);
28846
+ const prms = {};
28847
+ prms['FileUploadHandler'] = `${this._moduleConfig.environment.apiDomain.fileEndpoint}/${this._moduleConfig.environment.apiVersion}/KySoFile/SavePhysicalSignedFile`;
28848
+ prms['SessionId'] = '';
28849
+ prms['FileName'] = url;
28850
+ // tslint:disable-next-line: variable-name
28851
+ const json_prms = JSON.stringify(prms);
28852
+ vgca_comment(json_prms, (result) => {
28853
+ const resultObj = JSON.parse(result);
28854
+ if (resultObj.FileServer != '') {
28855
+ this._fileExplorerService.saveSignedFile({
28856
+ sourceFile: sourceFile,
28857
+ tempFileId: resultObj.FileServer,
28858
+ }).then(rss => {
28859
+ this.getFile();
28860
+ this._notifierService.showSuccess('Tạo bút phê thành công');
28861
+ });
28862
+ }
28863
+ });
28864
+ });
28865
+ }
28866
+ }));
28867
+ }
28868
+ addCommentAndSign(file) {
28869
+ return __awaiter(this, void 0, void 0, function* () {
28870
+ const rs = yield this._notifierService.showConfirm('Bạn có chắc chắn muốn tạo bút phê và ký văn bản này?');
28871
+ if (rs) {
28872
+ let sourceFileId = file.id;
28873
+ let sourceFile = file;
28874
+ // Ký số file word - cần convert sang pdf trước
28875
+ if (this._fileExplorerService.needConvertBeforeSign(file.name)) {
28876
+ // convert file before sign
28877
+ try {
28878
+ const rsConvert = yield this._fileExplorerService.convertDocumentToPdfAndSave({
28879
+ instanceId: sourceFileId,
28880
+ name: this._fileExplorerService.changeFileExtension(file.name, 'pdf'),
28881
+ folderInstanceId: file.parentFolderId,
28882
+ ownerType: this._userService.getCurrentUser().userId.toString(),
28883
+ });
28884
+ if (!rsConvert || !rsConvert.success) {
28885
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
28886
+ return;
28887
+ }
28888
+ else {
28889
+ this._notifierService.showSuccess(`Chuyển đổi tài liệu ${file.name} thành pdf thành công`);
28890
+ sourceFileId = rsConvert.data;
28891
+ sourceFile = { id: sourceFileId };
28892
+ this.getFile();
28893
+ }
28894
+ }
28895
+ catch (e) {
28896
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
28897
+ return;
28898
+ }
28899
+ }
28900
+ const downloadLink = yield this._fileExplorerService.generateLinkDownload({
28901
+ fileId: sourceFileId,
28902
+ });
28903
+ const url = this._downloadLinkService.getDownloadForSignUrl(downloadLink.data);
28904
+ const prms = {
28905
+ FileUploadHandler: `${this._moduleConfig.environment.apiDomain.fileEndpoint}/${this._moduleConfig.environment.apiVersion}/KySoFile/SavePhysicalSignedFile`,
28906
+ SessionId: '',
28907
+ FileName: url
28908
+ };
28909
+ const json_prms = JSON.stringify(prms);
28910
+ // Wrap callback-based functions in Promises
28911
+ const commentResult = yield new Promise((resolve) => {
28912
+ vgca_comment(json_prms, (result) => resolve(result));
28913
+ });
28914
+ const resultObj = JSON.parse(commentResult);
28915
+ const downloadLink2 = yield this._fileExplorerService.generateLinkDownload({
28916
+ fileId: resultObj.FileServer,
28917
+ });
28918
+ const url2 = this._downloadLinkService.getDownloadForSignUrl(downloadLink2.data);
28919
+ const prms2 = {
28920
+ FileUploadHandler: `${this._moduleConfig.environment.apiDomain.fileEndpoint}/${this._moduleConfig.environment.apiVersion}/KySoFile/SavePhysicalSignedFile`,
28921
+ SessionId: '',
28922
+ FileName: url2
28923
+ };
28924
+ const json_prms2 = JSON.stringify(prms2);
28925
+ const signResult = yield new Promise((resolve) => {
28926
+ vgca_sign_approved(json_prms2, (result) => resolve(result));
28927
+ });
28928
+ const signResultObj = JSON.parse(signResult);
28929
+ if (signResultObj.FileServer != '') {
28930
+ yield this._fileExplorerService.saveSignedFile({
28931
+ sourceFile: sourceFile,
28932
+ tempFileId: signResultObj.FileServer,
28933
+ });
28934
+ this.getFile();
28935
+ this._notifierService.showSuccess('Tạo bút phê và ký thành công');
28936
+ }
28937
+ }
28938
+ });
28939
+ }
28940
+ signFileDonVi(file) {
28941
+ this._notifierService
28942
+ .showConfirm('Bạn có chắc chắn muốn ký số đơn vị văn bản này?')
28943
+ .then((rs) => __awaiter(this, void 0, void 0, function* () {
28944
+ if (rs) {
28945
+ let sourceFileId = file.id;
28946
+ let sourceFile = file;
28947
+ if (this._fileExplorerService.needConvertBeforeSign(file.name)) {
28948
+ // convert file before sign
28949
+ try {
28950
+ const rsConvert = yield this._fileExplorerService.convertDocumentToPdfAndSave({
28951
+ instanceId: sourceFileId,
28952
+ name: this._fileExplorerService.changeFileExtension(file.name, 'pdf'),
28953
+ folderInstanceId: file.parentFolderId,
28954
+ ownerType: this._userService.getCurrentUser().userId.toString(),
28955
+ });
28956
+ if (!rsConvert || !rsConvert.success) {
28957
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
28958
+ return;
28959
+ }
28960
+ else {
28961
+ this._notifierService.showSuccess(`Chuyển đổi tài liệu ${file.name} thành pdf thành công`);
28962
+ this.getFile();
28963
+ sourceFileId = rsConvert.data;
28964
+ sourceFile = { id: sourceFileId };
28965
+ }
28966
+ }
28967
+ catch (e) {
28968
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
28969
+ return;
28970
+ }
28971
+ }
28972
+ this._fileExplorerService
28973
+ .generateLinkDownload({
28974
+ isFileVersion: false,
28975
+ fileId: sourceFileId,
28976
+ })
28977
+ .then((rs) => {
28978
+ const url = this._downloadLinkService.getDownloadForSignUrl(rs.data);
28979
+ const prms = {};
28980
+ prms['FileUploadHandler'] = `${this._moduleConfig.environment.apiDomain.fileEndpoint}/${this._moduleConfig.environment.apiVersion}/KySoFile/SavePhysicalSignedFile`;
28981
+ prms['SessionId'] = '';
28982
+ prms['FileName'] = url;
28983
+ // Truyền số, ngày ký số phòng ban nếu cần
28984
+ const that = this;
28985
+ if (that.control && that.control.dataKySoDonVi) {
28986
+ const dataKySoDonVi = that.control.dataKySoDonVi();
28987
+ if (dataKySoDonVi) {
28988
+ // lấy số DocNumber
28989
+ if (dataKySoDonVi.docNumber) {
28990
+ prms['DocNumber'] = dataKySoDonVi.docNumber;
28991
+ }
28992
+ // lấy ngày ban hành vb đi
28993
+ if (dataKySoDonVi.issuedDate) {
28994
+ prms['IssuedDate'] = dataKySoDonVi.issuedDate;
28995
+ }
28996
+ }
28997
+ }
28998
+ // tslint:disable-next-line: variable-name
28999
+ const json_prms = JSON.stringify(prms);
29000
+ vgca_sign_issued(json_prms, (result) => {
29001
+ const resultObj = JSON.parse(result);
29002
+ if (resultObj.FileServer != '') {
29003
+ this._fileExplorerService
29004
+ .saveSignedFile({
29005
+ sourceFile: sourceFile,
29006
+ tempFileId: resultObj.FileServer,
29007
+ })
29008
+ .then((rss) => {
29009
+ this.getFile();
29010
+ this._notifierService.showSuccess('Ký số thành công');
29011
+ });
29012
+ }
29013
+ });
29014
+ });
29015
+ }
29016
+ }));
29017
+ }
28485
29018
  }
28486
29019
  FileUploadComponent.decorators = [
28487
29020
  { type: Component, args: [{
28488
29021
  selector: 'file-upload',
28489
- template: "<div class=\"file-upload\">\n <div class=\"fl-icon\">\n <i *ngIf=\"loading\" class=\"pi pi-spin pi-spinner\" style=\"font-size: 2rem\"></i>\n <i *ngIf=\"!loading\" class=\"pi pi-file-o\" style=\"font-size: 2rem\"></i>\n </div>\n\n <div class=\"fl-file-name\" (click)=\"openFileViewer()\">\n <span *ngIf=\"!showNoti\">{{selectedFileName}}</span>\n <span *ngIf=\"showNoti\"> {{notification}} </span>\n </div>\n\n <div class=\"fl-buttons\">\n <button *ngIf=\"!hasFile && !readonly\" pTooltip=\"Ch\u1ECDn file\" class=\"fl-choose\"\n class=\"link-or-action p-button-text p-button-rounded fl-choose\" tooltipPosition=\"top\" pButton type=\"button\"\n icon=\"pi pi-plus\" (click)=\"onOpenSelect()\"></button>\n\n <button *ngIf=\"hasFile && !readonly && showDeleteFile\" (click)=\"onRemoveFile()\"\n class=\"link-or-action p-button-text p-button-rounded p-button-danger fl-remove\" pTooltip=\"X\u00F3a file\"\n tooltipPosition=\"top\" pButton type=\"button\" icon=\"pi pi-trash\"></button>\n\n <button [disabled]=\"!menu || !menu.length\" type=\"button\" pButton icon=\"pi pi-ellipsis-v\"\n class=\"link-or-action p-button-text p-button-rounded\" pTooltip=\"Th\u00EAm\" tooltipPosition=\"top\"\n (click)=\"showContextMenu($event)\"></button>\n </div>\n\n <div style=\"display: none;\">\n <p-fileUpload #file [accept]=\"accept\" [auto]=\"false\" class=\"file-upload\" mode=\"basic\"\n [chooseLabel]=\"chooseLabel\" name=\"file[]\" [accept]=\"accept\" pTooltip=\"Ch\u1ECDn t\u1EEB m\u00E1y t\u00EDnh\"\n toolStipPosition=\"top\" [invalidFileSizeMessageSummary]=\"invalidFileSizeMessageSummary\"\n [invalidFileSizeMessageDetail]=\"invalidFileSizeMessageDetail\"\n [invalidFileTypeMessageSummary]=\"invalidFileTypeMessageSummary\"\n [invalidFileTypeMessageDetail]=\"invalidFileTypeMessageDetail\"\n [invalidFileLimitMessageSummary]=\"invalidFileLimitMessageSummary\"\n [invalidFileLimitMessageDetail]=\"invalidFileLimitMessageDetail\" (onSelect)=\"onSelectFile($event)\"\n (onError)=\"handleError($event)\">\n </p-fileUpload>\n </div>\n\n</div>\n\n<p-contextMenu #contextMenu [appendTo]=\"'body'\" [model]=\"menu\" styleClass=\"fm-contextMenu-panel\">\n</p-contextMenu>\n\n<file-viewer #fileViewerNew *ngIf=\"forms.fileViewer.show\" [parentModel]=\"model\" [parentContext]=\"context\"\n [readonly]=\"readonly\" [model]=\"forms.fileViewer.formData\" (onClose)=\"forms.fileViewer.show = false;\">\n</file-viewer>",
29022
+ template: "<div class=\"file-upload\">\n <div class=\"fl-icon\">\n <i *ngIf=\"loading\" class=\"pi pi-spin pi-spinner\" style=\"font-size: 2rem\"></i>\n <i *ngIf=\"!loading\" class=\"pi pi-file-o\" style=\"font-size: 2rem\"></i>\n </div>\n\n <div class=\"fl-file-name\" (click)=\"openFileViewer()\">\n <span *ngIf=\"!showNoti\">{{selectedFileName}}</span>\n <span *ngIf=\"showNoti\"> {{notification}} </span>\n <span *ngIf=\"selectedFile?.signatures\" class=\"pull-right signature\" pTooltip=\"Xem chi ti\u1EBFt k\u00FD s\u1ED1\"\n tooltipPosition=\"top\" (click)=\"viewListSign($event, selectedFile.signatures)\">\n <i class=\"fas fa-signature\"></i>\n </span>\n </div>\n <div class=\"fl-buttons\">\n <button *ngIf=\"!hasFile && !readonly\" pTooltip=\"Ch\u1ECDn file\" class=\"fl-choose\"\n class=\"link-or-action p-button-text p-button-rounded fl-choose\" tooltipPosition=\"top\" pButton type=\"button\"\n icon=\"pi pi-plus\" (click)=\"onOpenSelect()\"></button>\n\n <button *ngIf=\"hasFile && !readonly && showDeleteFile\" (click)=\"onRemoveFile()\"\n class=\"link-or-action p-button-text p-button-rounded p-button-danger fl-remove\" pTooltip=\"X\u00F3a file\"\n tooltipPosition=\"top\" pButton type=\"button\" icon=\"pi pi-trash\"></button>\n\n <button [disabled]=\"!menu || !menu.length\" type=\"button\" pButton icon=\"pi pi-ellipsis-v\"\n class=\"link-or-action p-button-text p-button-rounded\" pTooltip=\"Th\u00EAm\" tooltipPosition=\"top\"\n (click)=\"showContextMenu($event)\"></button>\n </div>\n\n <div style=\"display: none;\">\n <p-fileUpload #file [accept]=\"accept\" [auto]=\"false\" class=\"file-upload\" mode=\"basic\"\n [chooseLabel]=\"chooseLabel\" name=\"file[]\" [accept]=\"accept\" pTooltip=\"Ch\u1ECDn t\u1EEB m\u00E1y t\u00EDnh\"\n toolStipPosition=\"top\" [invalidFileSizeMessageSummary]=\"invalidFileSizeMessageSummary\"\n [invalidFileSizeMessageDetail]=\"invalidFileSizeMessageDetail\"\n [invalidFileTypeMessageSummary]=\"invalidFileTypeMessageSummary\"\n [invalidFileTypeMessageDetail]=\"invalidFileTypeMessageDetail\"\n [invalidFileLimitMessageSummary]=\"invalidFileLimitMessageSummary\"\n [invalidFileLimitMessageDetail]=\"invalidFileLimitMessageDetail\" (onSelect)=\"onSelectFile($event)\"\n (onError)=\"handleError($event)\">\n </p-fileUpload>\n </div>\n\n</div>\n\n<p-contextMenu #contextMenu [appendTo]=\"'body'\" [model]=\"menu\" styleClass=\"fm-contextMenu-panel\">\n</p-contextMenu>\n\n<file-viewer #fileViewerNew *ngIf=\"forms.fileViewer.show\" [parentModel]=\"model\" [parentContext]=\"context\"\n [readonly]=\"readonly\" [model]=\"forms.fileViewer.formData\" (onClose)=\"forms.fileViewer.show = false;\">\n</file-viewer>\n<!-- Xem ch\u1EEF k\u00FD s\u1ED1 -->\n<tn-dialog *ngIf=\"forms.signatureDetail.show\" #dialog [styleClass]=\"'address-form'\"\n [header]=\"forms.signatureDetail.header | translate\" [popupSize]=\"forms[formIds.signatureDetail].popupSize\"\n (onHide)=\"forms.signatureDetail.show=false;\">\n <signature-detail [parentModel]=\"model\" [parentContext]=\"context\">\n </signature-detail>\n</tn-dialog>\n<tn-dialog *ngIf=\"signatureFormModel.show\" #dialog [styleClass]=\"'address-form'\" [header]=\"'Ch\u1ECDn ch\u1EEF k\u00FD s\u1ED1' | translate\"\n [popupSize]=\"signatureFormModel.popupSize\" (onHide)=\"signatureFormModel.show=false\">\n <signature-select #formBase [parentModel]=\"model\" [parentContext]=\"context\" [model]=\"signatureFormModel.formData\"\n (onCancel)=\"signatureFormModel.show = false\" (onSaved)=\"signFileSmartCA($event)\">\n </signature-select>\n</tn-dialog>",
28490
29023
  providers: [
28491
29024
  {
28492
29025
  provide: NG_VALUE_ACCESSOR,
@@ -28495,7 +29028,7 @@ FileUploadComponent.decorators = [
28495
29028
  },
28496
29029
  ComponentContextService
28497
29030
  ],
28498
- styles: ["::ng-deep .file-upload{display:flex;border:1px solid #ced4da;border-radius:4px}::ng-deep .file-upload .fl-icon{flex:0 0 30px;display:flex;font-size:20px;justify-content:center;align-items:center;border-right:1px solid #ced4da}::ng-deep .file-upload .fl-icon>i{font-size:16px!important}::ng-deep .file-upload .fl-file-name{display:flex;align-items:center;flex-grow:1;cursor:pointer;opacity:.8;padding-left:12px;color:#109bf8;width:calc(100% - 110px)}::ng-deep .file-upload .fl-file-name>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .file-upload .fl-file-name:hover{opacity:1}::ng-deep .file-upload .fl-buttons{flex:0 0 80px;display:flex;border-right:1px solid #ced4da;align-items:center;justify-content:space-evenly;border-left:1px solid #ced4da}"]
29031
+ styles: ["::ng-deep .file-upload{display:flex;border:1px solid #ced4da;border-radius:4px}::ng-deep .file-upload .fl-icon{flex:0 0 30px;display:flex;font-size:20px;justify-content:center;align-items:center;border-right:1px solid #ced4da}::ng-deep .file-upload .fl-icon>i{font-size:16px!important}::ng-deep .file-upload .fl-file-name{display:flex;align-items:center;flex-grow:1;cursor:pointer;opacity:.8;padding-left:12px;color:#109bf8;width:calc(100% - 110px);position:relative}::ng-deep .file-upload .fl-file-name>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .file-upload .fl-file-name:hover{opacity:1}::ng-deep .file-upload .fl-buttons{flex:0 0 80px;display:flex;border-right:1px solid #ced4da;align-items:center;justify-content:space-evenly;border-left:1px solid #ced4da}::ng-deep .file-upload .nfl-signature{display:flex;align-items:center;justify-content:center;cursor:pointer;opacity:.8;padding:0 10px;color:#109bf8;overflow:hidden}::ng-deep .file-upload .nfl-signature:hover{opacity:1}::ng-deep .file-upload .signature i{position:absolute;top:50%!important;transform:translate(-50%,-50%)!important;right:0}"]
28499
29032
  },] }
28500
29033
  ];
28501
29034
  FileUploadComponent.ctorParameters = () => [
@@ -28504,6 +29037,8 @@ FileUploadComponent.ctorParameters = () => [
28504
29037
  { type: DownloadLinkService },
28505
29038
  { type: ModuleConfigService },
28506
29039
  { type: FileExplorerService },
29040
+ { type: DeviceDetectorService },
29041
+ { type: UserService },
28507
29042
  { type: Injector }
28508
29043
  ];
28509
29044
  FileUploadComponent.propDecorators = {
@@ -28523,6 +29058,7 @@ FileUploadComponent.propDecorators = {
28523
29058
  sharedFolderType: [{ type: Input }],
28524
29059
  control: [{ type: Input }],
28525
29060
  isPublic: [{ type: Input }],
29061
+ parentSetting: [{ type: Input }],
28526
29062
  onInit: [{ type: Output }],
28527
29063
  onSelect: [{ type: Output }],
28528
29064
  onRemove: [{ type: Output }],
@@ -34471,7 +35007,7 @@ FileViewerComponent.propDecorators = {
34471
35007
  };
34472
35008
 
34473
35009
  class ServiceFileUploadComponent extends ComponentBase {
34474
- constructor(_fileObjectService, _signalRService, _moduleConfigService, _tnClientService, _authenService, _userService, _notifierService, _downloadLinkService, _fileExplorerService, _injector) {
35010
+ constructor(_fileObjectService, _signalRService, _moduleConfigService, _tnClientService, _authenService, _userService, _notifierService, _downloadLinkService, _fileExplorerService, _deviceDetectorService, _injector) {
34475
35011
  super(_injector);
34476
35012
  this._fileObjectService = _fileObjectService;
34477
35013
  this._signalRService = _signalRService;
@@ -34482,10 +35018,12 @@ class ServiceFileUploadComponent extends ComponentBase {
34482
35018
  this._notifierService = _notifierService;
34483
35019
  this._downloadLinkService = _downloadLinkService;
34484
35020
  this._fileExplorerService = _fileExplorerService;
35021
+ this._deviceDetectorService = _deviceDetectorService;
34485
35022
  this.control = new FileUploadControlSchema();
34486
35023
  this.serviceCode = '';
34487
35024
  this.entity = '';
34488
35025
  this.chooseLabel = 'Chọn';
35026
+ this.parentSetting = new CrudFormSetting();
34489
35027
  this.onInit = new EventEmitter();
34490
35028
  this.onSelect = new EventEmitter();
34491
35029
  this.onRemove = new EventEmitter();
@@ -34510,6 +35048,25 @@ class ServiceFileUploadComponent extends ComponentBase {
34510
35048
  this._subscribe = null;
34511
35049
  this.dataModel = {};
34512
35050
  this.forms = {};
35051
+ this.formIds = {
35052
+ createFolder: 'createFolder',
35053
+ renameFile: 'renameFile',
35054
+ shareFile: 'shareFile',
35055
+ shareFolder: 'shareFolder',
35056
+ fileViewer: 'fileViewer',
35057
+ fileVersionList: 'fileVersionList',
35058
+ signatureDetail: 'signatureDetail',
35059
+ kySoSim: 'kySoSim',
35060
+ viewDetail: 'viewDetail'
35061
+ };
35062
+ this.signatureFormModel = {
35063
+ formData: new CrudFormData(),
35064
+ show: false,
35065
+ popupSize: new PopupSize({
35066
+ width: 600,
35067
+ height: 400
35068
+ })
35069
+ };
34513
35070
  if (this._userService.isValidAccessToken()) {
34514
35071
  this.userId = this._userService.getUserIdCombine();
34515
35072
  }
@@ -34542,6 +35099,10 @@ class ServiceFileUploadComponent extends ComponentBase {
34542
35099
  show: false,
34543
35100
  formData: {},
34544
35101
  };
35102
+ this.forms[this.formIds.signatureDetail] = {
35103
+ header: 'Thông tin chữ ký số',
35104
+ show: false,
35105
+ };
34545
35106
  if (this.fileDataService) {
34546
35107
  this.fileDataService.register(this);
34547
35108
  }
@@ -34569,6 +35130,12 @@ class ServiceFileUploadComponent extends ComponentBase {
34569
35130
  else {
34570
35131
  this.setFileObject(null);
34571
35132
  }
35133
+ this._fileExplorerService.getSignatureInfoByFileId(this.fileId).then(rs => {
35134
+ var _a;
35135
+ if (rs.success && ((_a = rs.data) === null || _a === void 0 ? void 0 : _a.length)) {
35136
+ this.selectedFile.signatures = rs.data;
35137
+ }
35138
+ });
34572
35139
  this.control.hasFile = this.hasFile;
34573
35140
  this.setMenu();
34574
35141
  });
@@ -34584,6 +35151,7 @@ class ServiceFileUploadComponent extends ComponentBase {
34584
35151
  this.onChanged.emit();
34585
35152
  return;
34586
35153
  }
35154
+ this.selectedFile = fileObject;
34587
35155
  this.fileObj = fileObject;
34588
35156
  this.fileId = fileObject.id;
34589
35157
  this.setFileName(fileObject.name);
@@ -34610,7 +35178,70 @@ class ServiceFileUploadComponent extends ComponentBase {
34610
35178
  command: () => {
34611
35179
  this.download();
34612
35180
  }
34613
- }
35181
+ },
35182
+ {
35183
+ label: 'Ký số cá nhân (SIM)',
35184
+ icon: 'fas fa-sim-card',
35185
+ command: () => {
35186
+ this.signKySimFile(this.selectedFile);
35187
+ },
35188
+ visible: (this._fileObjectService.isTypeFileKySo(this.selectedFile.name)
35189
+ && !this.parentSetting.hiddenKySoSimCaNhan),
35190
+ },
35191
+ {
35192
+ label: 'Ký số SmartCA',
35193
+ icon: 'fas fa-signature',
35194
+ command: () => {
35195
+ this.signatureFormModel.show = true;
35196
+ },
35197
+ visible: (this._fileObjectService.isTypeFileKySo(this.selectedFile.name)
35198
+ && !this.parentSetting.hiddenKySoSmartCA),
35199
+ },
35200
+ {
35201
+ label: 'Ký số cá nhân (USB)', icon: 'fas fa-signature',
35202
+ command: () => {
35203
+ this.signFile(this.selectedFile);
35204
+ },
35205
+ visible: (this._fileObjectService.isTypeFileKySo(this.selectedFile.name)
35206
+ && this._deviceDetectorService.isDesktop()
35207
+ && !this.parentSetting.hiddenKySoUsbCaNhan),
35208
+ },
35209
+ {
35210
+ label: 'Ký số VNPTCA', icon: 'fas fa-signature',
35211
+ command: () => {
35212
+ this.signVNPTCA(this.selectedFile);
35213
+ },
35214
+ visible: (this._fileObjectService.isTypeFileKySo(this.selectedFile.name)
35215
+ && this._deviceDetectorService.isDesktop()
35216
+ && !this.parentSetting.hiddenKySoVNPTCA),
35217
+ },
35218
+ {
35219
+ label: 'Bút phê', icon: 'fas fa-comment-dots',
35220
+ command: () => {
35221
+ this.addComment(this.selectedFile);
35222
+ },
35223
+ visible: (this._fileObjectService.isTypeFileKySo(this.selectedFile.name)
35224
+ && this._deviceDetectorService.isDesktop()
35225
+ && !this.parentSetting.hiddenButPhe),
35226
+ },
35227
+ {
35228
+ label: 'Bút phê và ký', icon: 'fas fa-comment-medical',
35229
+ command: () => {
35230
+ this.addCommentAndSign(this.selectedFile);
35231
+ },
35232
+ visible: (this._fileObjectService.isTypeFileKySo(this.selectedFile.name)
35233
+ && this._deviceDetectorService.isDesktop()
35234
+ && !this.parentSetting.hiddenButPhe),
35235
+ },
35236
+ {
35237
+ label: 'Ký số đơn vị (USB)', icon: 'fas fa-signature',
35238
+ command: () => {
35239
+ this.signFileDonVi(this.selectedFile);
35240
+ },
35241
+ visible: (this._fileObjectService.isTypeFileKySo(this.selectedFile.name)
35242
+ && this._deviceDetectorService.isDesktop()
35243
+ && !this.parentSetting.hiddenKySoDonVi),
35244
+ },
34614
35245
  ];
34615
35246
  }
34616
35247
  subscribe() {
@@ -34638,70 +35269,82 @@ class ServiceFileUploadComponent extends ComponentBase {
34638
35269
  }
34639
35270
  }
34640
35271
  onSelectFile(evt) {
34641
- this.hasFile = false;
34642
- this.fileId = null;
34643
- this.file.clear();
34644
- if (evt.errorFiles && evt.errorFiles.length > 0) {
34645
- this.showNoti = true;
34646
- this.notification = `${evt.errorMessages[0].summary}${evt.errorMessages[0].detail}`;
34647
- }
34648
- else {
34649
- this.selectedFile = evt.successFiles[0];
34650
- this.setFileName(this.selectedFile ? this.selectedFile.name : null);
34651
- if (this.control.autoSaved) {
34652
- this.handleSaveFile();
35272
+ return __awaiter(this, void 0, void 0, function* () {
35273
+ this.hasFile = false;
35274
+ this.fileId = null;
35275
+ this.file.clear();
35276
+ if (evt.errorFiles && evt.errorFiles.length > 0) {
35277
+ this.showNoti = true;
35278
+ this.notification = `${evt.errorMessages[0].summary}${evt.errorMessages[0].detail}`;
34653
35279
  }
34654
35280
  else {
34655
- this.hasFile = true;
34656
- this.onChangeBase('has-value');
34657
- this.onSelect.emit(this.selectedFile);
34658
- this.onChanged.emit(this.selectedFile);
35281
+ this.selectedFile = evt.successFiles[0];
35282
+ this.setFileName(this.selectedFile ? this.selectedFile.name : null);
35283
+ if (this.control.autoSaved) {
35284
+ yield this.handleSaveFile();
35285
+ }
35286
+ else {
35287
+ this.hasFile = true;
35288
+ this.onChangeBase('has-value');
35289
+ this.onSelect.emit(this.selectedFile);
35290
+ this.onChanged.emit(this.selectedFile);
35291
+ }
34659
35292
  }
34660
- }
34661
- this.control.hasFile = this.hasFile;
35293
+ this.control.hasFile = this.hasFile;
35294
+ this.setMenu();
35295
+ });
34662
35296
  }
34663
35297
  handleSaveFile() {
34664
- // Đã lưu file.
34665
- if (this.fileId) {
34666
- return;
34667
- }
34668
- // Trường hợp không có đủ keys.
34669
- if (!this.hasKeys()) {
34670
- this._notifierService.showWarning('Chưa cấu hình keys');
34671
- return;
34672
- }
34673
- // Chưa chọn file.
34674
- if (!this.selectedFile) {
34675
- return;
34676
- }
34677
- const formData = new FormData();
34678
- formData.append('serviceCode', this.serviceCode);
34679
- formData.append('entity', this.entity);
34680
- formData.append('entityKey', this.entityKey);
34681
- formData.append('isMultiple', 'false');
34682
- formData.append('isPublic', `${this.control.isPublic}`);
34683
- formData.append('file', this.selectedFile);
34684
- this.loading = true;
34685
- this.setNoti('Đang tải file lên...');
34686
- this._fileObjectService.createServiceFile(formData)
34687
- .then(rs => {
34688
- this.loading = false;
34689
- this.setNoti(null);
34690
- if (rs.success) {
34691
- this.selectedFile = this.selectedFile;
34692
- this.selectedFileName = this.selectedFile.name;
34693
- this.fileId = rs.data;
34694
- this.hasFile = true;
34695
- this.control.hasFile = this.hasFile;
34696
- this.onChanged.emit({ fileId: this.fileId, selectedFile: this.selectedFile });
35298
+ return __awaiter(this, void 0, void 0, function* () {
35299
+ // Đã lưu file.
35300
+ if (this.fileId) {
35301
+ return;
34697
35302
  }
34698
- else {
34699
- this._crudService.processErrorResponse(rs);
35303
+ // Trường hợp không có đủ keys.
35304
+ if (!this.hasKeys()) {
35305
+ this._notifierService.showWarning('Chưa cấu hình keys');
35306
+ return;
34700
35307
  }
34701
- }, err => {
34702
- this.loading = false;
34703
- this.setNoti(null);
34704
- this._notifierService.showWarning('Upload file chưa thành công');
35308
+ // Chưa chọn file.
35309
+ if (!this.selectedFile) {
35310
+ return;
35311
+ }
35312
+ const formData = new FormData();
35313
+ formData.append('serviceCode', this.serviceCode);
35314
+ formData.append('entity', this.entity);
35315
+ formData.append('entityKey', this.entityKey);
35316
+ formData.append('isMultiple', 'false');
35317
+ formData.append('isPublic', `${this.control.isPublic}`);
35318
+ formData.append('file', this.selectedFile);
35319
+ this.loading = true;
35320
+ this.setNoti('Đang tải file lên...');
35321
+ yield this._fileObjectService.createServiceFile(formData)
35322
+ .then(rs => {
35323
+ this.loading = false;
35324
+ this.setNoti(null);
35325
+ if (rs.success) {
35326
+ this.selectedFile = this.selectedFile;
35327
+ this.selectedFileName = this.selectedFile.name;
35328
+ this.fileId = rs.data;
35329
+ this.selectedFile.id = rs.data;
35330
+ this.hasFile = true;
35331
+ this.control.hasFile = this.hasFile;
35332
+ this.onChanged.emit({ fileId: this.fileId, selectedFile: this.selectedFile });
35333
+ this._fileExplorerService.getSignatureInfoByFileId(this.fileId).then(rs => {
35334
+ var _a;
35335
+ if (rs.success && ((_a = rs.data) === null || _a === void 0 ? void 0 : _a.length)) {
35336
+ this.selectedFile.signatures = rs.data;
35337
+ }
35338
+ });
35339
+ }
35340
+ else {
35341
+ this._crudService.processErrorResponse(rs);
35342
+ }
35343
+ }, err => {
35344
+ this.loading = false;
35345
+ this.setNoti(null);
35346
+ this._notifierService.showWarning('Upload file chưa thành công');
35347
+ });
34705
35348
  });
34706
35349
  }
34707
35350
  setNoti(msg) {
@@ -34726,6 +35369,11 @@ class ServiceFileUploadComponent extends ComponentBase {
34726
35369
  this.selectedFileNameShort = null;
34727
35370
  }
34728
35371
  }
35372
+ viewListSign(e, signatures) {
35373
+ e.stopPropagation();
35374
+ this.forms[this.formIds.signatureDetail].show = true;
35375
+ this.model.advanceData = signatures;
35376
+ }
34729
35377
  showContextMenu(evt) {
34730
35378
  this.contextMenu.toggle(evt);
34731
35379
  evt.stopPropagation();
@@ -34869,11 +35517,432 @@ class ServiceFileUploadComponent extends ComponentBase {
34869
35517
  this.forms.fileViewer.show = true;
34870
35518
  });
34871
35519
  }
35520
+ signFileSmartCA(dataKySo) {
35521
+ var _a;
35522
+ return __awaiter(this, void 0, void 0, function* () {
35523
+ this.signatureFormModel.show = false;
35524
+ let sourceFileId = this.selectedFile.id;
35525
+ if (this._fileExplorerService.needConvertBeforeSign(this.selectedFile.name)) {
35526
+ try {
35527
+ const rsConvert = yield this._fileExplorerService.convertDocumentToPdfAndSave({
35528
+ instanceId: sourceFileId,
35529
+ name: this._fileExplorerService.changeFileExtension(this.selectedFile.name, 'pdf'),
35530
+ folderInstanceId: (_a = this.selectedFile.parentFolderId) !== null && _a !== void 0 ? _a : this._commonService.guid(),
35531
+ ownerType: this._userService.getCurrentUser().userId.toString(),
35532
+ });
35533
+ if (!rsConvert || !rsConvert.success) {
35534
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${this.selectedFile.name} thành pdf để ký. Vui lòng thử lại sau`);
35535
+ return;
35536
+ }
35537
+ else {
35538
+ this._notifierService.showSuccess(`Chuyển đổi tài liệu ${this.selectedFile.name} thành pdf thành công`);
35539
+ sourceFileId = rsConvert.data;
35540
+ }
35541
+ }
35542
+ catch (e) {
35543
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${this.selectedFile.name} thành pdf để ký. Vui lòng thử lại sau`);
35544
+ return;
35545
+ }
35546
+ }
35547
+ if (!dataKySo) {
35548
+ this._notifierService.showWarning('Người dùng chưa cấu hình thông tin ký số');
35549
+ }
35550
+ debugger;
35551
+ this.forms.fileViewer.formData.data = {
35552
+ fileId: sourceFileId,
35553
+ isFileVersion: false,
35554
+ fileName: this.selectedFile.name,
35555
+ service: this.serviceCode,
35556
+ entity: this.entity,
35557
+ entityKey: this.entityKey,
35558
+ fileBase64Content: dataKySo.fileBase64Content,
35559
+ userChuKySoId: dataKySo.id,
35560
+ showKySoButton: true,
35561
+ width: dataKySo.width,
35562
+ height: dataKySo.height,
35563
+ };
35564
+ this.forms.fileViewer.show = true;
35565
+ });
35566
+ }
35567
+ signKySimFile(file) {
35568
+ this.forms.kySoSim.show = true;
35569
+ this.model.advanceData = file;
35570
+ }
35571
+ signFile(file) {
35572
+ this._notifierService.showConfirm('Bạn có chắc chắn muốn ký số văn bản này?').then((rs) => __awaiter(this, void 0, void 0, function* () {
35573
+ if (rs) {
35574
+ let sourceFileId = file.id;
35575
+ let sourceFile = file;
35576
+ // Ký số file word - cần convert sang pdf trước
35577
+ if (this._fileExplorerService.needConvertBeforeSign(file.name)) {
35578
+ // convert file before sign
35579
+ try {
35580
+ const rsConvert = yield this._fileExplorerService.convertDocumentToPdfAndSave({
35581
+ instanceId: sourceFileId,
35582
+ name: this._fileExplorerService.changeFileExtension(file.name, 'pdf'),
35583
+ folderInstanceId: file.parentFolderId,
35584
+ ownerType: this._userService.getCurrentUser().userId.toString(),
35585
+ });
35586
+ if (!rsConvert || !rsConvert.success) {
35587
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
35588
+ return;
35589
+ }
35590
+ else {
35591
+ this._notifierService.showSuccess(`Chuyển đổi tài liệu ${file.name} thành pdf thành công`);
35592
+ sourceFileId = rsConvert.data;
35593
+ sourceFile = { id: sourceFileId };
35594
+ this.getServiceFile();
35595
+ }
35596
+ }
35597
+ catch (e) {
35598
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
35599
+ return;
35600
+ }
35601
+ }
35602
+ this._fileExplorerService.generateLinkDownload({
35603
+ fileId: sourceFileId,
35604
+ }).then(rs => {
35605
+ const url = this._downloadLinkService.getDownloadForSignUrl(rs.data);
35606
+ const prms = {};
35607
+ prms['FileUploadHandler'] = `${this._moduleConfig.environment.apiDomain.fileEndpoint}/${this._moduleConfig.environment.apiVersion}/KySoFile/SavePhysicalSignedFile`;
35608
+ prms['SessionId'] = '';
35609
+ prms['FileName'] = url;
35610
+ // tslint:disable-next-line: variable-name
35611
+ const json_prms = JSON.stringify(prms);
35612
+ vgca_sign_approved(json_prms, (result) => {
35613
+ const resultObj = JSON.parse(result);
35614
+ if (resultObj.FileServer != '') {
35615
+ this._fileExplorerService.saveSignedFile({
35616
+ sourceFile: sourceFile,
35617
+ tempFileId: resultObj.FileServer,
35618
+ }).then(rss => {
35619
+ this.getServiceFile();
35620
+ this._notifierService.showSuccess('Ký số thành công');
35621
+ });
35622
+ }
35623
+ });
35624
+ });
35625
+ }
35626
+ }));
35627
+ }
35628
+ signVNPTCA(item) {
35629
+ var _a;
35630
+ return __awaiter(this, void 0, void 0, function* () {
35631
+ let sourceFileId = item.id;
35632
+ if (this._fileExplorerService.needConvertBeforeSign(item.name)) {
35633
+ // convert file before sign
35634
+ try {
35635
+ const rsConvert = yield this._fileExplorerService.convertDocumentToPdfAndSave({
35636
+ instanceId: item.id,
35637
+ name: this._fileExplorerService.changeFileExtension(item.name, 'pdf'),
35638
+ folderInstanceId: (_a = item.parentFolderId) !== null && _a !== void 0 ? _a : this._commonService.guid(),
35639
+ ownerType: this._userService.getCurrentUser().userId.toString(),
35640
+ });
35641
+ if (!rsConvert || !rsConvert.success) {
35642
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${item.name} thành pdf để ký. Vui lòng thử lại sau`);
35643
+ return;
35644
+ }
35645
+ else {
35646
+ this._notifierService.showSuccess(`Chuyển đổi tài liệu ${item.name} thành pdf thành công`);
35647
+ sourceFileId = rsConvert.data;
35648
+ this.model.selectedItem.id = rsConvert.data;
35649
+ this.getServiceFile();
35650
+ }
35651
+ }
35652
+ catch (e) {
35653
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${item.name} thành pdf để ký. Vui lòng thử lại sau`);
35654
+ return;
35655
+ }
35656
+ }
35657
+ const dataInput = (yield this._fileExplorerService.getBase64FromFileId(sourceFileId)).split(',')[1];
35658
+ const sigOptions = new PdfSigner();
35659
+ sigOptions.page = 1;
35660
+ sigOptions.AdvancedCustom = true;
35661
+ sigOptions.SigType = 1;
35662
+ const dataJS = {
35663
+ data: dataInput,
35664
+ type: 'pdf',
35665
+ sigOptions: JSON.stringify(sigOptions)
35666
+ };
35667
+ try {
35668
+ const data = yield vnpt_plugin.signArrDataAdvanced([JSON.stringify(dataJS)], "", false);
35669
+ this.handeResult(data);
35670
+ }
35671
+ catch (e) {
35672
+ console.log(e);
35673
+ }
35674
+ });
35675
+ }
35676
+ handeResult(data) {
35677
+ if (typeof JSON.parse(data).code !== 'undefined') {
35678
+ var jsOb = JSON.parse(data);
35679
+ }
35680
+ else {
35681
+ var jsOb = JSON.parse(JSON.parse(data)[0]);
35682
+ }
35683
+ switch (jsOb.code) {
35684
+ case 0:
35685
+ this._fileExplorerService.kySimSaveSignedFile({
35686
+ sourceFile: this.model.selectedItem,
35687
+ fileContents: jsOb.data,
35688
+ }).then((rss) => {
35689
+ this._notifierService.showSuccess("Ký thành công");
35690
+ this.getServiceFile();
35691
+ });
35692
+ break;
35693
+ case 1:
35694
+ this._notifierService.showWarning("Dữ liệu đầu vào không đúng định dạng");
35695
+ break;
35696
+ case 2:
35697
+ this._notifierService.showWarning("Không lấy được thông tin chứng thư số");
35698
+ break;
35699
+ case 3:
35700
+ this._notifierService.showWarning("Có lỗi trong quá trình ký số");
35701
+ break;
35702
+ case 4:
35703
+ this._notifierService.showSuccess("Chứng thư số không có khóa bí mật");
35704
+ break;
35705
+ case 5:
35706
+ this._notifierService.showSuccess("Lỗi không xác định");
35707
+ break;
35708
+ case 6:
35709
+ this._notifierService.showSuccess("Ký pdf: không tìm thấy tham số số trang cần ký");
35710
+ break;
35711
+ case 7:
35712
+ this._notifierService.showSuccess("Ký pdf: trang đặt chữ ký không tồn tại");
35713
+ break;
35714
+ case 8:
35715
+ this._notifierService.showSuccess("Ký xml: không tìm thấy thẻ ký số");
35716
+ break;
35717
+ case 9:
35718
+ this._notifierService.showSuccess("Ký pdf: không tìm thấy id của thẻ ký số");
35719
+ break;
35720
+ case 10:
35721
+ this._notifierService.showSuccess("Dữ liệu ký đã chứa một hoặc nhiều chữ ký không hợp lệ");
35722
+ break;
35723
+ case 11:
35724
+ this._notifierService.showSuccess("Người dùng hủy bỏ");
35725
+ break;
35726
+ case 13:
35727
+ this._notifierService.showWarning("Dữ liệu ký rỗng");
35728
+ break;
35729
+ default:
35730
+ this._notifierService.showSuccess("Lỗi không xác định");
35731
+ break;
35732
+ }
35733
+ }
35734
+ addComment(file) {
35735
+ this._notifierService.showConfirm('Bạn có chắc chắn muốn bút phê văn bản này?').then((rs) => __awaiter(this, void 0, void 0, function* () {
35736
+ if (rs) {
35737
+ let sourceFileId = file.id;
35738
+ let sourceFile = file;
35739
+ // Ký số file word - cần convert sang pdf trước
35740
+ if (this._fileExplorerService.needConvertBeforeSign(file.name)) {
35741
+ // convert file before sign
35742
+ try {
35743
+ const rsConvert = yield this._fileExplorerService.convertDocumentToPdfAndSave({
35744
+ instanceId: sourceFileId,
35745
+ name: this._fileExplorerService.changeFileExtension(file.name, 'pdf'),
35746
+ folderInstanceId: file.parentFolderId,
35747
+ ownerType: this._userService.getCurrentUser().userId.toString(),
35748
+ });
35749
+ if (!rsConvert || !rsConvert.success) {
35750
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
35751
+ return;
35752
+ }
35753
+ else {
35754
+ this._notifierService.showSuccess(`Chuyển đổi tài liệu ${file.name} thành pdf thành công`);
35755
+ sourceFileId = rsConvert.data;
35756
+ sourceFile = { id: sourceFileId };
35757
+ this.getServiceFile();
35758
+ }
35759
+ }
35760
+ catch (e) {
35761
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
35762
+ return;
35763
+ }
35764
+ }
35765
+ this._fileExplorerService.generateLinkDownload({
35766
+ fileId: sourceFileId,
35767
+ }).then(rs => {
35768
+ const url = this._downloadLinkService.getDownloadForSignUrl(rs.data);
35769
+ const prms = {};
35770
+ prms['FileUploadHandler'] = `${this._moduleConfig.environment.apiDomain.fileEndpoint}/${this._moduleConfig.environment.apiVersion}/KySoFile/SavePhysicalSignedFile`;
35771
+ prms['SessionId'] = '';
35772
+ prms['FileName'] = url;
35773
+ // tslint:disable-next-line: variable-name
35774
+ const json_prms = JSON.stringify(prms);
35775
+ vgca_comment(json_prms, (result) => {
35776
+ const resultObj = JSON.parse(result);
35777
+ if (resultObj.FileServer != '') {
35778
+ this._fileExplorerService.saveSignedFile({
35779
+ sourceFile: sourceFile,
35780
+ tempFileId: resultObj.FileServer,
35781
+ }).then(rss => {
35782
+ this.getServiceFile();
35783
+ this._notifierService.showSuccess('Tạo bút phê thành công');
35784
+ });
35785
+ }
35786
+ });
35787
+ });
35788
+ }
35789
+ }));
35790
+ }
35791
+ addCommentAndSign(file) {
35792
+ return __awaiter(this, void 0, void 0, function* () {
35793
+ const rs = yield this._notifierService.showConfirm('Bạn có chắc chắn muốn tạo bút phê và ký văn bản này?');
35794
+ if (rs) {
35795
+ let sourceFileId = file.id;
35796
+ let sourceFile = file;
35797
+ // Ký số file word - cần convert sang pdf trước
35798
+ if (this._fileExplorerService.needConvertBeforeSign(file.name)) {
35799
+ // convert file before sign
35800
+ try {
35801
+ const rsConvert = yield this._fileExplorerService.convertDocumentToPdfAndSave({
35802
+ instanceId: sourceFileId,
35803
+ name: this._fileExplorerService.changeFileExtension(file.name, 'pdf'),
35804
+ folderInstanceId: file.parentFolderId,
35805
+ ownerType: this._userService.getCurrentUser().userId.toString(),
35806
+ });
35807
+ if (!rsConvert || !rsConvert.success) {
35808
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
35809
+ return;
35810
+ }
35811
+ else {
35812
+ this._notifierService.showSuccess(`Chuyển đổi tài liệu ${file.name} thành pdf thành công`);
35813
+ sourceFileId = rsConvert.data;
35814
+ sourceFile = { id: sourceFileId };
35815
+ this.getServiceFile();
35816
+ }
35817
+ }
35818
+ catch (e) {
35819
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
35820
+ return;
35821
+ }
35822
+ }
35823
+ const downloadLink = yield this._fileExplorerService.generateLinkDownload({
35824
+ fileId: sourceFileId,
35825
+ });
35826
+ const url = this._downloadLinkService.getDownloadForSignUrl(downloadLink.data);
35827
+ const prms = {
35828
+ FileUploadHandler: `${this._moduleConfig.environment.apiDomain.fileEndpoint}/${this._moduleConfig.environment.apiVersion}/KySoFile/SavePhysicalSignedFile`,
35829
+ SessionId: '',
35830
+ FileName: url
35831
+ };
35832
+ const json_prms = JSON.stringify(prms);
35833
+ // Wrap callback-based functions in Promises
35834
+ const commentResult = yield new Promise((resolve) => {
35835
+ vgca_comment(json_prms, (result) => resolve(result));
35836
+ });
35837
+ const resultObj = JSON.parse(commentResult);
35838
+ const downloadLink2 = yield this._fileExplorerService.generateLinkDownload({
35839
+ fileId: resultObj.FileServer,
35840
+ });
35841
+ const url2 = this._downloadLinkService.getDownloadForSignUrl(downloadLink2.data);
35842
+ const prms2 = {
35843
+ FileUploadHandler: `${this._moduleConfig.environment.apiDomain.fileEndpoint}/${this._moduleConfig.environment.apiVersion}/KySoFile/SavePhysicalSignedFile`,
35844
+ SessionId: '',
35845
+ FileName: url2
35846
+ };
35847
+ const json_prms2 = JSON.stringify(prms2);
35848
+ const signResult = yield new Promise((resolve) => {
35849
+ vgca_sign_approved(json_prms2, (result) => resolve(result));
35850
+ });
35851
+ const signResultObj = JSON.parse(signResult);
35852
+ if (signResultObj.FileServer != '') {
35853
+ yield this._fileExplorerService.saveSignedFile({
35854
+ sourceFile: sourceFile,
35855
+ tempFileId: signResultObj.FileServer,
35856
+ });
35857
+ this.getServiceFile();
35858
+ this._notifierService.showSuccess('Tạo bút phê và ký thành công');
35859
+ }
35860
+ }
35861
+ });
35862
+ }
35863
+ signFileDonVi(file) {
35864
+ this._notifierService
35865
+ .showConfirm('Bạn có chắc chắn muốn ký số đơn vị văn bản này?')
35866
+ .then((rs) => __awaiter(this, void 0, void 0, function* () {
35867
+ if (rs) {
35868
+ let sourceFileId = file.id;
35869
+ let sourceFile = file;
35870
+ if (this._fileExplorerService.needConvertBeforeSign(file.name)) {
35871
+ // convert file before sign
35872
+ try {
35873
+ const rsConvert = yield this._fileExplorerService.convertDocumentToPdfAndSave({
35874
+ instanceId: sourceFileId,
35875
+ name: this._fileExplorerService.changeFileExtension(file.name, 'pdf'),
35876
+ folderInstanceId: file.parentFolderId,
35877
+ ownerType: this._userService.getCurrentUser().userId.toString(),
35878
+ });
35879
+ if (!rsConvert || !rsConvert.success) {
35880
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
35881
+ return;
35882
+ }
35883
+ else {
35884
+ this._notifierService.showSuccess(`Chuyển đổi tài liệu ${file.name} thành pdf thành công`);
35885
+ this.getServiceFile();
35886
+ sourceFileId = rsConvert.data;
35887
+ sourceFile = { id: sourceFileId };
35888
+ }
35889
+ }
35890
+ catch (e) {
35891
+ this._notifierService.showWarning(`Có lỗi xảy ra khi chuyển đổi tài liệu ${file.name} thành pdf để ký. Vui lòng thử lại sau`);
35892
+ return;
35893
+ }
35894
+ }
35895
+ this._fileExplorerService
35896
+ .generateLinkDownload({
35897
+ isFileVersion: false,
35898
+ fileId: sourceFileId,
35899
+ })
35900
+ .then((rs) => {
35901
+ const url = this._downloadLinkService.getDownloadForSignUrl(rs.data);
35902
+ const prms = {};
35903
+ prms['FileUploadHandler'] = `${this._moduleConfig.environment.apiDomain.fileEndpoint}/${this._moduleConfig.environment.apiVersion}/KySoFile/SavePhysicalSignedFile`;
35904
+ prms['SessionId'] = '';
35905
+ prms['FileName'] = url;
35906
+ // Truyền số, ngày ký số phòng ban nếu cần
35907
+ const that = this;
35908
+ if (that.control && that.control.dataKySoDonVi) {
35909
+ const dataKySoDonVi = that.control.dataKySoDonVi();
35910
+ if (dataKySoDonVi) {
35911
+ // lấy số DocNumber
35912
+ if (dataKySoDonVi.docNumber) {
35913
+ prms['DocNumber'] = dataKySoDonVi.docNumber;
35914
+ }
35915
+ // lấy ngày ban hành vb đi
35916
+ if (dataKySoDonVi.issuedDate) {
35917
+ prms['IssuedDate'] = dataKySoDonVi.issuedDate;
35918
+ }
35919
+ }
35920
+ }
35921
+ // tslint:disable-next-line: variable-name
35922
+ const json_prms = JSON.stringify(prms);
35923
+ vgca_sign_issued(json_prms, (result) => {
35924
+ const resultObj = JSON.parse(result);
35925
+ if (resultObj.FileServer != '') {
35926
+ this._fileExplorerService
35927
+ .saveSignedFile({
35928
+ sourceFile: sourceFile,
35929
+ tempFileId: resultObj.FileServer,
35930
+ })
35931
+ .then((rss) => {
35932
+ this.getServiceFile();
35933
+ this._notifierService.showSuccess('Ký số thành công');
35934
+ });
35935
+ }
35936
+ });
35937
+ });
35938
+ }
35939
+ }));
35940
+ }
34872
35941
  }
34873
35942
  ServiceFileUploadComponent.decorators = [
34874
35943
  { type: Component, args: [{
34875
35944
  selector: 'service-file-upload',
34876
- template: "<div class=\"file-upload\">\n <div class=\"fl-icon\">\n <i *ngIf=\"loading\" class=\"pi pi-spin pi-spinner\"></i>\n <i *ngIf=\"!loading\" class=\"pi pi-file-o\"></i>\n </div>\n\n <div class=\"fl-file-name\" (click)=\"openFileViewer()\">\n <div>\n <ng-container *ngIf=\"!showNoti\">\n <span pTooltip=\"{{selectedFileName}}\">{{selectedFileNameShort}}</span>\n <span class=\"suffix\" *ngIf=\"extension\">.{{extension}} </span>\n </ng-container>\n <span *ngIf=\"showNoti\"> {{notification}} </span>\n </div>\n </div>\n\n <!-- <div class=\"fl-file-name\">\n <div>\n <ng-container *ngIf=\"!showNoti\">\n <span pTooltip=\"{{selectedFileName}}\">{{selectedFileNameShort}}</span>\n <span *ngIf=\"extension\">.{{extension}} </span>\n </ng-container>\n <span *ngIf=\"showNoti\"> {{notification}} </span>\n </div>\n </div> -->\n\n <div class=\"fl-buttons\">\n <button *ngIf=\"!hasFile && !readonly\" pTooltip=\"Ch\u1ECDn file\" class=\"fl-choose\"\n class=\"link-or-action p-button-text p-button-rounded fl-choose\" tooltipPosition=\"top\" pButton type=\"button\"\n icon=\"pi pi-plus\" [disabled]=\"disabled\" (click)=\"onOpenSelect()\"></button>\n\n <button *ngIf=\"hasFile && !readonly && control.showDeleteFile\"\n class=\"link-or-action p-button-text p-button-rounded p-button-danger fl-remove\" pTooltip=\"X\u00F3a file\"\n tooltipPosition=\"top\" pButton type=\"button\" icon=\"pi pi-trash\" [disabled]=\"disabled\"\n (click)=\"onRemoveFile()\"></button>\n\n <button [disabled]=\"!menu || !menu.length\" type=\"button\" pButton icon=\"pi pi-ellipsis-v\"\n class=\"link-or-action p-button-text p-button-rounded\" pTooltip=\"Th\u00EAm\" tooltipPosition=\"top\"\n (click)=\"showContextMenu($event)\"></button>\n </div>\n\n <div style=\"display: none;\">\n <p-fileUpload #file [accept]=\"accept\" class=\"file-upload\" mode=\"basic\" [chooseLabel]=\"chooseLabel\" name=\"file[]\"\n [maxFileSize]=\"control.maxFileSize\" pTooltip=\"Ch\u1ECDn t\u1EEB m\u00E1y t\u00EDnh\" toolStipPosition=\"top\" [multiple]=\"false\"\n [invalidFileSizeMessageSummary]=\"control.invalidFileSizeMessageSummary\"\n [invalidFileSizeMessageDetail]=\"control.invalidFileSizeMessageDetail\"\n [invalidFileTypeMessageSummary]=\"control.invalidFileTypeMessageSummary\"\n [invalidFileTypeMessageDetail]=\"control.invalidFileTypeMessageDetail\"\n [invalidFileLimitMessageSummary]=\"control.invalidFileLimitMessageSummary\"\n [invalidFileLimitMessageDetail]=\"control.invalidFileLimitMessageDetail\" (onSelect)=\"onSelectFile($event)\">\n </p-fileUpload>\n </div>\n\n</div>\n\n<p-contextMenu #contextMenu [appendTo]=\"'body'\" [model]=\"menu\" styleClass=\"fm-contextMenu-panel\">\n</p-contextMenu>\n\n<!-- Xem file tr\u1EF1c tuy\u1EBFn -->\n<file-viewer #fileViewerNew *ngIf=\"forms.fileViewer.show\" [parentModel]=\"model\" [parentContext]=\"context\"\n [readonly]=\"readonly || control.disabled\" [model]=\"forms.fileViewer.formData\"\n (onClose)=\"this.forms.fileViewer.show = false;\">\n</file-viewer>",
35945
+ template: "<div class=\"file-upload\">\n <div class=\"fl-icon\">\n <i *ngIf=\"loading\" class=\"pi pi-spin pi-spinner\"></i>\n <i *ngIf=\"!loading\" class=\"pi pi-file-o\"></i>\n </div>\n\n <div class=\"fl-file-name\" (click)=\"openFileViewer()\">\n <div style=\"position: relative;\">\n <ng-container *ngIf=\"!showNoti\">\n <span pTooltip=\"{{selectedFileName}}\">{{selectedFileNameShort}}</span>\n <span class=\"suffix\" *ngIf=\"extension\">.{{extension}} </span>\n </ng-container>\n <span *ngIf=\"showNoti\"> {{notification}} </span>\n <span *ngIf=\"selectedFile?.signatures\" class=\"pull-right signature\" pTooltip=\"Xem chi ti\u1EBFt k\u00FD s\u1ED1\"\n tooltipPosition=\"top\" (click)=\"viewListSign($event, selectedFile.signatures)\">\n <i class=\"fas fa-signature\"></i>\n </span>\n </div>\n </div>\n\n <!-- <div class=\"fl-file-name\">\n <div>\n <ng-container *ngIf=\"!showNoti\">\n <span pTooltip=\"{{selectedFileName}}\">{{selectedFileNameShort}}</span>\n <span *ngIf=\"extension\">.{{extension}} </span>\n </ng-container>\n <span *ngIf=\"showNoti\"> {{notification}} </span>\n </div>\n </div> -->\n <div class=\"fl-buttons\">\n <button *ngIf=\"!hasFile && !readonly\" pTooltip=\"Ch\u1ECDn file\" class=\"fl-choose\"\n class=\"link-or-action p-button-text p-button-rounded fl-choose\" tooltipPosition=\"top\" pButton type=\"button\"\n icon=\"pi pi-plus\" [disabled]=\"disabled\" (click)=\"onOpenSelect()\"></button>\n\n <button *ngIf=\"hasFile && !readonly && control.showDeleteFile\"\n class=\"link-or-action p-button-text p-button-rounded p-button-danger fl-remove\" pTooltip=\"X\u00F3a file\"\n tooltipPosition=\"top\" pButton type=\"button\" icon=\"pi pi-trash\" [disabled]=\"disabled\"\n (click)=\"onRemoveFile()\"></button>\n\n <button [disabled]=\"!menu || !menu.length\" type=\"button\" pButton icon=\"pi pi-ellipsis-v\"\n class=\"link-or-action p-button-text p-button-rounded\" pTooltip=\"Th\u00EAm\" tooltipPosition=\"top\"\n (click)=\"showContextMenu($event)\"></button>\n </div>\n\n <div style=\"display: none;\">\n <p-fileUpload #file [accept]=\"accept\" class=\"file-upload\" mode=\"basic\" [chooseLabel]=\"chooseLabel\" name=\"file[]\"\n [maxFileSize]=\"control.maxFileSize\" pTooltip=\"Ch\u1ECDn t\u1EEB m\u00E1y t\u00EDnh\" toolStipPosition=\"top\" [multiple]=\"false\"\n [invalidFileSizeMessageSummary]=\"control.invalidFileSizeMessageSummary\"\n [invalidFileSizeMessageDetail]=\"control.invalidFileSizeMessageDetail\"\n [invalidFileTypeMessageSummary]=\"control.invalidFileTypeMessageSummary\"\n [invalidFileTypeMessageDetail]=\"control.invalidFileTypeMessageDetail\"\n [invalidFileLimitMessageSummary]=\"control.invalidFileLimitMessageSummary\"\n [invalidFileLimitMessageDetail]=\"control.invalidFileLimitMessageDetail\" (onSelect)=\"onSelectFile($event)\">\n </p-fileUpload>\n </div>\n</div>\n\n<p-contextMenu #contextMenu [appendTo]=\"'body'\" [model]=\"menu\" styleClass=\"fm-contextMenu-panel\">\n</p-contextMenu>\n\n<!-- Xem file tr\u1EF1c tuy\u1EBFn -->\n<file-viewer #fileViewerNew *ngIf=\"forms.fileViewer.show\" [parentModel]=\"model\" [parentContext]=\"context\"\n [readonly]=\"readonly || control.disabled\" [model]=\"forms.fileViewer.formData\"\n (onClose)=\"this.forms.fileViewer.show = false;\">\n</file-viewer>\n<tn-dialog *ngIf=\"forms.signatureDetail.show\" #dialog [styleClass]=\"'address-form'\"\n [header]=\"forms.signatureDetail.header | translate\" [popupSize]=\"forms[formIds.signatureDetail].popupSize\"\n (onHide)=\"forms.signatureDetail.show=false;\">\n <signature-detail [parentModel]=\"model\" [parentContext]=\"context\">\n </signature-detail>\n</tn-dialog>\n<tn-dialog *ngIf=\"signatureFormModel.show\" #dialog [styleClass]=\"'address-form'\" [header]=\"'Ch\u1ECDn ch\u1EEF k\u00FD s\u1ED1' | translate\"\n [popupSize]=\"signatureFormModel.popupSize\" (onHide)=\"signatureFormModel.show=false\">\n <signature-select #formBase [parentModel]=\"model\" [parentContext]=\"context\" [model]=\"signatureFormModel.formData\"\n (onCancel)=\"signatureFormModel.show = false\" (onSaved)=\"signFileSmartCA($event)\">\n </signature-select>\n</tn-dialog>",
34877
35946
  providers: [
34878
35947
  {
34879
35948
  provide: NG_VALUE_ACCESSOR,
@@ -34882,7 +35951,7 @@ ServiceFileUploadComponent.decorators = [
34882
35951
  },
34883
35952
  ComponentContextService
34884
35953
  ],
34885
- styles: ["::ng-deep .file-upload{display:flex;border:1px solid #ced4da;border-radius:4px}::ng-deep .file-upload .fl-icon{flex:0 0 30px;display:flex;font-size:20px;justify-content:center;align-items:center;border-right:1px solid #ced4da}::ng-deep .file-upload .fl-icon>i{font-size:16px!important}::ng-deep .file-upload .fl-file-name{display:flex;align-items:center;flex-grow:1;cursor:pointer;opacity:.8;padding:0 10px;color:#109bf8;overflow:hidden}::ng-deep .file-upload .fl-file-name>div{width:100%;display:flex}::ng-deep .file-upload .fl-file-name>div>span:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .file-upload .fl-file-name:hover{opacity:1}::ng-deep .file-upload .fl-file-name .suffix{min-width:45px}::ng-deep .file-upload .fl-buttons{flex:0 0 80px;display:flex;border-right:1px solid #ced4da;align-items:center;justify-content:space-evenly;border-left:1px solid #ced4da}"]
35954
+ styles: ["::ng-deep .file-upload{display:flex;border:1px solid #ced4da;border-radius:4px}::ng-deep .file-upload .fl-icon{flex:0 0 30px;display:flex;font-size:20px;justify-content:center;align-items:center;border-right:1px solid #ced4da}::ng-deep .file-upload .fl-icon>i{font-size:16px!important}::ng-deep .file-upload .fl-file-name{display:flex;align-items:center;flex-grow:1;cursor:pointer;opacity:.8;padding:0 10px;color:#109bf8;overflow:hidden}::ng-deep .file-upload .fl-file-name>div{width:100%;display:flex}::ng-deep .file-upload .fl-file-name>div>span:first-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .file-upload .fl-file-name:hover{opacity:1}::ng-deep .file-upload .fl-file-name .suffix{min-width:45px}::ng-deep .file-upload .fl-buttons{flex:0 0 80px;display:flex;border-right:1px solid #ced4da;align-items:center;justify-content:space-evenly;border-left:1px solid #ced4da}::ng-deep .file-upload .nfl-signature{display:flex;align-items:center;justify-content:center;cursor:pointer;opacity:.8;padding:0 10px;color:#109bf8;overflow:hidden}::ng-deep .file-upload .nfl-signature:hover{opacity:1}::ng-deep .file-upload .signature i{position:absolute;top:0;right:0}"]
34886
35955
  },] }
34887
35956
  ];
34888
35957
  ServiceFileUploadComponent.ctorParameters = () => [
@@ -34895,6 +35964,7 @@ ServiceFileUploadComponent.ctorParameters = () => [
34895
35964
  { type: NotifierService },
34896
35965
  { type: DownloadLinkService },
34897
35966
  { type: FileExplorerService },
35967
+ { type: DeviceDetectorService },
34898
35968
  { type: Injector }
34899
35969
  ];
34900
35970
  ServiceFileUploadComponent.propDecorators = {
@@ -34908,6 +35978,7 @@ ServiceFileUploadComponent.propDecorators = {
34908
35978
  entity: [{ type: Input }],
34909
35979
  entityKey: [{ type: Input }],
34910
35980
  chooseLabel: [{ type: Input }],
35981
+ parentSetting: [{ type: Input }],
34911
35982
  onInit: [{ type: Output }],
34912
35983
  onSelect: [{ type: Output }],
34913
35984
  onRemove: [{ type: Output }],
@@ -39650,13 +40721,13 @@ class UserPickerSetting {
39650
40721
  }
39651
40722
  }
39652
40723
  const DatasourceFieldFilter = [
39653
- { id: 'userName', ten: 'Tài khoản' },
39654
- { id: 'code', ten: 'Mã' },
39655
- { id: 'email', ten: 'Email' },
40724
+ { id: 'userName', ten: 'Tài khoản', placeholder: 'thuan.pd\nvan.nbt' },
40725
+ { id: 'code', ten: 'Mã cán bộ', placeholder: '00000408\n00014270' },
40726
+ { id: 'email', ten: 'Email', placeholder: 'linh123@gmail.com\ntnam123@gmail.com' },
39656
40727
  ];
39657
40728
  const DatasourceFilterCanBo = [
39658
- { id: 'code', ten: 'Mã' },
39659
- { id: 'email', ten: 'Email' }
40729
+ { id: 'code', ten: 'Mã cán bộ', placeholder: '00000408\n00014270' },
40730
+ { id: 'email', ten: 'Email', placeholder: 'linh123@gmail.com\ntnam123@gmail.com' },
39660
40731
  ];
39661
40732
 
39662
40733
  class EntityPickerDataComponent extends DataListBase {
@@ -39681,7 +40752,7 @@ class EntityPickerDataComponent extends DataListBase {
39681
40752
  this._triggerProcessData();
39682
40753
  }
39683
40754
  ngOnInit() {
39684
- var _a;
40755
+ var _a, _b;
39685
40756
  this.loadDetailFromQueryParam = true;
39686
40757
  this.plusUrl = this.control.plusUrl;
39687
40758
  this.setting.hiddenAuthorizeButton = true;
@@ -39705,6 +40776,9 @@ class EntityPickerDataComponent extends DataListBase {
39705
40776
  if (this.control.baseService instanceof CanBoHoSoService) {
39706
40777
  this.datasourceFieldFilter = DatasourceFilterCanBo;
39707
40778
  }
40779
+ if ((_b = this.control.datasourceFieldFilter) === null || _b === void 0 ? void 0 : _b.length) {
40780
+ this.datasourceFieldFilter = this.control.datasourceFieldFilter;
40781
+ }
39708
40782
  this.control.columns.forEach(column => {
39709
40783
  if (column.isDisplay) {
39710
40784
  const newCol = new ColumnSchemaBase({
@@ -42318,8 +43392,8 @@ class EntityPickerSearchFormComponent extends DataFormBase {
42318
43392
  mdWidth: 12,
42319
43393
  hidden: !this.datasourceFieldFilter.length,
42320
43394
  onChanged: (evt) => {
42321
- const plusPlaceholder = evt.parentModel.fieldFilter == 'email' ? '@gmail.com' : '';
42322
- evt.formControls['lstDataCheck'].placeholder = `linh123${plusPlaceholder}\nnam123${plusPlaceholder}`;
43395
+ var _a;
43396
+ evt.formControls['lstDataCheck'].placeholder = (_a = this.datasourceFieldFilter.find(p => p.id == evt.parentModel.fieldFilter)) === null || _a === void 0 ? void 0 : _a.placeholder;
42323
43397
  }
42324
43398
  }),
42325
43399
  new TextAreaControlSchema({
@@ -42349,6 +43423,7 @@ class EntityPickerSearchFormComponent extends DataFormBase {
42349
43423
  return __awaiter(this, void 0, void 0, function* () {
42350
43424
  if (this.datasourceFieldFilter.length) {
42351
43425
  evt.rootModel.fieldFilter = this.datasourceFieldFilter[0].id;
43426
+ evt.formControls['lstDataCheck'].placeholder = this.datasourceFieldFilter[0].placeholder;
42352
43427
  }
42353
43428
  evt.rootModel.lstDataCheck = undefined;
42354
43429
  evt.rootModel.lstDataNotExist = undefined;
@@ -43108,6 +44183,14 @@ class EntityPickerComponent extends DataListBase {
43108
44183
  setDisabledState(isDisabled) {
43109
44184
  this.disabled = isDisabled;
43110
44185
  }
44186
+ _view(rowData) {
44187
+ return __awaiter(this, void 0, void 0, function* () {
44188
+ if (this.control.onViewDetail) {
44189
+ yield this.control.onViewDetail(rowData);
44190
+ return;
44191
+ }
44192
+ });
44193
+ }
43111
44194
  }
43112
44195
  EntityPickerComponent.decorators = [
43113
44196
  { type: Component, args: [{
@@ -48682,11 +49765,13 @@ CoCauToChucTestService.ctorParameters = () => [
48682
49765
  ];
48683
49766
 
48684
49767
  class UserPickerBoxComponent extends ComponentBase {
48685
- constructor(_injector, _userV5Service, _organizationService, _coCauToChucService) {
49768
+ constructor(_injector, _userV5Service, _organizationService, _coCauToChucService, _moduleConfigService) {
49769
+ var _a, _b, _c;
48686
49770
  super(_injector);
48687
49771
  this._userV5Service = _userV5Service;
48688
49772
  this._organizationService = _organizationService;
48689
49773
  this._coCauToChucService = _coCauToChucService;
49774
+ this._moduleConfigService = _moduleConfigService;
48690
49775
  this.multiple = false;
48691
49776
  this.disabled = false;
48692
49777
  this.enableCaching = true;
@@ -48715,6 +49800,10 @@ class UserPickerBoxComponent extends ComponentBase {
48715
49800
  this.rootFilter = {};
48716
49801
  this.treeLoading = false;
48717
49802
  this.datasourceFieldFilter = DatasourceFieldFilter;
49803
+ const _environment = _moduleConfigService.getConfig().environment;
49804
+ if (((_b = (_a = _environment.cauHinhNghiepVu) === null || _a === void 0 ? void 0 : _a.datasourceFieldFilterCanBo) === null || _b === void 0 ? void 0 : _b.length) > 0) {
49805
+ this.datasourceFieldFilter = (_c = _environment.cauHinhNghiepVu) === null || _c === void 0 ? void 0 : _c.datasourceFieldFilterCanBo;
49806
+ }
48718
49807
  }
48719
49808
  ngOnInit() {
48720
49809
  this.control.plusUrl = 'ForUserPicker';
@@ -48860,7 +49949,8 @@ UserPickerBoxComponent.ctorParameters = () => [
48860
49949
  { type: Injector },
48861
49950
  { type: UserV5Service },
48862
49951
  { type: OrganizationService },
48863
- { type: CoCauToChucTestService }
49952
+ { type: CoCauToChucTestService },
49953
+ { type: ModuleConfigService }
48864
49954
  ];
48865
49955
  UserPickerBoxComponent.propDecorators = {
48866
49956
  multiple: [{ type: Input }],
@@ -50357,6 +51447,7 @@ FileSizePipe.decorators = [
50357
51447
 
50358
51448
  // 1
50359
51449
  // 2
51450
+ // 3
50360
51451
  function coreDeclaration() {
50361
51452
  return [
50362
51453
  AddressComponent,