@myrtex-org/form 1.1.26 → 1.1.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/modules/object-form/components/elements/base/base-field/base-field.component.mjs +8 -2
- package/esm2022/lib/modules/object-form/components/elements/input/number/input-number.component.mjs +9 -3
- package/esm2022/lib/modules/object-form/components/elements/input/table/components/input-table-modal/input-table-modal.component.mjs +51 -6
- package/esm2022/lib/modules/object-form/components/elements/input/table/input-table.component.mjs +2 -20
- package/esm2022/lib/modules/object-form/factories/component-factory/component-factory.directive.mjs +23 -32
- package/esm2022/lib/modules/object-form/services/formula-calculate.service.mjs +180 -0
- package/esm2022/lib/modules/object-form/services/index.mjs +2 -1
- package/fesm2022/myrtex-org-form.mjs +263 -56
- package/fesm2022/myrtex-org-form.mjs.map +1 -1
- package/lib/modules/object-form/components/elements/input/number/input-number.component.d.ts +2 -0
- package/lib/modules/object-form/components/elements/input/table/components/input-table-modal/input-table-modal.component.d.ts +5 -1
- package/lib/modules/object-form/components/elements/input/table/input-table.component.d.ts +2 -2
- package/lib/modules/object-form/factories/component-factory/component-factory.directive.d.ts +2 -3
- package/lib/modules/object-form/services/formula-calculate.service.d.ts +19 -0
- package/lib/modules/object-form/services/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, inject,
|
|
2
|
+
import { Injectable, inject, ChangeDetectionStrategy, Component, EventEmitter, Output, Input, Directive, ChangeDetectorRef, Inject, ViewChild, NgModule } from '@angular/core';
|
|
3
3
|
import * as i1$3 from '@angular/common';
|
|
4
4
|
import { CommonModule } from '@angular/common';
|
|
5
5
|
import * as i1$1 from '@angular/router';
|
|
@@ -863,6 +863,184 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
863
863
|
type: Injectable
|
|
864
864
|
}] });
|
|
865
865
|
|
|
866
|
+
class FormulaCalculateService {
|
|
867
|
+
constructor() {
|
|
868
|
+
this._operatorPrecedence = {
|
|
869
|
+
'+': 1,
|
|
870
|
+
'-': 1,
|
|
871
|
+
'*': 2,
|
|
872
|
+
'/': 2,
|
|
873
|
+
};
|
|
874
|
+
this._operators = ['+', '-', '*', '/'];
|
|
875
|
+
}
|
|
876
|
+
calculateMathExpression(expression, values) {
|
|
877
|
+
try {
|
|
878
|
+
return this._calculateMathExpression(expression, values);
|
|
879
|
+
}
|
|
880
|
+
catch {
|
|
881
|
+
return 0;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
calculateStringConcatenation(expression, values) {
|
|
885
|
+
return expression.replace(/{(?<systemName>\w+)(?::(?<format>[^}]+))?}/g, (_match, systemName) => {
|
|
886
|
+
const value = values.find(x => x.sysName === systemName);
|
|
887
|
+
return value?.value?.toString?.() ?? '';
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
_calculateMathExpression(expression, values) {
|
|
891
|
+
const operatorStack = [];
|
|
892
|
+
const operandStack = [];
|
|
893
|
+
for (let i = 0; i < expression.length; i++) {
|
|
894
|
+
const charValue = expression[i];
|
|
895
|
+
if (/\s/.test(charValue)) {
|
|
896
|
+
continue;
|
|
897
|
+
}
|
|
898
|
+
if (charValue === '{') {
|
|
899
|
+
let sysNameOperand = '';
|
|
900
|
+
while (i < expression.length && expression[i] !== '}') {
|
|
901
|
+
sysNameOperand += expression[i];
|
|
902
|
+
i++;
|
|
903
|
+
}
|
|
904
|
+
sysNameOperand += expression[i] ?? '';
|
|
905
|
+
const value = this._getNumberValue(values, sysNameOperand);
|
|
906
|
+
if (value === null) {
|
|
907
|
+
return 0;
|
|
908
|
+
}
|
|
909
|
+
operandStack.push(value);
|
|
910
|
+
continue;
|
|
911
|
+
}
|
|
912
|
+
if (charValue === '(') {
|
|
913
|
+
const nestedExpression = this._getExpressionBetweenParentheses(expression, i);
|
|
914
|
+
operandStack.push(this._calculateMathExpression(nestedExpression, values));
|
|
915
|
+
i += nestedExpression.length + 1;
|
|
916
|
+
continue;
|
|
917
|
+
}
|
|
918
|
+
if (this._isOperator(charValue)) {
|
|
919
|
+
this._addOperator(operatorStack, operandStack, charValue);
|
|
920
|
+
continue;
|
|
921
|
+
}
|
|
922
|
+
if (/\d/.test(charValue)) {
|
|
923
|
+
let number = '';
|
|
924
|
+
while (i < expression.length && (/[\d.]/.test(expression[i]))) {
|
|
925
|
+
number += expression[i];
|
|
926
|
+
i++;
|
|
927
|
+
}
|
|
928
|
+
i--;
|
|
929
|
+
const value = this._getNumberValue(values, number);
|
|
930
|
+
if (value === null) {
|
|
931
|
+
return 0;
|
|
932
|
+
}
|
|
933
|
+
operandStack.push(value);
|
|
934
|
+
continue;
|
|
935
|
+
}
|
|
936
|
+
if (/[a-zA-Z]/.test(charValue)) {
|
|
937
|
+
i += this._addFunctionResult(operandStack, values, expression, i);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
this._calculateAll(operandStack, operatorStack);
|
|
941
|
+
return operandStack.pop() ?? 0;
|
|
942
|
+
}
|
|
943
|
+
_addFunctionResult(operandStack, values, expression, startIndex) {
|
|
944
|
+
const idxEof = expression.indexOf(')', startIndex);
|
|
945
|
+
const operand = expression.substring(startIndex, idxEof - startIndex + 1);
|
|
946
|
+
const lowerOperand = operand.toLowerCase();
|
|
947
|
+
if (lowerOperand.startsWith('pow(') && lowerOperand.endsWith(')')) {
|
|
948
|
+
const innerExpression = operand.substring(4, operand.length - 1);
|
|
949
|
+
const innerOperands = innerExpression.split(',').map(x => x.trim());
|
|
950
|
+
const baseValue = this._getNumberValue(values, innerOperands[0]);
|
|
951
|
+
const exponent = this._getNumberValue(values, innerOperands[1]);
|
|
952
|
+
if (baseValue === null || exponent === null) {
|
|
953
|
+
operandStack.push(0);
|
|
954
|
+
}
|
|
955
|
+
else {
|
|
956
|
+
operandStack.push(Math.pow(baseValue, exponent));
|
|
957
|
+
}
|
|
958
|
+
return operand.length - 1;
|
|
959
|
+
}
|
|
960
|
+
if (lowerOperand.startsWith('sqrt(') && lowerOperand.endsWith(')')) {
|
|
961
|
+
const innerExpression = operand.substring(5, operand.length - 1);
|
|
962
|
+
const value = this._getNumberValue(values, innerExpression);
|
|
963
|
+
operandStack.push(value === null ? 0 : Math.sqrt(value));
|
|
964
|
+
return operand.length - 1;
|
|
965
|
+
}
|
|
966
|
+
throw new Error('Invalid function operand');
|
|
967
|
+
}
|
|
968
|
+
_addOperator(operatorStack, operandStack, operatorToken) {
|
|
969
|
+
while (operatorStack.length > 0 &&
|
|
970
|
+
this._getOperatorPrecedence(operatorToken) <= this._getOperatorPrecedence(operatorStack[operatorStack.length - 1])) {
|
|
971
|
+
const operand2 = operandStack.pop() ?? 0;
|
|
972
|
+
const operand1 = operandStack.pop() ?? 0;
|
|
973
|
+
const operatorTokenToApply = operatorStack.pop();
|
|
974
|
+
operandStack.push(this._calculate(operand1, operand2, operatorTokenToApply));
|
|
975
|
+
}
|
|
976
|
+
operatorStack.push(operatorToken);
|
|
977
|
+
}
|
|
978
|
+
_calculateAll(operandStack, operatorStack) {
|
|
979
|
+
while (operatorStack.length > 0) {
|
|
980
|
+
const operatorToken = operatorStack.pop();
|
|
981
|
+
const operand2 = operandStack.pop() ?? 0;
|
|
982
|
+
const operand1 = operandStack.pop() ?? 0;
|
|
983
|
+
operandStack.push(this._calculate(operand1, operand2, operatorToken));
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
_getOperatorPrecedence(operatorToken) {
|
|
987
|
+
return this._operatorPrecedence[operatorToken];
|
|
988
|
+
}
|
|
989
|
+
_getExpressionBetweenParentheses(expression, startIndex) {
|
|
990
|
+
let level = 0;
|
|
991
|
+
for (let i = startIndex; i < expression.length; i++) {
|
|
992
|
+
if (expression[i] === '(') {
|
|
993
|
+
level++;
|
|
994
|
+
}
|
|
995
|
+
else if (expression[i] === ')') {
|
|
996
|
+
level--;
|
|
997
|
+
if (level === 0) {
|
|
998
|
+
return expression.substring(startIndex + 1, i);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
throw new Error('Unbalanced parentheses');
|
|
1003
|
+
}
|
|
1004
|
+
_getNumberValue(values, operand) {
|
|
1005
|
+
const cleanOperand = operand.trim().replace(',', '.').replace(/^\{|\}$/g, '');
|
|
1006
|
+
const val = values.find(x => x.sysName === cleanOperand);
|
|
1007
|
+
if (val) {
|
|
1008
|
+
if (val.value === null || val.value === undefined || val.value === '') {
|
|
1009
|
+
return null;
|
|
1010
|
+
}
|
|
1011
|
+
const parsed = Number(String(val.value).replace(',', '.'));
|
|
1012
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
1013
|
+
}
|
|
1014
|
+
const asNumber = Number(cleanOperand);
|
|
1015
|
+
if (Number.isFinite(asNumber)) {
|
|
1016
|
+
return asNumber;
|
|
1017
|
+
}
|
|
1018
|
+
throw new Error(`Invalid operand ${operand}`);
|
|
1019
|
+
}
|
|
1020
|
+
_calculate(operand1, operand2, operatorToken) {
|
|
1021
|
+
switch (operatorToken) {
|
|
1022
|
+
case '+':
|
|
1023
|
+
return operand1 + operand2;
|
|
1024
|
+
case '-':
|
|
1025
|
+
return operand1 - operand2;
|
|
1026
|
+
case '*':
|
|
1027
|
+
return operand1 * operand2;
|
|
1028
|
+
case '/':
|
|
1029
|
+
return operand1 / operand2;
|
|
1030
|
+
default:
|
|
1031
|
+
throw new Error(`Invalid operator ${operatorToken}`);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
_isOperator(token) {
|
|
1035
|
+
return this._operators.includes(token);
|
|
1036
|
+
}
|
|
1037
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FormulaCalculateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1038
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FormulaCalculateService }); }
|
|
1039
|
+
}
|
|
1040
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FormulaCalculateService, decorators: [{
|
|
1041
|
+
type: Injectable
|
|
1042
|
+
}] });
|
|
1043
|
+
|
|
866
1044
|
class ObjectFormEffects {
|
|
867
1045
|
constructor(_actions$, _store, _router, _applicationService, _toasterService) {
|
|
868
1046
|
this._actions$ = _actions$;
|
|
@@ -1041,48 +1219,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
1041
1219
|
}], ctorParameters: () => [{ type: i1$1.Router }] });
|
|
1042
1220
|
|
|
1043
1221
|
class ComponentFactoryDirective {
|
|
1044
|
-
constructor(viewContainer
|
|
1222
|
+
constructor(viewContainer) {
|
|
1045
1223
|
this.viewContainer = viewContainer;
|
|
1046
|
-
this.cdr = cdr;
|
|
1047
1224
|
this.values = [];
|
|
1048
1225
|
this.changed = new EventEmitter();
|
|
1049
1226
|
}
|
|
1050
1227
|
ngOnChanges(changes) {
|
|
1051
|
-
|
|
1052
|
-
if ('type' in changes && this.type) {
|
|
1228
|
+
if ('type' in changes && this.type && changes['type'].previousValue !== changes['type'].currentValue) {
|
|
1053
1229
|
this.initWidget(this.type);
|
|
1054
1230
|
}
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
// Используем currentValue из changes, чтобы быть уверенными в свежести данных
|
|
1064
|
-
if ('values' in changes) {
|
|
1065
|
-
this.dynamicComponent.instance.values = changes['values'].currentValue;
|
|
1066
|
-
}
|
|
1067
|
-
// КРИТИЧНО: уведомляем Angular, что в динамическом компоненте обновились данные
|
|
1068
|
-
this.dynamicComponent.changeDetectorRef.detectChanges();
|
|
1231
|
+
if ('data' in changes && this.data) {
|
|
1232
|
+
this.applyData(this.data);
|
|
1233
|
+
}
|
|
1234
|
+
if ('valueMode' in changes && this.data && this.valueMode) {
|
|
1235
|
+
this.applyValueMode(this.valueMode);
|
|
1236
|
+
}
|
|
1237
|
+
if ('values' in changes && this.data) {
|
|
1238
|
+
this.applyValues(this.values);
|
|
1069
1239
|
}
|
|
1070
1240
|
}
|
|
1071
1241
|
initWidget(type) {
|
|
1072
1242
|
const componentType = this.map[type];
|
|
1073
|
-
if (!componentType)
|
|
1243
|
+
if (!componentType) {
|
|
1074
1244
|
return;
|
|
1075
|
-
|
|
1245
|
+
}
|
|
1246
|
+
if (this.dynamicComponent) {
|
|
1247
|
+
this.viewContainer.clear();
|
|
1248
|
+
this.dynamicComponent = undefined;
|
|
1249
|
+
}
|
|
1076
1250
|
this.dynamicComponent = this.viewContainer.createComponent(componentType);
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
if (this.values)
|
|
1082
|
-
instance.values = this.values;
|
|
1083
|
-
if (this.valueMode)
|
|
1084
|
-
instance.valueMode = this.valueMode;
|
|
1085
|
-
if (this.dynamicComponent && this.dynamicComponent.instance.changed) {
|
|
1251
|
+
if (this.data) {
|
|
1252
|
+
this.dynamicComponent.instance.data = this.data;
|
|
1253
|
+
}
|
|
1254
|
+
if (this.dynamicComponent.instance.changed) {
|
|
1086
1255
|
this.dynamicComponent.instance.changed.subscribe((res) => {
|
|
1087
1256
|
this.changed.emit(res);
|
|
1088
1257
|
});
|
|
@@ -1103,7 +1272,7 @@ class ComponentFactoryDirective {
|
|
|
1103
1272
|
this.dynamicComponent.instance.valueMode = valueMode;
|
|
1104
1273
|
}
|
|
1105
1274
|
}
|
|
1106
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ComponentFactoryDirective, deps: [{ token: i0.ViewContainerRef }
|
|
1275
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ComponentFactoryDirective, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1107
1276
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: ComponentFactoryDirective, isStandalone: true, selector: "[appComponentFactory]", inputs: { type: "type", data: "data", values: "values", valueMode: "valueMode", map: "map" }, outputs: { changed: "changed" }, usesOnChanges: true, ngImport: i0 }); }
|
|
1108
1277
|
}
|
|
1109
1278
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ComponentFactoryDirective, decorators: [{
|
|
@@ -1112,7 +1281,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
1112
1281
|
selector: '[appComponentFactory]',
|
|
1113
1282
|
standalone: true
|
|
1114
1283
|
}]
|
|
1115
|
-
}], ctorParameters: () => [{ type: i0.ViewContainerRef }
|
|
1284
|
+
}], ctorParameters: () => [{ type: i0.ViewContainerRef }], propDecorators: { type: [{
|
|
1116
1285
|
type: Input
|
|
1117
1286
|
}], data: [{
|
|
1118
1287
|
type: Input
|
|
@@ -1172,6 +1341,12 @@ class BaseFieldComponent {
|
|
|
1172
1341
|
set values(value) {
|
|
1173
1342
|
if (this.valueMode === 'manual') {
|
|
1174
1343
|
this.manualValues = value;
|
|
1344
|
+
const isFormulaInputNumber = this.settings?.type === ComponentType.InputNumber &&
|
|
1345
|
+
this.settings?.options?.inputState === InputState.Formula;
|
|
1346
|
+
if (isFormulaInputNumber && this.model) {
|
|
1347
|
+
this.model.value = getValueModel(this.settings, this.manualValues)?.value;
|
|
1348
|
+
this._detector.detectChanges();
|
|
1349
|
+
}
|
|
1175
1350
|
}
|
|
1176
1351
|
}
|
|
1177
1352
|
set data(settings) {
|
|
@@ -1403,6 +1578,12 @@ class InputNumberComponent extends BaseFieldComponent {
|
|
|
1403
1578
|
this.validateValue = 0;
|
|
1404
1579
|
}
|
|
1405
1580
|
get isReadonly() {
|
|
1581
|
+
return this.hasFormula;
|
|
1582
|
+
}
|
|
1583
|
+
get isInputDisabled() {
|
|
1584
|
+
return this.disabled || this.hasFormula;
|
|
1585
|
+
}
|
|
1586
|
+
get hasFormula() {
|
|
1406
1587
|
return this.settings.options.inputState === InputState.Formula;
|
|
1407
1588
|
}
|
|
1408
1589
|
onChangeInput() {
|
|
@@ -1415,11 +1596,11 @@ class InputNumberComponent extends BaseFieldComponent {
|
|
|
1415
1596
|
this.settings.options.maxValue && model.value && this.settings.options.maxValue < model.value);
|
|
1416
1597
|
}
|
|
1417
1598
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InputNumberComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
1418
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: InputNumberComponent, selector: "app-input-number", usesInheritance: true, ngImport: i0, template: "@if (settings) {\r\n <div class=\"input-number-content\">\r\n @if (settings.options.label) {\r\n <mrx-label\r\n [required]=\"settings.options.required\"\r\n [tooltip]=\"settings.options.tooltip || ''\"\r\n >\r\n {{ settings.options.label }}\r\n </mrx-label>\r\n }\r\n\r\n <mrx-input-number\r\n [(ngModel)]=\"model.value\"\r\n [fields]=\"autosaveFields\"\r\n [readonly]=\"isReadonly\"\r\n [allowNegative]=\"true\"\r\n [numberType]=\"isReadonly || settings.options.decimals ? 'float' : 'int'\"\r\n [decimalSeparator]=\"settings.options.decimalSeparator\"\r\n [decimals]=\"isReadonly ? (settings.options.decimals || 2) : settings.options.decimals\"\r\n [placeholder]=\"settings.options.placeholder\"\r\n [disabled]=\"
|
|
1599
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: InputNumberComponent, selector: "app-input-number", usesInheritance: true, ngImport: i0, template: "@if (settings) {\r\n <div class=\"input-number-content\">\r\n @if (settings.options.label) {\r\n <mrx-label\r\n [required]=\"settings.options.required\"\r\n [tooltip]=\"settings.options.tooltip || ''\"\r\n >\r\n {{ settings.options.label }}\r\n </mrx-label>\r\n }\r\n\r\n <mrx-input-number\r\n [(ngModel)]=\"model.value\"\r\n [fields]=\"autosaveFields\"\r\n [readonly]=\"isReadonly\"\r\n [allowNegative]=\"true\"\r\n [numberType]=\"isReadonly || settings.options.decimals ? 'float' : 'int'\"\r\n [decimalSeparator]=\"settings.options.decimalSeparator\"\r\n [decimals]=\"isReadonly ? (settings.options.decimals || 2) : settings.options.decimals\"\r\n [placeholder]=\"settings.options.placeholder\"\r\n [disabled]=\"isInputDisabled\"\r\n [invalid]=\"getInvalid\"\r\n [invalidMessage]=\"getInvalidMessage\"\r\n (modelChange)=\"dispatchModify($event)\"\r\n (change)=\"onChangeInput()\"\r\n ></mrx-input-number>\r\n\r\n @if (settings.options.minValue) {\r\n <mrx-hint-error-message\r\n message=\"\u041C\u0438\u043D\u0438\u043C\u0430\u043B\u044C\u043D\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u2014 {{ settings.options.minValue }}\"\r\n [value]=\"validateValue\"\r\n [minValue]=\"settings.options.minValue\"\r\n ></mrx-hint-error-message>\r\n }\r\n @if (settings.options.maxValue) {\r\n <mrx-hint-error-message\r\n message=\"\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u2014 {{ settings.options.maxValue }}\"\r\n [value]=\"validateValue\"\r\n [maxValue]=\"settings.options.maxValue\"\r\n ></mrx-hint-error-message>\r\n }\r\n </div>\r\n}\r\n", styles: [""], dependencies: [{ kind: "component", type: i1$2.LabelComponent, selector: "mrx-label", inputs: ["requiredHidden", "required", "boldLabel", "disabled", "placeholder", "label", "customClasses", "triggerTextPosition", "isPublicInfo", "publicInfoTooltip", "isSwitch", "switchLabel", "switchValue", "switchSize", "isCheckbox", "checkboxLabel", "checkboxValue", "counter", "linkText", "linkPrevent", "linkType", "linkMonochrome", "href", "triggerType", "tooltip", "tooltipInitialVisible", "isSaveToStorage"], outputs: ["changeSwitchValue", "changeCheckboxValue", "clickedLink"] }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i1$2.InputNumberComponent, selector: "mrx-input-number", inputs: ["fields", "placeholder", "innerClass", "customClasses", "required", "allowNegative", "size", "separator", "decimalSeparator", "decimals", "isNullableValue", "isAutoCorrectingValue", "invalid", "checkInvalid", "numberType", "invalidMessage", "disabled", "readonly", "minValue", "maxValue"], outputs: ["modelChange", "modelChangeBlur"] }, { kind: "component", type: i1$2.HintErrorMessageComponent, selector: "mrx-hint-error-message", inputs: ["message", "value", "maxValue", "minValue", "minLength", "maxLength", "checkInvalid"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1419
1600
|
}
|
|
1420
1601
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InputNumberComponent, decorators: [{
|
|
1421
1602
|
type: Component,
|
|
1422
|
-
args: [{ selector: 'app-input-number', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (settings) {\r\n <div class=\"input-number-content\">\r\n @if (settings.options.label) {\r\n <mrx-label\r\n [required]=\"settings.options.required\"\r\n [tooltip]=\"settings.options.tooltip || ''\"\r\n >\r\n {{ settings.options.label }}\r\n </mrx-label>\r\n }\r\n\r\n <mrx-input-number\r\n [(ngModel)]=\"model.value\"\r\n [fields]=\"autosaveFields\"\r\n [readonly]=\"isReadonly\"\r\n [allowNegative]=\"true\"\r\n [numberType]=\"isReadonly || settings.options.decimals ? 'float' : 'int'\"\r\n [decimalSeparator]=\"settings.options.decimalSeparator\"\r\n [decimals]=\"isReadonly ? (settings.options.decimals || 2) : settings.options.decimals\"\r\n [placeholder]=\"settings.options.placeholder\"\r\n [disabled]=\"
|
|
1603
|
+
args: [{ selector: 'app-input-number', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (settings) {\r\n <div class=\"input-number-content\">\r\n @if (settings.options.label) {\r\n <mrx-label\r\n [required]=\"settings.options.required\"\r\n [tooltip]=\"settings.options.tooltip || ''\"\r\n >\r\n {{ settings.options.label }}\r\n </mrx-label>\r\n }\r\n\r\n <mrx-input-number\r\n [(ngModel)]=\"model.value\"\r\n [fields]=\"autosaveFields\"\r\n [readonly]=\"isReadonly\"\r\n [allowNegative]=\"true\"\r\n [numberType]=\"isReadonly || settings.options.decimals ? 'float' : 'int'\"\r\n [decimalSeparator]=\"settings.options.decimalSeparator\"\r\n [decimals]=\"isReadonly ? (settings.options.decimals || 2) : settings.options.decimals\"\r\n [placeholder]=\"settings.options.placeholder\"\r\n [disabled]=\"isInputDisabled\"\r\n [invalid]=\"getInvalid\"\r\n [invalidMessage]=\"getInvalidMessage\"\r\n (modelChange)=\"dispatchModify($event)\"\r\n (change)=\"onChangeInput()\"\r\n ></mrx-input-number>\r\n\r\n @if (settings.options.minValue) {\r\n <mrx-hint-error-message\r\n message=\"\u041C\u0438\u043D\u0438\u043C\u0430\u043B\u044C\u043D\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u2014 {{ settings.options.minValue }}\"\r\n [value]=\"validateValue\"\r\n [minValue]=\"settings.options.minValue\"\r\n ></mrx-hint-error-message>\r\n }\r\n @if (settings.options.maxValue) {\r\n <mrx-hint-error-message\r\n message=\"\u041C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u043E\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u2014 {{ settings.options.maxValue }}\"\r\n [value]=\"validateValue\"\r\n [maxValue]=\"settings.options.maxValue\"\r\n ></mrx-hint-error-message>\r\n }\r\n </div>\r\n}\r\n" }]
|
|
1423
1604
|
}] });
|
|
1424
1605
|
|
|
1425
1606
|
class InputSelectComponent extends BaseFieldComponent {
|
|
@@ -1994,10 +2175,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
1994
2175
|
}] } });
|
|
1995
2176
|
|
|
1996
2177
|
class InputTableModalComponent extends ModalServiceComponent {
|
|
1997
|
-
constructor(dialogRef, store, data) {
|
|
2178
|
+
constructor(dialogRef, store, formulaCalculateService, data) {
|
|
1998
2179
|
super();
|
|
1999
2180
|
this.dialogRef = dialogRef;
|
|
2000
2181
|
this.store = store;
|
|
2182
|
+
this.formulaCalculateService = formulaCalculateService;
|
|
2001
2183
|
this.emptyRow = true;
|
|
2002
2184
|
this.title = data.title;
|
|
2003
2185
|
this.okText = data.okText;
|
|
@@ -2015,6 +2197,7 @@ class InputTableModalComponent extends ModalServiceComponent {
|
|
|
2015
2197
|
else {
|
|
2016
2198
|
this._transformValues(valueModel);
|
|
2017
2199
|
}
|
|
2200
|
+
this._recalculateFormulaFields();
|
|
2018
2201
|
this.emptyRow = this.rowModel.data.every(x => this.isEmpty(x.value, x.valueType));
|
|
2019
2202
|
}
|
|
2020
2203
|
ok() {
|
|
@@ -2042,6 +2225,46 @@ class InputTableModalComponent extends ModalServiceComponent {
|
|
|
2042
2225
|
}
|
|
2043
2226
|
this.rowModel = cloneRowModel;
|
|
2044
2227
|
}
|
|
2228
|
+
_recalculateFormulaFields() {
|
|
2229
|
+
const formulaComponents = this._getFormulaNumberComponents(this.settings.components);
|
|
2230
|
+
if (!formulaComponents.length) {
|
|
2231
|
+
return;
|
|
2232
|
+
}
|
|
2233
|
+
const cloneRowModel = structuredClone(this.rowModel);
|
|
2234
|
+
for (let i = 0; i < formulaComponents.length; i++) {
|
|
2235
|
+
let hasUpdates = false;
|
|
2236
|
+
for (const component of formulaComponents) {
|
|
2237
|
+
const formula = component.options?.formula?.trim();
|
|
2238
|
+
if (!formula) {
|
|
2239
|
+
continue;
|
|
2240
|
+
}
|
|
2241
|
+
const result = this.formulaCalculateService.calculateMathExpression(formula, cloneRowModel.data);
|
|
2242
|
+
const targetValue = cloneRowModel.data.find(x => x.sysName === component.sysName);
|
|
2243
|
+
if (!targetValue || targetValue.value === result) {
|
|
2244
|
+
continue;
|
|
2245
|
+
}
|
|
2246
|
+
targetValue.value = result;
|
|
2247
|
+
hasUpdates = true;
|
|
2248
|
+
}
|
|
2249
|
+
if (!hasUpdates) {
|
|
2250
|
+
break;
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
this.rowModel = cloneRowModel;
|
|
2254
|
+
}
|
|
2255
|
+
_getFormulaNumberComponents(components) {
|
|
2256
|
+
const result = [];
|
|
2257
|
+
for (const component of components) {
|
|
2258
|
+
if (component.type === ComponentType.InputNumber &&
|
|
2259
|
+
component.options?.inputState === InputState.Formula) {
|
|
2260
|
+
result.push(component);
|
|
2261
|
+
}
|
|
2262
|
+
if (component.components?.length) {
|
|
2263
|
+
result.push(...this._getFormulaNumberComponents(component.components));
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
return result;
|
|
2267
|
+
}
|
|
2045
2268
|
_isValid() {
|
|
2046
2269
|
var hasError = false;
|
|
2047
2270
|
var requiredComponents = this._getRequiredComponents(this.settings.components);
|
|
@@ -2073,9 +2296,10 @@ class InputTableModalComponent extends ModalServiceComponent {
|
|
|
2073
2296
|
return value.length === 0;
|
|
2074
2297
|
return false;
|
|
2075
2298
|
}
|
|
2076
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InputTableModalComponent, deps: [{ token: i1$2.ModalRef }, { token: i2.Store }, { token: MODAL_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2299
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: InputTableModalComponent, deps: [{ token: i1$2.ModalRef }, { token: i2.Store }, { token: FormulaCalculateService }, { token: MODAL_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2077
2300
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: InputTableModalComponent, isStandalone: true, selector: "app-input-table-modal", providers: [
|
|
2078
2301
|
provideNgxMask(),
|
|
2302
|
+
FormulaCalculateService,
|
|
2079
2303
|
ReferenceService // для компонента список
|
|
2080
2304
|
], usesInheritance: true, ngImport: i0, template: "<mrx-modal\r\n [title]=\"title\"\r\n size=\"large\"\r\n (close)=\"close()\"\r\n (ok)=\"ok()\"\r\n>\r\n <app-form-dispenser-modal\r\n [sectionSettings]=\"settings\"\r\n [values]=\"rowModel.data\"\r\n [valueMode]=\"'manual'\"\r\n (changed)=\"componentValueChanged($event)\"\r\n ></app-form-dispenser-modal>\r\n\r\n <ng-template #footerContent>\r\n <mrx-button\r\n [customClasses]=\"'mr-3'\"\r\n [type]=\"'secondary'\"\r\n [size]=\"'medium'\"\r\n (click)=\"close()\"\r\n >\u041E\u0442\u043C\u0435\u043D\u0430\r\n </mrx-button>\r\n <mrx-button\r\n [type]=\"'primary'\"\r\n [size]=\"'medium'\"\r\n [disabled]=\"emptyRow\"\r\n (click)=\"ok()\"\r\n >{{ okText }}\r\n </mrx-button>\r\n </ng-template>\r\n</mrx-modal>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ModalModule }, { kind: "component", type: i1$2.ModalComponent, selector: "mrx-modal", inputs: ["title", "message", "alert", "okText", "closeText", "size", "color", "customClasses", "expandable", "isEmbed", "isClose", "isBack", "backText", "enableFooter", "alignButtons", "isLoading", "iconPosition"], outputs: ["ok", "close", "back", "expand"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.ButtonComponent, selector: "mrx-button", inputs: ["size", "type", "color", "iconPosition", "active", "disabled", "isLoading", "iconOnly", "customClasses", "label", "icon", "iconClass", "buttonType", "href", "target", "routerLink", "queryParams"], outputs: ["mrxClick"] }, { kind: "component", type: FormDispenserModal, selector: "app-form-dispenser-modal", inputs: ["sectionSettings", "values", "valueMode"], outputs: ["changed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2081
2305
|
}
|
|
@@ -2087,9 +2311,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
2087
2311
|
FormDispenserModal,
|
|
2088
2312
|
], providers: [
|
|
2089
2313
|
provideNgxMask(),
|
|
2314
|
+
FormulaCalculateService,
|
|
2090
2315
|
ReferenceService // для компонента список
|
|
2091
2316
|
], template: "<mrx-modal\r\n [title]=\"title\"\r\n size=\"large\"\r\n (close)=\"close()\"\r\n (ok)=\"ok()\"\r\n>\r\n <app-form-dispenser-modal\r\n [sectionSettings]=\"settings\"\r\n [values]=\"rowModel.data\"\r\n [valueMode]=\"'manual'\"\r\n (changed)=\"componentValueChanged($event)\"\r\n ></app-form-dispenser-modal>\r\n\r\n <ng-template #footerContent>\r\n <mrx-button\r\n [customClasses]=\"'mr-3'\"\r\n [type]=\"'secondary'\"\r\n [size]=\"'medium'\"\r\n (click)=\"close()\"\r\n >\u041E\u0442\u043C\u0435\u043D\u0430\r\n </mrx-button>\r\n <mrx-button\r\n [type]=\"'primary'\"\r\n [size]=\"'medium'\"\r\n [disabled]=\"emptyRow\"\r\n (click)=\"ok()\"\r\n >{{ okText }}\r\n </mrx-button>\r\n </ng-template>\r\n</mrx-modal>\r\n" }]
|
|
2092
|
-
}], ctorParameters: () => [{ type: i1$2.ModalRef }, { type: i2.Store }, { type: undefined, decorators: [{
|
|
2317
|
+
}], ctorParameters: () => [{ type: i1$2.ModalRef }, { type: i2.Store }, { type: FormulaCalculateService }, { type: undefined, decorators: [{
|
|
2093
2318
|
type: Inject,
|
|
2094
2319
|
args: [MODAL_DATA]
|
|
2095
2320
|
}] }] });
|
|
@@ -2190,7 +2415,7 @@ class InputTableComponent {
|
|
|
2190
2415
|
});
|
|
2191
2416
|
}
|
|
2192
2417
|
deleteRow(event) {
|
|
2193
|
-
const findRow =
|
|
2418
|
+
const findRow = this.model.data.find(item => item.id === event.row.data.id);
|
|
2194
2419
|
if (findRow) {
|
|
2195
2420
|
this.model.data = this.model.data.filter(item => item.id !== event.row.data.id);
|
|
2196
2421
|
this._initDataSource(this.model.data);
|
|
@@ -2238,8 +2463,6 @@ class InputTableComponent {
|
|
|
2238
2463
|
switch (component.type) {
|
|
2239
2464
|
case ComponentType.InputDate:
|
|
2240
2465
|
return 'date';
|
|
2241
|
-
case ComponentType.InputSwitch:
|
|
2242
|
-
return 'boolean';
|
|
2243
2466
|
default:
|
|
2244
2467
|
return 'string';
|
|
2245
2468
|
}
|
|
@@ -2296,7 +2519,6 @@ class InputTableComponent {
|
|
|
2296
2519
|
this._detector.detectChanges();
|
|
2297
2520
|
}
|
|
2298
2521
|
_transformColumn(component) {
|
|
2299
|
-
const dataType = this.getDataType(component);
|
|
2300
2522
|
const column = {
|
|
2301
2523
|
caption: component.options.label || '',
|
|
2302
2524
|
columns: component.components.map(c => this._transformColumn(structuredClone(c))),
|
|
@@ -2305,21 +2527,6 @@ class InputTableComponent {
|
|
|
2305
2527
|
format: this.getFormat(component),
|
|
2306
2528
|
minWidth: 160
|
|
2307
2529
|
};
|
|
2308
|
-
if (dataType === 'boolean') {
|
|
2309
|
-
column.calculateCellValue = (rowData) => {
|
|
2310
|
-
const value = rowData[component.sysName];
|
|
2311
|
-
// Если true — Да, если false, "" или null — Нет
|
|
2312
|
-
return !!value;
|
|
2313
|
-
};
|
|
2314
|
-
column.lookup = {
|
|
2315
|
-
dataSource: [
|
|
2316
|
-
{ value: true, displayValue: 'Да' },
|
|
2317
|
-
{ value: false, displayValue: 'Нет' }
|
|
2318
|
-
],
|
|
2319
|
-
valueExpr: 'value',
|
|
2320
|
-
displayExpr: 'displayValue'
|
|
2321
|
-
};
|
|
2322
|
-
}
|
|
2323
2530
|
if (this.settings.options.groups.length) {
|
|
2324
2531
|
const findIdx = this.settings.options.groups.findIndex(x => x === component.sysName);
|
|
2325
2532
|
if (findIdx !== -1) {
|