@masterteam/properties 0.0.75 → 0.0.77

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.
@@ -1307,7 +1307,7 @@ class PropertiesList {
1307
1307
  });
1308
1308
  }
1309
1309
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: PropertiesList, deps: [], target: i0.ɵɵFactoryTarget.Component });
1310
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: PropertiesList, isStandalone: true, selector: "mt-properties-list", inputs: { tab: { classPropertyName: "tab", publicName: "tab", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "isCalculatedTpl", first: true, predicate: ["isCalculatedTpl"], descendants: true, isSignal: true }, { propertyName: "viewTypeTpl", first: true, predicate: ["viewTypeTpl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"space-y-3\">\r\n <div class=\"flex items-center justify-between\">\r\n <div class=\"space-y-1\">\r\n <h1 class=\"text-xl font-semibold text-slate-900 tracking-tight\">\r\n {{ \"properties.list.pageTitle\" | transloco }}\r\n </h1>\r\n <mt-breadcrumb\r\n [items]=\"breadcrumbItems()\"\r\n [styleClass]=\"'flex justify-center'\"\r\n >\r\n </mt-breadcrumb>\r\n </div>\r\n </div>\r\n <mt-table\r\n [tabs]=\"tabs()\"\r\n [(activeTab)]=\"activeTab\"\r\n (onTabChange)=\"onTabChange($event)\"\r\n [data]=\"tableData()\"\r\n [actions]=\"tableActions()\"\r\n [columns]=\"tableColumns()\"\r\n dataKey=\"id\"\r\n storageKey=\"properties-list-table\"\r\n [rowActions]=\"rowActions()\"\r\n [generalSearch]=\"true\"\r\n [showFilters]=\"true\"\r\n [loading]=\"loading()\"\r\n >\r\n <ng-template #viewTypeTpl let-row>\r\n <span class=\"text-sm text-slate-700 dark:text-slate-200\">\r\n {{ row.viewTypeLabel || row.viewType }}\r\n </span>\r\n </ng-template>\r\n\r\n <ng-template #isCalculatedTpl let-row>\r\n @if (row.isCalculated) {\r\n <span\r\n class=\"inline-flex items-center gap-1 rounded-md bg-blue-50 dark:bg-blue-900/30 p-2\"\r\n >\r\n <mt-icon\r\n icon=\"education.calculator\"\r\n class=\"text-blue-600 dark:text-blue-300 text-sm\"\r\n />\r\n <span class=\"text-blue-700 dark:text-blue-200 text-xs font-medium\">\r\n {{ \"properties.list.calculated\" | transloco }}\r\n </span>\r\n </span>\r\n } @else {\r\n <span\r\n class=\"inline-flex items-center gap-1 rounded-md bg-slate-100 dark:bg-slate-800/50 p-2\"\r\n >\r\n <mt-icon\r\n icon=\"general.minus-circle\"\r\n class=\"text-slate-500 dark:text-slate-400 text-sm\"\r\n />\r\n <span class=\"text-slate-600 dark:text-slate-300 text-xs font-medium\">\r\n {{ \"properties.list.uncalculated\" | transloco }}\r\n </span>\r\n </span>\r\n }\r\n </ng-template>\r\n\r\n <ng-template #empty>\r\n <div headless class=\"flex-col justify-center items-center w-full p-5\">\r\n <div class=\"content flex flex-col gap-5 items-center text-center mb-5\">\r\n <svg\r\n width=\"152\"\r\n height=\"120\"\r\n viewBox=\"0 0 152 120\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n >\r\n <circle cx=\"76\" cy=\"52\" r=\"52\" fill=\"#E9EAEB\" />\r\n <g filter=\"url(#filter0_ddd_2474_28277)\">\r\n <path\r\n d=\"M77.6 16C66.8273 16 57.2978 21.3233 51.4987 29.4829C49.605 29.0363 47.6301 28.8 45.6 28.8C31.4615 28.8 20 40.2615 20 54.4C20 68.5385 31.4615 80 45.6 80L109.6 80C121.971 80 132 69.9712 132 57.6C132 45.2288 121.971 35.2 109.6 35.2C108.721 35.2 107.854 35.2506 107.002 35.349C102.098 23.9677 90.7797 16 77.6 16Z\"\r\n fill=\"#FAFAFA\"\r\n />\r\n <ellipse\r\n cx=\"45.6\"\r\n cy=\"54.3998\"\r\n rx=\"25.6\"\r\n ry=\"25.6\"\r\n fill=\"url(#paint0_linear_2474_28277)\"\r\n />\r\n <circle\r\n cx=\"77.6016\"\r\n cy=\"48\"\r\n r=\"32\"\r\n fill=\"url(#paint1_linear_2474_28277)\"\r\n />\r\n <ellipse\r\n cx=\"109.599\"\r\n cy=\"57.6002\"\r\n rx=\"22.4\"\r\n ry=\"22.4\"\r\n fill=\"url(#paint2_linear_2474_28277)\"\r\n />\r\n </g>\r\n <circle cx=\"21\" cy=\"19\" r=\"5\" fill=\"#F5F5F5\" />\r\n <circle cx=\"18\" cy=\"109\" r=\"7\" fill=\"#F5F5F5\" />\r\n <circle cx=\"145\" cy=\"35\" r=\"7\" fill=\"#F5F5F5\" />\r\n <circle cx=\"134\" cy=\"8\" r=\"4\" fill=\"#F5F5F5\" />\r\n <foreignObject x=\"44\" y=\"54\" width=\"64\" height=\"64\">\r\n <div\r\n xmlns=\"http://www.w3.org/1999/xhtml\"\r\n style=\"\r\n backdrop-filter: blur(4px);\r\n clip-path: url(#bgblur_0_2474_28277_clip_path);\r\n height: 100%;\r\n width: 100%;\r\n \"\r\n ></div>\r\n </foreignObject>\r\n <g data-figma-bg-blur-radius=\"8\">\r\n <path\r\n d=\"M52 86C52 72.7452 62.7452 62 76 62C89.2548 62 100 72.7452 100 86C100 99.2548 89.2548 110 76 110C62.7452 110 52 99.2548 52 86Z\"\r\n fill=\"#344054\"\r\n fill-opacity=\"0.4\"\r\n />\r\n <path\r\n d=\"M85 95L81.5001 91.5M84 85.5C84 90.1944 80.1944 94 75.5 94C70.8056 94 67 90.1944 67 85.5C67 80.8056 70.8056 77 75.5 77C80.1944 77 84 80.8056 84 85.5Z\"\r\n stroke=\"white\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </g>\r\n <defs>\r\n <filter\r\n id=\"filter0_ddd_2474_28277\"\r\n x=\"0\"\r\n y=\"16\"\r\n width=\"152\"\r\n height=\"104\"\r\n filterUnits=\"userSpaceOnUse\"\r\n color-interpolation-filters=\"sRGB\"\r\n >\r\n <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"1.5\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect1_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"3\" />\r\n <feGaussianBlur stdDeviation=\"1.5\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.04 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"BackgroundImageFix\"\r\n result=\"effect1_dropShadow_2474_28277\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"4\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect2_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"8\" />\r\n <feGaussianBlur stdDeviation=\"4\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.03 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"effect1_dropShadow_2474_28277\"\r\n result=\"effect2_dropShadow_2474_28277\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"4\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect3_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"20\" />\r\n <feGaussianBlur stdDeviation=\"12\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.08 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"effect2_dropShadow_2474_28277\"\r\n result=\"effect3_dropShadow_2474_28277\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in=\"SourceGraphic\"\r\n in2=\"effect3_dropShadow_2474_28277\"\r\n result=\"shape\"\r\n />\r\n </filter>\r\n <clipPath\r\n id=\"bgblur_0_2474_28277_clip_path\"\r\n transform=\"translate(-44 -54)\"\r\n >\r\n <path\r\n d=\"M52 86C52 72.7452 62.7452 62 76 62C89.2548 62 100 72.7452 100 86C100 99.2548 89.2548 110 76 110C62.7452 110 52 99.2548 52 86Z\"\r\n />\r\n </clipPath>\r\n <linearGradient\r\n id=\"paint0_linear_2474_28277\"\r\n x1=\"25.9429\"\r\n y1=\"37.4855\"\r\n x2=\"71.2\"\r\n y2=\"79.9998\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop offset=\"0.350715\" stop-color=\"white\" stop-opacity=\"0\" />\r\n </linearGradient>\r\n <linearGradient\r\n id=\"paint1_linear_2474_28277\"\r\n x1=\"53.0301\"\r\n y1=\"26.8571\"\r\n x2=\"109.602\"\r\n y2=\"80\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop offset=\"0.350715\" stop-color=\"white\" stop-opacity=\"0\" />\r\n </linearGradient>\r\n <linearGradient\r\n id=\"paint2_linear_2474_28277\"\r\n x1=\"92.3992\"\r\n y1=\"42.8002\"\r\n x2=\"131.999\"\r\n y2=\"80.0002\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop offset=\"0.350715\" stop-color=\"white\" stop-opacity=\"0\" />\r\n </linearGradient>\r\n </defs>\r\n </svg>\r\n\r\n <div class=\"flex flex-col gap-1\">\r\n <div class=\"text-md text-surface-600\">\r\n {{ \"properties.list.emptyStateNoData\" | transloco }}\r\n </div>\r\n </div>\r\n <div>\r\n <mt-button\r\n [label]=\"'properties.list.addNewProperty' | transloco\"\r\n icon=\"general.plus\"\r\n (click)=\"createProperty()\"\r\n />\r\n </div>\r\n </div>\r\n <p-divider type=\"solid\">\r\n <div class=\"text-lg text-surface-600\">\r\n {{ \"properties.list.emptyStateTemplate\" | transloco }}\r\n </div>\r\n </p-divider>\r\n <div class=\"flex gap-3 mt-5 justify-center\">\r\n @for (card of propertyTypes(); track card.label) {\r\n <mt-card\r\n headless\r\n class=\"w-25 tailwind-4 cursor-pointer\"\r\n style=\"background-color: #fafafa\"\r\n (click)=\"createPropertyWithType(card.value)\"\r\n >\r\n <div class=\"content flex flex-col gap-3 items-center text-center\">\r\n <mt-avatar\r\n [style.--p-avatar-background]=\"\r\n 'var(--p-' + card.color + '-100)'\r\n \"\r\n [style.--p-avatar-color]=\"'var(--p-' + card.color + '-600)'\"\r\n [icon]=\"card.icon\"\r\n shape=\"square\"\r\n ></mt-avatar>\r\n <div class=\"flex flex-col gap-1\">\r\n <div class=\"text-xs font-normal\">{{ card.label }}</div>\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n </div>\r\n </ng-template>\r\n </mt-table>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "persistStateExclude", "exportable", "printable", "groupable", "groupCountMap", "cellClickFilter", "freezeActions", "virtualScroll", "virtualScrollItemSize", "scrollHeight", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy", "sortField", "sortDirection"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange", "sortFieldChange", "sortDirectionChange"] }, { kind: "component", type: Breadcrumb, selector: "mt-breadcrumb", inputs: ["items", "styleClass"], outputs: ["onItemClick"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }, { kind: "component", type: Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
1310
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: PropertiesList, isStandalone: true, selector: "mt-properties-list", inputs: { tab: { classPropertyName: "tab", publicName: "tab", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "isCalculatedTpl", first: true, predicate: ["isCalculatedTpl"], descendants: true, isSignal: true }, { propertyName: "viewTypeTpl", first: true, predicate: ["viewTypeTpl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"space-y-3\">\r\n <div class=\"flex items-center justify-between\">\r\n <div class=\"space-y-1\">\r\n <h1 class=\"text-xl font-semibold text-slate-900 tracking-tight\">\r\n {{ \"properties.list.pageTitle\" | transloco }}\r\n </h1>\r\n <mt-breadcrumb\r\n [items]=\"breadcrumbItems()\"\r\n [styleClass]=\"'flex justify-center'\"\r\n >\r\n </mt-breadcrumb>\r\n </div>\r\n </div>\r\n <mt-table\r\n [tabs]=\"tabs()\"\r\n [(activeTab)]=\"activeTab\"\r\n (onTabChange)=\"onTabChange($event)\"\r\n [data]=\"tableData()\"\r\n [actions]=\"tableActions()\"\r\n [columns]=\"tableColumns()\"\r\n dataKey=\"id\"\r\n storageKey=\"properties-list-table\"\r\n [rowActions]=\"rowActions()\"\r\n [generalSearch]=\"true\"\r\n [showFilters]=\"true\"\r\n [loading]=\"loading()\"\r\n >\r\n <ng-template #viewTypeTpl let-row>\r\n <span class=\"text-sm text-slate-700 dark:text-slate-200\">\r\n {{ row.viewTypeLabel || row.viewType }}\r\n </span>\r\n </ng-template>\r\n\r\n <ng-template #isCalculatedTpl let-row>\r\n @if (row.isCalculated) {\r\n <span\r\n class=\"inline-flex items-center gap-1 rounded-md bg-blue-50 dark:bg-blue-900/30 p-2\"\r\n >\r\n <mt-icon\r\n icon=\"education.calculator\"\r\n class=\"text-blue-600 dark:text-blue-300 text-sm\"\r\n />\r\n <span class=\"text-blue-700 dark:text-blue-200 text-xs font-medium\">\r\n {{ \"properties.list.calculated\" | transloco }}\r\n </span>\r\n </span>\r\n } @else {\r\n <span\r\n class=\"inline-flex items-center gap-1 rounded-md bg-slate-100 dark:bg-slate-800/50 p-2\"\r\n >\r\n <mt-icon\r\n icon=\"general.minus-circle\"\r\n class=\"text-slate-500 dark:text-slate-400 text-sm\"\r\n />\r\n <span class=\"text-slate-600 dark:text-slate-300 text-xs font-medium\">\r\n {{ \"properties.list.uncalculated\" | transloco }}\r\n </span>\r\n </span>\r\n }\r\n </ng-template>\r\n\r\n <ng-template #empty>\r\n <div headless class=\"flex-col justify-center items-center w-full p-5\">\r\n <div class=\"content flex flex-col gap-5 items-center text-center mb-5\">\r\n <svg\r\n width=\"152\"\r\n height=\"120\"\r\n viewBox=\"0 0 152 120\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n >\r\n <circle cx=\"76\" cy=\"52\" r=\"52\" fill=\"#E9EAEB\" />\r\n <g filter=\"url(#filter0_ddd_2474_28277)\">\r\n <path\r\n d=\"M77.6 16C66.8273 16 57.2978 21.3233 51.4987 29.4829C49.605 29.0363 47.6301 28.8 45.6 28.8C31.4615 28.8 20 40.2615 20 54.4C20 68.5385 31.4615 80 45.6 80L109.6 80C121.971 80 132 69.9712 132 57.6C132 45.2288 121.971 35.2 109.6 35.2C108.721 35.2 107.854 35.2506 107.002 35.349C102.098 23.9677 90.7797 16 77.6 16Z\"\r\n fill=\"#FAFAFA\"\r\n />\r\n <ellipse\r\n cx=\"45.6\"\r\n cy=\"54.3998\"\r\n rx=\"25.6\"\r\n ry=\"25.6\"\r\n fill=\"url(#paint0_linear_2474_28277)\"\r\n />\r\n <circle\r\n cx=\"77.6016\"\r\n cy=\"48\"\r\n r=\"32\"\r\n fill=\"url(#paint1_linear_2474_28277)\"\r\n />\r\n <ellipse\r\n cx=\"109.599\"\r\n cy=\"57.6002\"\r\n rx=\"22.4\"\r\n ry=\"22.4\"\r\n fill=\"url(#paint2_linear_2474_28277)\"\r\n />\r\n </g>\r\n <circle cx=\"21\" cy=\"19\" r=\"5\" fill=\"#F5F5F5\" />\r\n <circle cx=\"18\" cy=\"109\" r=\"7\" fill=\"#F5F5F5\" />\r\n <circle cx=\"145\" cy=\"35\" r=\"7\" fill=\"#F5F5F5\" />\r\n <circle cx=\"134\" cy=\"8\" r=\"4\" fill=\"#F5F5F5\" />\r\n <foreignObject x=\"44\" y=\"54\" width=\"64\" height=\"64\">\r\n <div\r\n xmlns=\"http://www.w3.org/1999/xhtml\"\r\n style=\"\r\n backdrop-filter: blur(4px);\r\n clip-path: url(#bgblur_0_2474_28277_clip_path);\r\n height: 100%;\r\n width: 100%;\r\n \"\r\n ></div>\r\n </foreignObject>\r\n <g data-figma-bg-blur-radius=\"8\">\r\n <path\r\n d=\"M52 86C52 72.7452 62.7452 62 76 62C89.2548 62 100 72.7452 100 86C100 99.2548 89.2548 110 76 110C62.7452 110 52 99.2548 52 86Z\"\r\n fill=\"#344054\"\r\n fill-opacity=\"0.4\"\r\n />\r\n <path\r\n d=\"M85 95L81.5001 91.5M84 85.5C84 90.1944 80.1944 94 75.5 94C70.8056 94 67 90.1944 67 85.5C67 80.8056 70.8056 77 75.5 77C80.1944 77 84 80.8056 84 85.5Z\"\r\n stroke=\"white\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </g>\r\n <defs>\r\n <filter\r\n id=\"filter0_ddd_2474_28277\"\r\n x=\"0\"\r\n y=\"16\"\r\n width=\"152\"\r\n height=\"104\"\r\n filterUnits=\"userSpaceOnUse\"\r\n color-interpolation-filters=\"sRGB\"\r\n >\r\n <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"1.5\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect1_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"3\" />\r\n <feGaussianBlur stdDeviation=\"1.5\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.04 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"BackgroundImageFix\"\r\n result=\"effect1_dropShadow_2474_28277\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"4\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect2_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"8\" />\r\n <feGaussianBlur stdDeviation=\"4\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.03 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"effect1_dropShadow_2474_28277\"\r\n result=\"effect2_dropShadow_2474_28277\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"4\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect3_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"20\" />\r\n <feGaussianBlur stdDeviation=\"12\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.08 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"effect2_dropShadow_2474_28277\"\r\n result=\"effect3_dropShadow_2474_28277\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in=\"SourceGraphic\"\r\n in2=\"effect3_dropShadow_2474_28277\"\r\n result=\"shape\"\r\n />\r\n </filter>\r\n <clipPath\r\n id=\"bgblur_0_2474_28277_clip_path\"\r\n transform=\"translate(-44 -54)\"\r\n >\r\n <path\r\n d=\"M52 86C52 72.7452 62.7452 62 76 62C89.2548 62 100 72.7452 100 86C100 99.2548 89.2548 110 76 110C62.7452 110 52 99.2548 52 86Z\"\r\n />\r\n </clipPath>\r\n <linearGradient\r\n id=\"paint0_linear_2474_28277\"\r\n x1=\"25.9429\"\r\n y1=\"37.4855\"\r\n x2=\"71.2\"\r\n y2=\"79.9998\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop offset=\"0.350715\" stop-color=\"white\" stop-opacity=\"0\" />\r\n </linearGradient>\r\n <linearGradient\r\n id=\"paint1_linear_2474_28277\"\r\n x1=\"53.0301\"\r\n y1=\"26.8571\"\r\n x2=\"109.602\"\r\n y2=\"80\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop offset=\"0.350715\" stop-color=\"white\" stop-opacity=\"0\" />\r\n </linearGradient>\r\n <linearGradient\r\n id=\"paint2_linear_2474_28277\"\r\n x1=\"92.3992\"\r\n y1=\"42.8002\"\r\n x2=\"131.999\"\r\n y2=\"80.0002\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop offset=\"0.350715\" stop-color=\"white\" stop-opacity=\"0\" />\r\n </linearGradient>\r\n </defs>\r\n </svg>\r\n\r\n <div class=\"flex flex-col gap-1\">\r\n <div class=\"text-md text-surface-600\">\r\n {{ \"properties.list.emptyStateNoData\" | transloco }}\r\n </div>\r\n </div>\r\n <div>\r\n <mt-button\r\n [label]=\"'properties.list.addNewProperty' | transloco\"\r\n icon=\"general.plus\"\r\n (click)=\"createProperty()\"\r\n />\r\n </div>\r\n </div>\r\n <p-divider type=\"solid\">\r\n <div class=\"text-lg text-surface-600\">\r\n {{ \"properties.list.emptyStateTemplate\" | transloco }}\r\n </div>\r\n </p-divider>\r\n <div class=\"flex gap-3 mt-5 justify-center\">\r\n @for (card of propertyTypes(); track card.label) {\r\n <mt-card\r\n headless\r\n class=\"w-25 tailwind-4 cursor-pointer\"\r\n style=\"background-color: #fafafa\"\r\n (click)=\"createPropertyWithType(card.value)\"\r\n >\r\n <div class=\"content flex flex-col gap-3 items-center text-center\">\r\n <mt-avatar\r\n [style.--p-avatar-background]=\"\r\n 'var(--p-' + card.color + '-100)'\r\n \"\r\n [style.--p-avatar-color]=\"'var(--p-' + card.color + '-600)'\"\r\n [icon]=\"card.icon\"\r\n shape=\"square\"\r\n ></mt-avatar>\r\n <div class=\"flex flex-col gap-1\">\r\n <div class=\"text-xs font-normal\">{{ card.label }}</div>\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n </div>\r\n </ng-template>\r\n </mt-table>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "persistStateExclude", "exportable", "printable", "groupable", "groupCountMap", "cellClickFilter", "freezeActions", "virtualScroll", "virtualScrollItemSize", "scrollHeight", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "emptyTitle", "emptyDescription", "emptyActionLabel", "emptyActionIcon", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy", "sortField", "sortDirection"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "emptyAction", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange", "sortFieldChange", "sortDirectionChange"] }, { kind: "component", type: Breadcrumb, selector: "mt-breadcrumb", inputs: ["items", "styleClass"], outputs: ["onItemClick"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }, { kind: "component", type: Divider, selector: "p-divider", inputs: ["styleClass", "layout", "type", "align"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs", "ariaLabel"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
1311
1311
  }
1312
1312
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: PropertiesList, decorators: [{
1313
1313
  type: Component,
@@ -1539,7 +1539,7 @@ class ApiConfiguration {
1539
1539
  useExisting: forwardRef(() => ApiConfiguration),
1540
1540
  multi: true,
1541
1541
  },
1542
- ], ngImport: i0, template: "<div [formGroup]=\"form\" class=\"space-y-6\">\r\n <div class=\"space-y-4 rounded-xl bg-content px-6 py-4 shadow-sm\">\r\n <div class=\"grid items-end gap-3 md:grid-cols-[minmax(0,1fr)_auto]\">\r\n <mt-text-field\r\n formControlName=\"endpoint\"\r\n [label]=\"'properties.form.endpoint' | transloco\"\r\n [placeholder]=\"'properties.form.endpointPlaceholder' | transloco\"\r\n />\r\n <div class=\"flex justify-end gap-2\">\r\n <mt-button\r\n type=\"button\"\r\n [text]=\"true\"\r\n icon=\"general.plus\"\r\n [label]=\"'properties.form.addHeader' | transloco\"\r\n (click)=\"addHeader()\"\r\n />\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"'properties.form.testApi' | transloco\"\r\n [loading]=\"isTesting()\"\r\n (click)=\"testApi()\"\r\n />\r\n </div>\r\n </div>\r\n\r\n @if (headers.controls.length) {\r\n <div class=\"space-y-3\">\r\n <div class=\"text-sm font-medium text-surface-500\">\r\n {{ \"properties.form.headers\" | transloco }}\r\n </div>\r\n <div class=\"space-y-3\">\r\n @for (\r\n headerCtrl of headers.controls;\r\n track headerCtrl;\r\n let i = $index\r\n ) {\r\n <div\r\n [formGroup]=\"headerCtrl\"\r\n class=\"grid items-end gap-3 md:grid-cols-[minmax(0,1fr)_minmax(0,1fr)_auto]\"\r\n >\r\n <mt-text-field\r\n formControlName=\"key\"\r\n [label]=\"'properties.form.headerKey' | transloco\"\r\n />\r\n <mt-text-field\r\n formControlName=\"value\"\r\n [label]=\"'properties.form.headerValue' | transloco\"\r\n />\r\n <mt-button\r\n type=\"button\"\r\n [text]=\"true\"\r\n icon=\"general.trash-01\"\r\n (click)=\"removeHeader(i)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n } @else {\r\n <p class=\"text-xs text-surface-400\">\r\n {{ \"properties.form.noHeadersMessage\" | transloco }}\r\n </p>\r\n }\r\n </div>\r\n\r\n <div class=\"space-y-4 rounded-xl bg-content px-6 py-4 shadow-sm\">\r\n @if (hasDetectedSchema()) {\r\n <div class=\"grid gap-4 md:grid-cols-2\">\r\n <mt-select-field\r\n formControlName=\"key\"\r\n [options]=\"resolvedApiProperties()\"\r\n [showClear]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [label]=\"'properties.form.keyField' | transloco\"\r\n />\r\n <mt-select-field\r\n formControlName=\"value\"\r\n [options]=\"resolvedApiProperties()\"\r\n [showClear]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [label]=\"'properties.form.valueField' | transloco\"\r\n />\r\n </div>\r\n } @else {\r\n <p class=\"text-xs text-surface-400\">\r\n {{ \"properties.form.messageTestApiPrompt\" | transloco }}\r\n </p>\r\n }\r\n\r\n <div class=\"flex items-center justify-between gap-4\">\r\n <mt-toggle-field\r\n formControlName=\"supportMultiSelect\"\r\n [label]=\"'properties.form.labelSupportMultiSelect' | transloco\"\r\n />\r\n @if (isTesting()) {\r\n <span class=\"text-xs text-surface-400\">\r\n {{ \"properties.form.messageTesting\" | transloco }}\r\n </span>\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1542
+ ], ngImport: i0, template: "<div [formGroup]=\"form\" class=\"space-y-6\">\r\n <div class=\"space-y-4 rounded-xl bg-content px-6 py-4 shadow-sm\">\r\n <div class=\"grid items-end gap-3 md:grid-cols-[minmax(0,1fr)_auto]\">\r\n <mt-text-field\r\n formControlName=\"endpoint\"\r\n [label]=\"'properties.form.endpoint' | transloco\"\r\n [placeholder]=\"'properties.form.endpointPlaceholder' | transloco\"\r\n />\r\n <div class=\"flex justify-end gap-2\">\r\n <mt-button\r\n type=\"button\"\r\n [text]=\"true\"\r\n icon=\"general.plus\"\r\n [label]=\"'properties.form.addHeader' | transloco\"\r\n (click)=\"addHeader()\"\r\n />\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"'properties.form.testApi' | transloco\"\r\n [loading]=\"isTesting()\"\r\n (click)=\"testApi()\"\r\n />\r\n </div>\r\n </div>\r\n\r\n @if (headers.controls.length) {\r\n <div class=\"space-y-3\">\r\n <div class=\"text-sm font-medium text-surface-500\">\r\n {{ \"properties.form.headers\" | transloco }}\r\n </div>\r\n <div class=\"space-y-3\">\r\n @for (\r\n headerCtrl of headers.controls;\r\n track headerCtrl;\r\n let i = $index\r\n ) {\r\n <div\r\n [formGroup]=\"headerCtrl\"\r\n class=\"grid items-end gap-3 md:grid-cols-[minmax(0,1fr)_minmax(0,1fr)_auto]\"\r\n >\r\n <mt-text-field\r\n formControlName=\"key\"\r\n [label]=\"'properties.form.headerKey' | transloco\"\r\n />\r\n <mt-text-field\r\n formControlName=\"value\"\r\n [label]=\"'properties.form.headerValue' | transloco\"\r\n />\r\n <mt-button\r\n type=\"button\"\r\n [text]=\"true\"\r\n icon=\"general.trash-01\"\r\n (click)=\"removeHeader(i)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n } @else {\r\n <p class=\"text-xs text-surface-400\">\r\n {{ \"properties.form.noHeadersMessage\" | transloco }}\r\n </p>\r\n }\r\n </div>\r\n\r\n <div class=\"space-y-4 rounded-xl bg-content px-6 py-4 shadow-sm\">\r\n @if (hasDetectedSchema()) {\r\n <div class=\"grid gap-4 md:grid-cols-2\">\r\n <mt-select-field\r\n formControlName=\"key\"\r\n [options]=\"resolvedApiProperties()\"\r\n [showClear]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [label]=\"'properties.form.keyField' | transloco\"\r\n />\r\n <mt-select-field\r\n formControlName=\"value\"\r\n [options]=\"resolvedApiProperties()\"\r\n [showClear]=\"true\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [label]=\"'properties.form.valueField' | transloco\"\r\n />\r\n </div>\r\n } @else {\r\n <p class=\"text-xs text-surface-400\">\r\n {{ \"properties.form.messageTestApiPrompt\" | transloco }}\r\n </p>\r\n }\r\n\r\n <div class=\"flex items-center justify-between gap-4\">\r\n <mt-toggle-field\r\n formControlName=\"supportMultiSelect\"\r\n [label]=\"'properties.form.labelSupportMultiSelect' | transloco\"\r\n />\r\n @if (isTesting()) {\r\n <span class=\"text-xs text-surface-400\">\r\n {{ \"properties.form.messageTesting\" | transloco }}\r\n </span>\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs", "ariaLabel"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1543
1543
  }
1544
1544
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ApiConfiguration, decorators: [{
1545
1545
  type: Component,
@@ -1906,19 +1906,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
1906
1906
 
1907
1907
  /** Fallback colour applied when no rule matches. */
1908
1908
  const PERCENTAGE_DEFAULT_COLOR = '#293558';
1909
+ const PERCENTAGE_MIN_VALUE = 0;
1910
+ const PERCENTAGE_MAX_VALUE = 100;
1909
1911
  /**
1910
1912
  * The colour scale the backend applies to Percentage properties that carry no
1911
1913
  * custom configuration. A newly created property starts from these so the form
1912
1914
  * never has to submit `{}` or an empty `colorRules` array.
1915
+ *
1916
+ * Every band declares both bounds — the editor requires them — and consecutive
1917
+ * bands share a boundary rather than skipping a step: first match wins, so the
1918
+ * earlier rule keeps the shared value, and nothing between two rules can fall
1919
+ * through to the default colour.
1913
1920
  */
1914
1921
  const PERCENTAGE_DEFAULT_COLOR_RULES = [
1915
- { maxValue: 25, color: '#ed2517' },
1916
- { maxValue: 50, color: '#FFB300' },
1917
- { maxValue: 75, color: '#0A5EBE' },
1918
- { maxValue: 100, color: '#4caf50' },
1922
+ { minValue: 0, maxValue: 25, color: '#ed2517' },
1923
+ { minValue: 25, maxValue: 50, color: '#FFB300' },
1924
+ { minValue: 50, maxValue: 75, color: '#0A5EBE' },
1925
+ { minValue: 75, maxValue: 100, color: '#4caf50' },
1919
1926
  ];
1920
- const PERCENTAGE_MIN_VALUE = 0;
1921
- const PERCENTAGE_MAX_VALUE = 100;
1922
1927
  const HEX_COLOR_PATTERN = /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/;
1923
1928
  function toFiniteNumber(value) {
1924
1929
  if (value === null || value === undefined || value === '') {
@@ -1963,8 +1968,12 @@ function normalizePercentageConfiguration(raw) {
1963
1968
  colorRules: rawRules
1964
1969
  .filter((rule) => !!rule && typeof rule === 'object')
1965
1970
  .map((rule) => ({
1966
- minValue: toFiniteNumber(rule['minValue']),
1967
- maxValue: toFiniteNumber(rule['maxValue']),
1971
+ // The editor requires both bounds, but the stored shape leaves them
1972
+ // optional and reads an absent one as open-ended. Closing it against
1973
+ // the scale is the same band written out in full, so a rule saved
1974
+ // before the bounds became mandatory still loads as valid.
1975
+ minValue: toFiniteNumber(rule['minValue']) ?? PERCENTAGE_MIN_VALUE,
1976
+ maxValue: toFiniteNumber(rule['maxValue']) ?? PERCENTAGE_MAX_VALUE,
1968
1977
  color: toColor(rule['color'], PERCENTAGE_DEFAULT_COLOR),
1969
1978
  })),
1970
1979
  defaultColor,
@@ -2204,13 +2213,14 @@ class PercentageConfiguration {
2204
2213
  // ── Rule list ──
2205
2214
  addRule() {
2206
2215
  const rules = this.rules();
2207
- const previous = rules[rules.length - 1];
2216
+ const previousMax = rules[rules.length - 1]?.maxValue;
2208
2217
  // Continue the scale rather than starting from a blank row: the next rule
2209
- // almost always picks up where the previous one stopped.
2210
- const previousMax = previous?.maxValue;
2211
- const start = typeof previousMax === 'number' && previousMax < PERCENTAGE_MAX_VALUE
2212
- ? previousMax + 1
2213
- : null;
2218
+ // almost always picks up where the previous one stopped. Both bounds are
2219
+ // required, so the row is seeded with a usable range rather than left empty
2220
+ // for the user to fill in before the form can be saved.
2221
+ const start = typeof previousMax === 'number'
2222
+ ? Math.min(Math.max(previousMax, PERCENTAGE_MIN_VALUE), PERCENTAGE_MAX_VALUE)
2223
+ : PERCENTAGE_MIN_VALUE;
2214
2224
  this.form.controls.colorRules.push(this.createRuleGroup({
2215
2225
  minValue: start,
2216
2226
  maxValue: PERCENTAGE_MAX_VALUE,
@@ -2259,7 +2269,10 @@ class PercentageConfiguration {
2259
2269
  array.updateValueAndValidity({ emitEvent });
2260
2270
  }
2261
2271
  createRuleGroup(rule) {
2272
+ // `Validators.required` is also what `mt-number-field` reads to mark the
2273
+ // label, so it has to sit on the control rather than on the group.
2262
2274
  const bounds = [
2275
+ Validators.required,
2263
2276
  Validators.min(PERCENTAGE_MIN_VALUE),
2264
2277
  Validators.max(PERCENTAGE_MAX_VALUE),
2265
2278
  ];
@@ -2280,19 +2293,13 @@ class PercentageConfiguration {
2280
2293
  }, { validators: (group) => this.validateRuleBounds(group) });
2281
2294
  }
2282
2295
  /**
2283
- * A rule needs at least one bound with neither it would match nothing and
2284
- * an inverted pair is always a typo.
2296
+ * Both bounds are required, and each control reports its own absenceall
2297
+ * that is left for the group is the pair, where an inverted range is always
2298
+ * a typo.
2285
2299
  */
2286
2300
  validateRuleBounds(group) {
2287
2301
  const min = group.get('minValue')?.value;
2288
2302
  const max = group.get('maxValue')?.value;
2289
- if (min === null && max === null) {
2290
- return {
2291
- boundsRequired: {
2292
- message: this.transloco.translate('properties.form.percentageRuleBoundsRequired'),
2293
- },
2294
- };
2295
- }
2296
2303
  if (typeof min === 'number' && typeof max === 'number' && min > max) {
2297
2304
  return {
2298
2305
  boundsOrder: {
@@ -2328,7 +2335,7 @@ class PercentageConfiguration {
2328
2335
  useExisting: forwardRef(() => PercentageConfiguration),
2329
2336
  multi: true,
2330
2337
  },
2331
- ], ngImport: i0, template: "<div\r\n [formGroup]=\"form\"\r\n class=\"space-y-4 rounded-xl bg-content px-6 py-4 shadow-sm\"\r\n>\r\n <div class=\"flex flex-wrap items-start justify-between gap-3\">\r\n <div class=\"space-y-1\">\r\n <h3 class=\"text-base font-semibold\">\r\n {{ \"properties.form.percentageColorsSection\" | transloco }}\r\n </h3>\r\n <p class=\"max-w-prose text-xs text-surface-500\">\r\n {{ \"properties.form.percentageColorsHint\" | transloco }}\r\n </p>\r\n </div>\r\n <div class=\"flex shrink-0 items-center gap-2\">\r\n <mt-button\r\n type=\"button\"\r\n [text]=\"true\"\r\n icon=\"arrow.refresh-ccw-01\"\r\n [label]=\"'properties.form.percentageRestoreDefaults' | transloco\"\r\n (click)=\"restoreDefaults()\"\r\n />\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.plus\"\r\n [label]=\"'properties.form.percentageAddRule' | transloco\"\r\n (click)=\"addRule()\"\r\n />\r\n </div>\r\n </div>\r\n\r\n @if (ruleControls.length) {\r\n <div class=\"space-y-2\">\r\n @for (ruleCtrl of ruleControls; track ruleCtrl; let i = $index) {\r\n <div\r\n [formGroup]=\"ruleCtrl\"\r\n class=\"rounded-lg border border-surface-200 px-3 py-2\"\r\n >\r\n <div\r\n class=\"grid items-start gap-3 md:grid-cols-[auto_minmax(0,7rem)_minmax(0,7rem)_minmax(0,1fr)_auto]\"\r\n >\r\n <span\r\n class=\"mt-2 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-surface-100 text-xs font-semibold text-surface-600\"\r\n [title]=\"'properties.form.percentageRuleOrderHint' | transloco\"\r\n >\r\n {{ i + 1 }}\r\n </span>\r\n <mt-number-field\r\n formControlName=\"minValue\"\r\n [min]=\"minValue\"\r\n [max]=\"maxValue\"\r\n [label]=\"'properties.form.percentageRuleFrom' | transloco\"\r\n [placeholder]=\"'properties.form.percentageRuleOpen' | transloco\"\r\n />\r\n <mt-number-field\r\n formControlName=\"maxValue\"\r\n [min]=\"minValue\"\r\n [max]=\"maxValue\"\r\n [label]=\"'properties.form.percentageRuleTo' | transloco\"\r\n [placeholder]=\"'properties.form.percentageRuleOpen' | transloco\"\r\n />\r\n <mt-color-picker-field\r\n formControlName=\"color\"\r\n [label]=\"'properties.form.percentageRuleColor' | transloco\"\r\n />\r\n <div class=\"flex items-center gap-1 md:mt-6\">\r\n <mt-button\r\n type=\"button\"\r\n [text]=\"true\"\r\n icon=\"arrow.chevron-up\"\r\n [disabled]=\"i === 0\"\r\n [tooltip]=\"'properties.form.percentageMoveUp' | transloco\"\r\n (click)=\"moveRule(i, -1)\"\r\n />\r\n <mt-button\r\n type=\"button\"\r\n [text]=\"true\"\r\n icon=\"arrow.chevron-down\"\r\n [disabled]=\"i === ruleControls.length - 1\"\r\n [tooltip]=\"'properties.form.percentageMoveDown' | transloco\"\r\n (click)=\"moveRule(i, 1)\"\r\n />\r\n <mt-button\r\n type=\"button\"\r\n [text]=\"true\"\r\n severity=\"danger\"\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"'properties.form.percentageRemoveRule' | transloco\"\r\n (click)=\"removeRule(i)\"\r\n />\r\n </div>\r\n </div>\r\n @if (ruleCtrl.errors && ruleCtrl.touched) {\r\n <p class=\"text-xs text-red-500\">\r\n {{\r\n ruleCtrl.errors[\"boundsRequired\"]?.message ??\r\n ruleCtrl.errors[\"boundsOrder\"]?.message\r\n }}\r\n </p>\r\n }\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <p\r\n class=\"rounded-lg border border-dashed border-surface-300 px-4 py-3 text-xs text-surface-500\"\r\n >\r\n {{ \"properties.form.percentageNoRules\" | transloco }}\r\n </p>\r\n }\r\n\r\n <div class=\"grid gap-4 md:grid-cols-[minmax(0,18rem)_minmax(0,1fr)]\">\r\n <div class=\"space-y-1\">\r\n <mt-color-picker-field\r\n formControlName=\"defaultColor\"\r\n [label]=\"'properties.form.percentageDefaultColor' | transloco\"\r\n />\r\n <p class=\"text-xs text-surface-400\">\r\n {{ \"properties.form.percentageDefaultColorHint\" | transloco }}\r\n </p>\r\n </div>\r\n\r\n <div class=\"space-y-2\">\r\n <span class=\"text-xs font-medium text-surface-500\">\r\n {{ \"properties.form.percentagePreview\" | transloco }}\r\n </span>\r\n <div class=\"flex h-3 overflow-hidden rounded-full\">\r\n @for (segment of previewSegments(); track $index) {\r\n <span\r\n class=\"block h-full\"\r\n [style.flex-grow]=\"segment.weight\"\r\n [style.background-color]=\"segment.color\"\r\n ></span>\r\n }\r\n </div>\r\n <div class=\"flex justify-between text-[10px] text-surface-400\">\r\n <span>{{ minValue }}%</span>\r\n <span>{{ maxValue }}%</span>\r\n </div>\r\n <div class=\"grid items-center gap-3 md:grid-cols-[minmax(0,1fr)_9rem]\">\r\n <mt-slider-field\r\n [formControl]=\"previewControl\"\r\n [min]=\"minValue\"\r\n [max]=\"maxValue\"\r\n [label]=\"'properties.form.percentagePreviewValue' | transloco\"\r\n />\r\n <mt-progress\r\n [value]=\"previewControl.value\"\r\n [color]=\"previewColor()\"\r\n [height]=\"9\"\r\n [showLabel]=\"false\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n @if (warnings().length) {\r\n <ul class=\"space-y-1 text-xs text-amber-600\">\r\n @for (warning of warnings(); track warning) {\r\n <li>{{ warning }}</li>\r\n }\r\n </ul>\r\n }\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: SliderField, selector: "mt-slider-field", inputs: ["field", "label", "class", "min", "max", "step", "hideNumber", "unit", "readonly", "required"] }, { kind: "component", type: Progress, selector: "mt-progress", inputs: ["value", "mode", "showLabel", "unit", "color", "minValue", "maxValue", "height", "circleSize", "strokeWidth", "customClass"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2338
+ ], ngImport: i0, template: "<div\n [formGroup]=\"form\"\n class=\"space-y-4 rounded-xl bg-content px-6 py-4 shadow-sm\"\n>\n <div class=\"flex flex-wrap items-start justify-between gap-3\">\n <div class=\"space-y-1\">\n <h3 class=\"text-base font-semibold\">\n {{ \"properties.form.percentageColorsSection\" | transloco }}\n </h3>\n <p class=\"max-w-prose text-xs text-surface-500\">\n {{ \"properties.form.percentageColorsHint\" | transloco }}\n </p>\n </div>\n <div class=\"flex shrink-0 items-center gap-2\">\n <mt-button\n type=\"button\"\n [text]=\"true\"\n icon=\"arrow.refresh-ccw-01\"\n [label]=\"'properties.form.percentageRestoreDefaults' | transloco\"\n (click)=\"restoreDefaults()\"\n />\n <mt-button\n type=\"button\"\n icon=\"general.plus\"\n [label]=\"'properties.form.percentageAddRule' | transloco\"\n (click)=\"addRule()\"\n />\n </div>\n </div>\n\n @if (ruleControls.length) {\n <div class=\"space-y-2\">\n @for (ruleCtrl of ruleControls; track ruleCtrl; let i = $index) {\n <div\n [formGroup]=\"ruleCtrl\"\n class=\"rounded-lg border border-surface-200 px-3 py-2\"\n >\n <div\n class=\"grid items-start gap-3 md:grid-cols-[auto_minmax(0,7rem)_minmax(0,7rem)_minmax(0,1fr)_auto]\"\n >\n <span\n class=\"mt-2 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-surface-100 text-xs font-semibold text-surface-600\"\n [title]=\"'properties.form.percentageRuleOrderHint' | transloco\"\n >\n {{ i + 1 }}\n </span>\n <mt-number-field\n formControlName=\"minValue\"\n [min]=\"minValue\"\n [max]=\"maxValue\"\n [label]=\"'properties.form.percentageRuleFrom' | transloco\"\n />\n <mt-number-field\n formControlName=\"maxValue\"\n [min]=\"minValue\"\n [max]=\"maxValue\"\n [label]=\"'properties.form.percentageRuleTo' | transloco\"\n />\n <mt-color-picker-field\n formControlName=\"color\"\n [label]=\"'properties.form.percentageRuleColor' | transloco\"\n />\n <div class=\"flex items-center gap-1 md:mt-6\">\n <mt-button\n type=\"button\"\n [text]=\"true\"\n icon=\"arrow.chevron-up\"\n [disabled]=\"i === 0\"\n [tooltip]=\"'properties.form.percentageMoveUp' | transloco\"\n (click)=\"moveRule(i, -1)\"\n />\n <mt-button\n type=\"button\"\n [text]=\"true\"\n icon=\"arrow.chevron-down\"\n [disabled]=\"i === ruleControls.length - 1\"\n [tooltip]=\"'properties.form.percentageMoveDown' | transloco\"\n (click)=\"moveRule(i, 1)\"\n />\n <mt-button\n type=\"button\"\n [text]=\"true\"\n severity=\"danger\"\n icon=\"general.trash-01\"\n [tooltip]=\"'properties.form.percentageRemoveRule' | transloco\"\n (click)=\"removeRule(i)\"\n />\n </div>\n </div>\n @if (\n ruleCtrl.touched && ruleCtrl.errors?.[\"boundsOrder\"];\n as boundsOrder\n ) {\n <p class=\"text-xs text-red-500\">{{ boundsOrder.message }}</p>\n }\n </div>\n }\n </div>\n } @else {\n <p\n class=\"rounded-lg border border-dashed border-surface-300 px-4 py-3 text-xs text-surface-500\"\n >\n {{ \"properties.form.percentageNoRules\" | transloco }}\n </p>\n }\n\n <div class=\"grid gap-4 md:grid-cols-[minmax(0,18rem)_minmax(0,1fr)]\">\n <div class=\"space-y-1\">\n <mt-color-picker-field\n formControlName=\"defaultColor\"\n [label]=\"'properties.form.percentageDefaultColor' | transloco\"\n />\n <p class=\"text-xs text-surface-400\">\n {{ \"properties.form.percentageDefaultColorHint\" | transloco }}\n </p>\n </div>\n\n <div class=\"space-y-2\">\n <span class=\"text-xs font-medium text-surface-500\">\n {{ \"properties.form.percentagePreview\" | transloco }}\n </span>\n <div class=\"flex h-3 overflow-hidden rounded-full\">\n @for (segment of previewSegments(); track $index) {\n <span\n class=\"block h-full\"\n [style.flex-grow]=\"segment.weight\"\n [style.background-color]=\"segment.color\"\n ></span>\n }\n </div>\n <div class=\"flex justify-between text-[10px] text-surface-400\">\n <span>{{ minValue }}%</span>\n <span>{{ maxValue }}%</span>\n </div>\n <div class=\"grid items-center gap-3 md:grid-cols-[minmax(0,1fr)_9rem]\">\n <mt-slider-field\n [formControl]=\"previewControl\"\n [min]=\"minValue\"\n [max]=\"maxValue\"\n [label]=\"'properties.form.percentagePreviewValue' | transloco\"\n />\n <mt-progress\n [value]=\"previewControl.value\"\n [color]=\"previewColor()\"\n [height]=\"9\"\n [showLabel]=\"false\"\n />\n </div>\n </div>\n </div>\n\n @if (warnings().length) {\n <ul class=\"space-y-1 text-xs text-amber-600\">\n @for (warning of warnings(); track warning) {\n <li>{{ warning }}</li>\n }\n </ul>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs", "ariaLabel"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ColorPickerField, selector: "mt-color-picker-field", inputs: ["label", "appendTo", "placeholder", "class", "variant", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: SliderField, selector: "mt-slider-field", inputs: ["field", "label", "class", "min", "max", "step", "hideNumber", "unit", "readonly", "required"] }, { kind: "component", type: Progress, selector: "mt-progress", inputs: ["value", "mode", "showLabel", "unit", "color", "minValue", "maxValue", "height", "circleSize", "strokeWidth", "customClass"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2332
2339
  }
2333
2340
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: PercentageConfiguration, decorators: [{
2334
2341
  type: Component,
@@ -2351,7 +2358,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
2351
2358
  useExisting: forwardRef(() => PercentageConfiguration),
2352
2359
  multi: true,
2353
2360
  },
2354
- ], template: "<div\r\n [formGroup]=\"form\"\r\n class=\"space-y-4 rounded-xl bg-content px-6 py-4 shadow-sm\"\r\n>\r\n <div class=\"flex flex-wrap items-start justify-between gap-3\">\r\n <div class=\"space-y-1\">\r\n <h3 class=\"text-base font-semibold\">\r\n {{ \"properties.form.percentageColorsSection\" | transloco }}\r\n </h3>\r\n <p class=\"max-w-prose text-xs text-surface-500\">\r\n {{ \"properties.form.percentageColorsHint\" | transloco }}\r\n </p>\r\n </div>\r\n <div class=\"flex shrink-0 items-center gap-2\">\r\n <mt-button\r\n type=\"button\"\r\n [text]=\"true\"\r\n icon=\"arrow.refresh-ccw-01\"\r\n [label]=\"'properties.form.percentageRestoreDefaults' | transloco\"\r\n (click)=\"restoreDefaults()\"\r\n />\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.plus\"\r\n [label]=\"'properties.form.percentageAddRule' | transloco\"\r\n (click)=\"addRule()\"\r\n />\r\n </div>\r\n </div>\r\n\r\n @if (ruleControls.length) {\r\n <div class=\"space-y-2\">\r\n @for (ruleCtrl of ruleControls; track ruleCtrl; let i = $index) {\r\n <div\r\n [formGroup]=\"ruleCtrl\"\r\n class=\"rounded-lg border border-surface-200 px-3 py-2\"\r\n >\r\n <div\r\n class=\"grid items-start gap-3 md:grid-cols-[auto_minmax(0,7rem)_minmax(0,7rem)_minmax(0,1fr)_auto]\"\r\n >\r\n <span\r\n class=\"mt-2 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-surface-100 text-xs font-semibold text-surface-600\"\r\n [title]=\"'properties.form.percentageRuleOrderHint' | transloco\"\r\n >\r\n {{ i + 1 }}\r\n </span>\r\n <mt-number-field\r\n formControlName=\"minValue\"\r\n [min]=\"minValue\"\r\n [max]=\"maxValue\"\r\n [label]=\"'properties.form.percentageRuleFrom' | transloco\"\r\n [placeholder]=\"'properties.form.percentageRuleOpen' | transloco\"\r\n />\r\n <mt-number-field\r\n formControlName=\"maxValue\"\r\n [min]=\"minValue\"\r\n [max]=\"maxValue\"\r\n [label]=\"'properties.form.percentageRuleTo' | transloco\"\r\n [placeholder]=\"'properties.form.percentageRuleOpen' | transloco\"\r\n />\r\n <mt-color-picker-field\r\n formControlName=\"color\"\r\n [label]=\"'properties.form.percentageRuleColor' | transloco\"\r\n />\r\n <div class=\"flex items-center gap-1 md:mt-6\">\r\n <mt-button\r\n type=\"button\"\r\n [text]=\"true\"\r\n icon=\"arrow.chevron-up\"\r\n [disabled]=\"i === 0\"\r\n [tooltip]=\"'properties.form.percentageMoveUp' | transloco\"\r\n (click)=\"moveRule(i, -1)\"\r\n />\r\n <mt-button\r\n type=\"button\"\r\n [text]=\"true\"\r\n icon=\"arrow.chevron-down\"\r\n [disabled]=\"i === ruleControls.length - 1\"\r\n [tooltip]=\"'properties.form.percentageMoveDown' | transloco\"\r\n (click)=\"moveRule(i, 1)\"\r\n />\r\n <mt-button\r\n type=\"button\"\r\n [text]=\"true\"\r\n severity=\"danger\"\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"'properties.form.percentageRemoveRule' | transloco\"\r\n (click)=\"removeRule(i)\"\r\n />\r\n </div>\r\n </div>\r\n @if (ruleCtrl.errors && ruleCtrl.touched) {\r\n <p class=\"text-xs text-red-500\">\r\n {{\r\n ruleCtrl.errors[\"boundsRequired\"]?.message ??\r\n ruleCtrl.errors[\"boundsOrder\"]?.message\r\n }}\r\n </p>\r\n }\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <p\r\n class=\"rounded-lg border border-dashed border-surface-300 px-4 py-3 text-xs text-surface-500\"\r\n >\r\n {{ \"properties.form.percentageNoRules\" | transloco }}\r\n </p>\r\n }\r\n\r\n <div class=\"grid gap-4 md:grid-cols-[minmax(0,18rem)_minmax(0,1fr)]\">\r\n <div class=\"space-y-1\">\r\n <mt-color-picker-field\r\n formControlName=\"defaultColor\"\r\n [label]=\"'properties.form.percentageDefaultColor' | transloco\"\r\n />\r\n <p class=\"text-xs text-surface-400\">\r\n {{ \"properties.form.percentageDefaultColorHint\" | transloco }}\r\n </p>\r\n </div>\r\n\r\n <div class=\"space-y-2\">\r\n <span class=\"text-xs font-medium text-surface-500\">\r\n {{ \"properties.form.percentagePreview\" | transloco }}\r\n </span>\r\n <div class=\"flex h-3 overflow-hidden rounded-full\">\r\n @for (segment of previewSegments(); track $index) {\r\n <span\r\n class=\"block h-full\"\r\n [style.flex-grow]=\"segment.weight\"\r\n [style.background-color]=\"segment.color\"\r\n ></span>\r\n }\r\n </div>\r\n <div class=\"flex justify-between text-[10px] text-surface-400\">\r\n <span>{{ minValue }}%</span>\r\n <span>{{ maxValue }}%</span>\r\n </div>\r\n <div class=\"grid items-center gap-3 md:grid-cols-[minmax(0,1fr)_9rem]\">\r\n <mt-slider-field\r\n [formControl]=\"previewControl\"\r\n [min]=\"minValue\"\r\n [max]=\"maxValue\"\r\n [label]=\"'properties.form.percentagePreviewValue' | transloco\"\r\n />\r\n <mt-progress\r\n [value]=\"previewControl.value\"\r\n [color]=\"previewColor()\"\r\n [height]=\"9\"\r\n [showLabel]=\"false\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n @if (warnings().length) {\r\n <ul class=\"space-y-1 text-xs text-amber-600\">\r\n @for (warning of warnings(); track warning) {\r\n <li>{{ warning }}</li>\r\n }\r\n </ul>\r\n }\r\n</div>\r\n" }]
2361
+ ], template: "<div\n [formGroup]=\"form\"\n class=\"space-y-4 rounded-xl bg-content px-6 py-4 shadow-sm\"\n>\n <div class=\"flex flex-wrap items-start justify-between gap-3\">\n <div class=\"space-y-1\">\n <h3 class=\"text-base font-semibold\">\n {{ \"properties.form.percentageColorsSection\" | transloco }}\n </h3>\n <p class=\"max-w-prose text-xs text-surface-500\">\n {{ \"properties.form.percentageColorsHint\" | transloco }}\n </p>\n </div>\n <div class=\"flex shrink-0 items-center gap-2\">\n <mt-button\n type=\"button\"\n [text]=\"true\"\n icon=\"arrow.refresh-ccw-01\"\n [label]=\"'properties.form.percentageRestoreDefaults' | transloco\"\n (click)=\"restoreDefaults()\"\n />\n <mt-button\n type=\"button\"\n icon=\"general.plus\"\n [label]=\"'properties.form.percentageAddRule' | transloco\"\n (click)=\"addRule()\"\n />\n </div>\n </div>\n\n @if (ruleControls.length) {\n <div class=\"space-y-2\">\n @for (ruleCtrl of ruleControls; track ruleCtrl; let i = $index) {\n <div\n [formGroup]=\"ruleCtrl\"\n class=\"rounded-lg border border-surface-200 px-3 py-2\"\n >\n <div\n class=\"grid items-start gap-3 md:grid-cols-[auto_minmax(0,7rem)_minmax(0,7rem)_minmax(0,1fr)_auto]\"\n >\n <span\n class=\"mt-2 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-surface-100 text-xs font-semibold text-surface-600\"\n [title]=\"'properties.form.percentageRuleOrderHint' | transloco\"\n >\n {{ i + 1 }}\n </span>\n <mt-number-field\n formControlName=\"minValue\"\n [min]=\"minValue\"\n [max]=\"maxValue\"\n [label]=\"'properties.form.percentageRuleFrom' | transloco\"\n />\n <mt-number-field\n formControlName=\"maxValue\"\n [min]=\"minValue\"\n [max]=\"maxValue\"\n [label]=\"'properties.form.percentageRuleTo' | transloco\"\n />\n <mt-color-picker-field\n formControlName=\"color\"\n [label]=\"'properties.form.percentageRuleColor' | transloco\"\n />\n <div class=\"flex items-center gap-1 md:mt-6\">\n <mt-button\n type=\"button\"\n [text]=\"true\"\n icon=\"arrow.chevron-up\"\n [disabled]=\"i === 0\"\n [tooltip]=\"'properties.form.percentageMoveUp' | transloco\"\n (click)=\"moveRule(i, -1)\"\n />\n <mt-button\n type=\"button\"\n [text]=\"true\"\n icon=\"arrow.chevron-down\"\n [disabled]=\"i === ruleControls.length - 1\"\n [tooltip]=\"'properties.form.percentageMoveDown' | transloco\"\n (click)=\"moveRule(i, 1)\"\n />\n <mt-button\n type=\"button\"\n [text]=\"true\"\n severity=\"danger\"\n icon=\"general.trash-01\"\n [tooltip]=\"'properties.form.percentageRemoveRule' | transloco\"\n (click)=\"removeRule(i)\"\n />\n </div>\n </div>\n @if (\n ruleCtrl.touched && ruleCtrl.errors?.[\"boundsOrder\"];\n as boundsOrder\n ) {\n <p class=\"text-xs text-red-500\">{{ boundsOrder.message }}</p>\n }\n </div>\n }\n </div>\n } @else {\n <p\n class=\"rounded-lg border border-dashed border-surface-300 px-4 py-3 text-xs text-surface-500\"\n >\n {{ \"properties.form.percentageNoRules\" | transloco }}\n </p>\n }\n\n <div class=\"grid gap-4 md:grid-cols-[minmax(0,18rem)_minmax(0,1fr)]\">\n <div class=\"space-y-1\">\n <mt-color-picker-field\n formControlName=\"defaultColor\"\n [label]=\"'properties.form.percentageDefaultColor' | transloco\"\n />\n <p class=\"text-xs text-surface-400\">\n {{ \"properties.form.percentageDefaultColorHint\" | transloco }}\n </p>\n </div>\n\n <div class=\"space-y-2\">\n <span class=\"text-xs font-medium text-surface-500\">\n {{ \"properties.form.percentagePreview\" | transloco }}\n </span>\n <div class=\"flex h-3 overflow-hidden rounded-full\">\n @for (segment of previewSegments(); track $index) {\n <span\n class=\"block h-full\"\n [style.flex-grow]=\"segment.weight\"\n [style.background-color]=\"segment.color\"\n ></span>\n }\n </div>\n <div class=\"flex justify-between text-[10px] text-surface-400\">\n <span>{{ minValue }}%</span>\n <span>{{ maxValue }}%</span>\n </div>\n <div class=\"grid items-center gap-3 md:grid-cols-[minmax(0,1fr)_9rem]\">\n <mt-slider-field\n [formControl]=\"previewControl\"\n [min]=\"minValue\"\n [max]=\"maxValue\"\n [label]=\"'properties.form.percentagePreviewValue' | transloco\"\n />\n <mt-progress\n [value]=\"previewControl.value\"\n [color]=\"previewColor()\"\n [height]=\"9\"\n [showLabel]=\"false\"\n />\n </div>\n </div>\n </div>\n\n @if (warnings().length) {\n <ul class=\"space-y-1 text-xs text-amber-600\">\n @for (warning of warnings(); track warning) {\n <li>{{ warning }}</li>\n }\n </ul>\n }\n</div>\n" }]
2355
2362
  }], ctorParameters: () => [] });
2356
2363
 
2357
2364
  class StatusItemForm {
@@ -2521,7 +2528,7 @@ class StatusItemForm {
2521
2528
  });
2522
2529
  }
2523
2530
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: StatusItemForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
2524
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: StatusItemForm, isStandalone: true, selector: "mt-status-item-form", inputs: { propertyId: { classPropertyName: "propertyId", publicName: "propertyId", isSignal: true, isRequired: true, transformFunction: null }, contextKey: { classPropertyName: "contextKey", publicName: "contextKey", isSignal: true, isRequired: false, transformFunction: null }, levelSchemaId: { classPropertyName: "levelSchemaId", publicName: "levelSchemaId", isSignal: true, isRequired: false, transformFunction: null }, moduleId: { classPropertyName: "moduleId", publicName: "moduleId", isSignal: true, isRequired: false, transformFunction: null }, statusData: { classPropertyName: "statusData", publicName: "statusData", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\r\n [class]=\"\r\n 'flex max-h-[75vh] flex-col gap-4 overflow-y-auto p-4 my-4 ' +\r\n modal.contentClass\r\n \"\r\n>\r\n <form class=\"space-y-6\">\r\n <mt-dynamic-form\r\n class=\"block\"\r\n [formConfig]=\"statusFormConfig()\"\r\n [formControl]=\"statusFormControl\"\r\n />\r\n\r\n @if (showFormula()) {\r\n <div class=\"rounded-xl border border-surface-200 bg-content px-4 py-4\">\r\n <div class=\"mb-3 font-medium text-surface-700\">\r\n {{ \"properties.form.statusFormula\" | transloco }}\r\n <span class=\"text-red-500 dark:text-red-600\" aria-hidden=\"true\"\r\n >*</span\r\n >\r\n </div>\r\n\r\n <mt-formula-builder\r\n [formControl]=\"formulaControl\"\r\n [contextKey]=\"contextKey()\"\r\n [levelSchemaId]=\"levelSchemaId()\"\r\n [moduleId]=\"moduleId()\"\r\n />\r\n </div>\r\n }\r\n </form>\r\n</div>\r\n\r\n<div [class]=\"modal.footerClass\" class=\"mt-7\">\r\n <mt-button [label]=\"cancelLabel()\" variant=\"outlined\" (click)=\"ref.close()\" />\r\n <mt-button\r\n [label]=\"buttonLabel()\"\r\n (click)=\"onSubmit()\"\r\n [loading]=\"isSubmitting()\"\r\n [disabled]=\"\r\n statusFormControl.invalid ||\r\n (showFormula() && formulaControl.invalid) ||\r\n isSubmitting()\r\n \"\r\n />\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig", "forcedHiddenFieldKeys", "forcedDisabledFieldKeys", "preserveForcedHiddenValues", "visibleSectionKeys", "externalValues"], outputs: ["runtimeMessagesChange"] }, { kind: "component", type: FormulaBuilder, selector: "mt-formula-builder", inputs: ["propertiesByPath", "levelSchemaId", "moduleId", "contextKey", "contextEntityTypeKey", "templateId", "placeholder", "hideToolbar", "hideStatusBar", "toolbarTabs", "codeOnly", "builderOnly", "valueMode", "isProcessBuilder"], outputs: ["validationChange", "tokensChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
2531
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: StatusItemForm, isStandalone: true, selector: "mt-status-item-form", inputs: { propertyId: { classPropertyName: "propertyId", publicName: "propertyId", isSignal: true, isRequired: true, transformFunction: null }, contextKey: { classPropertyName: "contextKey", publicName: "contextKey", isSignal: true, isRequired: false, transformFunction: null }, levelSchemaId: { classPropertyName: "levelSchemaId", publicName: "levelSchemaId", isSignal: true, isRequired: false, transformFunction: null }, moduleId: { classPropertyName: "moduleId", publicName: "moduleId", isSignal: true, isRequired: false, transformFunction: null }, statusData: { classPropertyName: "statusData", publicName: "statusData", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\r\n [class]=\"\r\n 'flex max-h-[75vh] flex-col gap-4 overflow-y-auto p-4 my-4 ' +\r\n modal.contentClass\r\n \"\r\n>\r\n <form class=\"space-y-6\">\r\n <mt-dynamic-form\r\n class=\"block\"\r\n [formConfig]=\"statusFormConfig()\"\r\n [formControl]=\"statusFormControl\"\r\n />\r\n\r\n @if (showFormula()) {\r\n <div class=\"rounded-xl border border-surface-200 bg-content px-4 py-4\">\r\n <div class=\"mb-3 font-medium text-surface-700\">\r\n {{ \"properties.form.statusFormula\" | transloco }}\r\n <span class=\"text-red-500 dark:text-red-600\" aria-hidden=\"true\"\r\n >*</span\r\n >\r\n </div>\r\n\r\n <mt-formula-builder\r\n [formControl]=\"formulaControl\"\r\n [contextKey]=\"contextKey()\"\r\n [levelSchemaId]=\"levelSchemaId()\"\r\n [moduleId]=\"moduleId()\"\r\n />\r\n </div>\r\n }\r\n </form>\r\n</div>\r\n\r\n<div [class]=\"modal.footerClass\" class=\"mt-7\">\r\n <mt-button [label]=\"cancelLabel()\" variant=\"outlined\" (click)=\"ref.close()\" />\r\n <mt-button\r\n [label]=\"buttonLabel()\"\r\n (click)=\"onSubmit()\"\r\n [loading]=\"isSubmitting()\"\r\n [disabled]=\"\r\n statusFormControl.invalid ||\r\n (showFormula() && formulaControl.invalid) ||\r\n isSubmitting()\r\n \"\r\n />\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs", "ariaLabel"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig", "forcedHiddenFieldKeys", "forcedDisabledFieldKeys", "preserveForcedHiddenValues", "visibleSectionKeys", "externalValues"], outputs: ["runtimeMessagesChange"] }, { kind: "component", type: FormulaBuilder, selector: "mt-formula-builder", inputs: ["propertiesByPath", "levelSchemaId", "moduleId", "contextKey", "contextEntityTypeKey", "templateId", "placeholder", "hideToolbar", "hideStatusBar", "toolbarTabs", "codeOnly", "builderOnly", "valueMode", "isProcessBuilder"], outputs: ["validationChange", "tokensChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
2525
2532
  }
2526
2533
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: StatusItemForm, decorators: [{
2527
2534
  type: Component,
@@ -2684,7 +2691,7 @@ class StatusConfiguration {
2684
2691
  return Number.isFinite(parsed) ? parsed : null;
2685
2692
  }
2686
2693
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: StatusConfiguration, deps: [], target: i0.ɵɵFactoryTarget.Component });
2687
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: StatusConfiguration, isStandalone: true, selector: "mt-status-configuration", inputs: { propertyId: { classPropertyName: "propertyId", publicName: "propertyId", isSignal: true, isRequired: false, transformFunction: null }, contextKey: { classPropertyName: "contextKey", publicName: "contextKey", isSignal: true, isRequired: false, transformFunction: null }, levelSchemaId: { classPropertyName: "levelSchemaId", publicName: "levelSchemaId", isSignal: true, isRequired: false, transformFunction: null }, moduleId: { classPropertyName: "moduleId", publicName: "moduleId", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "colorTpl", first: true, predicate: ["colorTpl"], descendants: true, isSignal: true }], ngImport: i0, template: "<mt-card [title]=\"'properties.form.statusesSection' | transloco\">\r\n @if (canManageStatuses()) {\r\n <mt-table\r\n [data]=\"statuses()\"\r\n [columns]=\"tableColumns()\"\r\n [actions]=\"tableActions()\"\r\n [rowActions]=\"rowActions()\"\r\n [generalSearch]=\"true\"\r\n [loading]=\"loading()\"\r\n [updating]=\"reordering()\"\r\n [reorderableRows]=\"true\"\r\n dataKey=\"id\"\r\n storageKey=\"properties-status-configuration-table\"\r\n (rowReorder)=\"onRowReorder($event)\"\r\n >\r\n <ng-template #colorTpl let-row>\r\n @if (row.color) {\r\n <span\r\n class=\"inline-block h-5 w-5 rounded-full border border-surface-300\"\r\n [style.background-color]=\"row.color\"\r\n [title]=\"row.color\"\r\n ></span>\r\n } @else {\r\n <span class=\"text-surface-400\">\u2014</span>\r\n }\r\n </ng-template>\r\n </mt-table>\r\n } @else {\r\n <div\r\n class=\"rounded-xl border border-dashed border-surface-300 bg-surface-50 px-4 py-6 text-sm text-surface-600\"\r\n >\r\n {{ \"properties.form.statusesSavePrompt\" | transloco }}\r\n </div>\r\n }\r\n</mt-card>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "persistStateExclude", "exportable", "printable", "groupable", "groupCountMap", "cellClickFilter", "freezeActions", "virtualScroll", "virtualScrollItemSize", "scrollHeight", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy", "sortField", "sortDirection"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange", "sortFieldChange", "sortDirectionChange"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
2694
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: StatusConfiguration, isStandalone: true, selector: "mt-status-configuration", inputs: { propertyId: { classPropertyName: "propertyId", publicName: "propertyId", isSignal: true, isRequired: false, transformFunction: null }, contextKey: { classPropertyName: "contextKey", publicName: "contextKey", isSignal: true, isRequired: false, transformFunction: null }, levelSchemaId: { classPropertyName: "levelSchemaId", publicName: "levelSchemaId", isSignal: true, isRequired: false, transformFunction: null }, moduleId: { classPropertyName: "moduleId", publicName: "moduleId", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "colorTpl", first: true, predicate: ["colorTpl"], descendants: true, isSignal: true }], ngImport: i0, template: "<mt-card [title]=\"'properties.form.statusesSection' | transloco\">\r\n @if (canManageStatuses()) {\r\n <mt-table\r\n [data]=\"statuses()\"\r\n [columns]=\"tableColumns()\"\r\n [actions]=\"tableActions()\"\r\n [rowActions]=\"rowActions()\"\r\n [generalSearch]=\"true\"\r\n [loading]=\"loading()\"\r\n [updating]=\"reordering()\"\r\n [reorderableRows]=\"true\"\r\n dataKey=\"id\"\r\n storageKey=\"properties-status-configuration-table\"\r\n (rowReorder)=\"onRowReorder($event)\"\r\n >\r\n <ng-template #colorTpl let-row>\r\n @if (row.color) {\r\n <span\r\n class=\"inline-block h-5 w-5 rounded-full border border-surface-300\"\r\n [style.background-color]=\"row.color\"\r\n [title]=\"row.color\"\r\n ></span>\r\n } @else {\r\n <span class=\"text-surface-400\">\u2014</span>\r\n }\r\n </ng-template>\r\n </mt-table>\r\n } @else {\r\n <div\r\n class=\"rounded-xl border border-dashed border-surface-300 bg-surface-50 px-4 py-6 text-sm text-surface-600\"\r\n >\r\n {{ \"properties.form.statusesSavePrompt\" | transloco }}\r\n </div>\r\n }\r\n</mt-card>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "persistStateExclude", "exportable", "printable", "groupable", "groupCountMap", "cellClickFilter", "freezeActions", "virtualScroll", "virtualScrollItemSize", "scrollHeight", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "emptyTitle", "emptyDescription", "emptyActionLabel", "emptyActionIcon", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy", "sortField", "sortDirection"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "emptyAction", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange", "sortFieldChange", "sortDirectionChange"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
2688
2695
  }
2689
2696
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: StatusConfiguration, decorators: [{
2690
2697
  type: Component,
@@ -3410,6 +3417,12 @@ class PropertyForm {
3410
3417
  this.submitProperty(payload);
3411
3418
  return;
3412
3419
  }
3420
+ // Calculated properties are formula-driven, not something a user
3421
+ // hand-adds to a form — skip the prompt and never add them.
3422
+ if (isCalculated) {
3423
+ this.submitProperty({ ...payload, addToForm: false });
3424
+ return;
3425
+ }
3413
3426
  // On create, ask (via a popup anchored to the Save button) whether the
3414
3427
  // new property should also be added to the form. ConfirmPopup only fires
3415
3428
  // `accept`/`reject` on the buttons; clicking outside or pressing Escape
@@ -3522,7 +3535,7 @@ class PropertyForm {
3522
3535
  this.subscriptions.unsubscribe();
3523
3536
  }
3524
3537
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: PropertyForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
3525
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: PropertyForm, isStandalone: true, selector: "mt-property-form", inputs: { propertyId: { classPropertyName: "propertyId", publicName: "propertyId", isSignal: true, isRequired: false, transformFunction: null }, scope: { classPropertyName: "scope", publicName: "scope", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "statusConfigurationSection", first: true, predicate: ["statusConfigurationSection"], descendants: true, isSignal: true }, { propertyName: "configurationHost", first: true, predicate: ["configurationHost"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<mt-page\r\n [title]=\"\r\n propertyId()\r\n ? ('properties.form.editProperty' | transloco)\r\n : ('properties.form.createNewProperty' | transloco)\r\n \"\r\n avatarIcon=\"custom.products-and-services\"\r\n [avatarStyle]=\"{\r\n '--p-avatar-background': 'var(--p-sky-50)',\r\n '--p-avatar-color': 'var(--p-sky-700)',\r\n }\"\r\n (backButtonClick)=\"goBack()\"\r\n backButton\r\n class=\"h-full\"\r\n>\r\n <ng-template #headerEnd>\r\n <mt-button\r\n class=\"mx-2\"\r\n [label]=\"submitLabel()\"\r\n [icon]=\"isEditing() ? 'custom.pencil' : 'general.plus'\"\r\n [loading]=\"submitting()\"\r\n [disabled]=\"submitDisabled() || this.propertyForm.invalid\"\r\n (click)=\"createOrEditProperty($event)\"\r\n />\r\n </ng-template>\r\n <div\r\n [formGroup]=\"propertyForm\"\r\n class=\"h-full py-4 h-full overflow-y-auto flex justify-center\"\r\n >\r\n <div class=\"w-2/3 flex flex-col gap-6\">\r\n @if (loading()) {\r\n <!-- Skeleton Loading State -->\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <div class=\"flex justify-between items-center gap-6\">\r\n <p-skeleton width=\"50%\" height=\"3rem\"></p-skeleton>\r\n <p-skeleton width=\"8rem\" height=\"2.5rem\"></p-skeleton>\r\n </div>\r\n </div>\r\n\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <p-skeleton\r\n width=\"12rem\"\r\n height=\"1.5rem\"\r\n styleClass=\"mb-4\"\r\n ></p-skeleton>\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"6rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n <p-skeleton height=\"3rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <p-skeleton\r\n width=\"10rem\"\r\n height=\"1.5rem\"\r\n styleClass=\"mb-4\"\r\n ></p-skeleton>\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"8rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n } @else {\r\n <mt-dynamic-form\r\n [formConfig]=\"dynamicFormConfigMain()\"\r\n [forcedDisabledFieldKeys]=\"lockedMainFieldKeys()\"\r\n [formControlName]=\"'main'\"\r\n />\r\n @if (configurationFormConfig()) {\r\n <mt-dynamic-form\r\n formControlName=\"configuration\"\r\n [formConfig]=\"configurationFormConfig()!\"\r\n />\r\n } @else {\r\n <ng-container #configurationHost></ng-container>\r\n @if (!configurationComponentExists()) {\r\n @switch (propertyType()) {\r\n @case (\"User\") {\r\n <mt-user-configuration />\r\n }\r\n @case (\"Percentage\") {\r\n <mt-percentage-configuration formControlName=\"configuration\" />\r\n }\r\n @case (\"Lookup\") {\r\n <mt-lookup-configuration />\r\n }\r\n @case (\"LookupMultiSelect\") {\r\n <mt-lookup-configuration />\r\n }\r\n @case (\"EntityList\") {\r\n <mt-entity-list-configuration />\r\n }\r\n @case (\"API\") {\r\n <mt-api-configuration formControlName=\"configuration\" />\r\n }\r\n @case (\"Status\") {\r\n <section #statusConfigurationSection>\r\n <mt-status-configuration\r\n [propertyId]=\"statusPropertyId()\"\r\n [contextKey]=\"formulaContextKey()\"\r\n [levelSchemaId]=\"formulaSchemaId()\"\r\n [moduleId]=\"formulaModuleId()\"\r\n />\r\n </section>\r\n }\r\n <!-- @case('ViewList') { REMOVED FOR NOW\r\n <mt-view-list-configuration />\r\n } -->\r\n @case (\"Attachment\") {\r\n <mt-attachment-configuration />\r\n }\r\n <!-- @case('ReferenceProperty') { REMOVED FOR NOW\r\n } -->\r\n @case (\"LookupModuleCheckList\") {\r\n <mt-check-list-form-configuration />\r\n }\r\n <!-- @case('LookupMatrix') { REMOVED FOR NOW\r\n <mt-lookup-configuration />\r\n } -->\r\n @case (\"Location\") {\r\n <mt-location-configuration />\r\n }\r\n }\r\n }\r\n }\r\n @if (isCalculated() && !hideFormulaBuilder()) {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div\r\n class=\"flex items-center justify-between px-4 py-5 border-b border-surface\"\r\n >\r\n <h3 class=\"text-xl font-semibold\">\r\n {{ \"properties.form.formula\" | transloco }}\r\n <span class=\"text-red-500\">*</span>\r\n </h3>\r\n </div>\r\n <div class=\"flex-1 min-h-0 p-4\">\r\n <mt-formula-builder\r\n formControlName=\"formula\"\r\n [contextKey]=\"formulaContextKey()\"\r\n [levelSchemaId]=\"formulaSchemaId()\"\r\n [moduleId]=\"formulaModuleId()\"\r\n />\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n }\r\n </div>\r\n </div>\r\n</mt-page>\r\n", styles: [""], dependencies: [{ kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig", "forcedHiddenFieldKeys", "forcedDisabledFieldKeys", "preserveForcedHiddenValues", "visibleSectionKeys", "externalValues"], outputs: ["runtimeMessagesChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: FormulaBuilder, selector: "mt-formula-builder", inputs: ["propertiesByPath", "levelSchemaId", "moduleId", "contextKey", "contextEntityTypeKey", "templateId", "placeholder", "hideToolbar", "hideStatusBar", "toolbarTabs", "codeOnly", "builderOnly", "valueMode", "isProcessBuilder"], outputs: ["validationChange", "tokensChange"] }, { kind: "component", type: ApiConfiguration, selector: "mt-api-configuration" }, { kind: "component", type: CheckListFormConfiguration, selector: "mt-check-list-form-configuration" }, { kind: "component", type: EntityListConfiguration, selector: "mt-entity-list-configuration" }, { kind: "component", type: LocationConfiguration, selector: "mt-location-configuration" }, { kind: "component", type: LookupConfiguration, selector: "mt-lookup-configuration" }, { kind: "component", type: PercentageConfiguration, selector: "mt-percentage-configuration" }, { kind: "component", type: StatusConfiguration, selector: "mt-status-configuration", inputs: ["propertyId", "contextKey", "levelSchemaId", "moduleId"] }, { kind: "component", type: UserConfiguration, selector: "mt-user-configuration" }, { kind: "component", type: AttachmentConfiguration, selector: "mt-attachment-configuration" }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i2$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
3538
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: PropertyForm, isStandalone: true, selector: "mt-property-form", inputs: { propertyId: { classPropertyName: "propertyId", publicName: "propertyId", isSignal: true, isRequired: false, transformFunction: null }, scope: { classPropertyName: "scope", publicName: "scope", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "statusConfigurationSection", first: true, predicate: ["statusConfigurationSection"], descendants: true, isSignal: true }, { propertyName: "configurationHost", first: true, predicate: ["configurationHost"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<mt-page\r\n [title]=\"\r\n propertyId()\r\n ? ('properties.form.editProperty' | transloco)\r\n : ('properties.form.createNewProperty' | transloco)\r\n \"\r\n avatarIcon=\"custom.products-and-services\"\r\n [avatarStyle]=\"{\r\n '--p-avatar-background': 'var(--p-sky-50)',\r\n '--p-avatar-color': 'var(--p-sky-700)',\r\n }\"\r\n (backButtonClick)=\"goBack()\"\r\n backButton\r\n class=\"h-full\"\r\n>\r\n <ng-template #headerEnd>\r\n <mt-button\r\n class=\"mx-2\"\r\n [label]=\"submitLabel()\"\r\n [icon]=\"isEditing() ? 'custom.pencil' : 'general.plus'\"\r\n [loading]=\"submitting()\"\r\n [disabled]=\"submitDisabled() || this.propertyForm.invalid\"\r\n (click)=\"createOrEditProperty($event)\"\r\n />\r\n </ng-template>\r\n <div\r\n [formGroup]=\"propertyForm\"\r\n class=\"h-full py-4 h-full overflow-y-auto flex justify-center\"\r\n >\r\n <div class=\"w-2/3 flex flex-col gap-6\">\r\n @if (loading()) {\r\n <!-- Skeleton Loading State -->\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <div class=\"flex justify-between items-center gap-6\">\r\n <p-skeleton width=\"50%\" height=\"3rem\"></p-skeleton>\r\n <p-skeleton width=\"8rem\" height=\"2.5rem\"></p-skeleton>\r\n </div>\r\n </div>\r\n\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <p-skeleton\r\n width=\"12rem\"\r\n height=\"1.5rem\"\r\n styleClass=\"mb-4\"\r\n ></p-skeleton>\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"6rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n <p-skeleton height=\"3rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n\r\n <div class=\"rounded-xl bg-white shadow-sm p-6 space-y-4\">\r\n <p-skeleton\r\n width=\"10rem\"\r\n height=\"1.5rem\"\r\n styleClass=\"mb-4\"\r\n ></p-skeleton>\r\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"3rem\"></p-skeleton>\r\n <p-skeleton height=\"8rem\" styleClass=\"md:col-span-2\"></p-skeleton>\r\n </div>\r\n </div>\r\n } @else {\r\n <mt-dynamic-form\r\n [formConfig]=\"dynamicFormConfigMain()\"\r\n [forcedDisabledFieldKeys]=\"lockedMainFieldKeys()\"\r\n [formControlName]=\"'main'\"\r\n />\r\n @if (configurationFormConfig()) {\r\n <mt-dynamic-form\r\n formControlName=\"configuration\"\r\n [formConfig]=\"configurationFormConfig()!\"\r\n />\r\n } @else {\r\n <ng-container #configurationHost></ng-container>\r\n @if (!configurationComponentExists()) {\r\n @switch (propertyType()) {\r\n @case (\"User\") {\r\n <mt-user-configuration />\r\n }\r\n @case (\"Percentage\") {\r\n <mt-percentage-configuration formControlName=\"configuration\" />\r\n }\r\n @case (\"Lookup\") {\r\n <mt-lookup-configuration />\r\n }\r\n @case (\"LookupMultiSelect\") {\r\n <mt-lookup-configuration />\r\n }\r\n @case (\"EntityList\") {\r\n <mt-entity-list-configuration />\r\n }\r\n @case (\"API\") {\r\n <mt-api-configuration formControlName=\"configuration\" />\r\n }\r\n @case (\"Status\") {\r\n <section #statusConfigurationSection>\r\n <mt-status-configuration\r\n [propertyId]=\"statusPropertyId()\"\r\n [contextKey]=\"formulaContextKey()\"\r\n [levelSchemaId]=\"formulaSchemaId()\"\r\n [moduleId]=\"formulaModuleId()\"\r\n />\r\n </section>\r\n }\r\n <!-- @case('ViewList') { REMOVED FOR NOW\r\n <mt-view-list-configuration />\r\n } -->\r\n @case (\"Attachment\") {\r\n <mt-attachment-configuration />\r\n }\r\n <!-- @case('ReferenceProperty') { REMOVED FOR NOW\r\n } -->\r\n @case (\"LookupModuleCheckList\") {\r\n <mt-check-list-form-configuration />\r\n }\r\n <!-- @case('LookupMatrix') { REMOVED FOR NOW\r\n <mt-lookup-configuration />\r\n } -->\r\n @case (\"Location\") {\r\n <mt-location-configuration />\r\n }\r\n }\r\n }\r\n }\r\n @if (isCalculated() && !hideFormulaBuilder()) {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div\r\n class=\"flex items-center justify-between px-4 py-5 border-b border-surface\"\r\n >\r\n <h3 class=\"text-xl font-semibold\">\r\n {{ \"properties.form.formula\" | transloco }}\r\n <span class=\"text-red-500\">*</span>\r\n </h3>\r\n </div>\r\n <div class=\"flex-1 min-h-0 p-4\">\r\n <mt-formula-builder\r\n formControlName=\"formula\"\r\n [contextKey]=\"formulaContextKey()\"\r\n [levelSchemaId]=\"formulaSchemaId()\"\r\n [moduleId]=\"formulaModuleId()\"\r\n />\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n }\r\n </div>\r\n </div>\r\n</mt-page>\r\n", styles: [""], dependencies: [{ kind: "component", type: Page, selector: "mt-page", inputs: ["backButton", "backButtonIcon", "avatarIcon", "avatarStyle", "avatarShape", "title", "tabs", "activeTab", "contentClass", "contentId"], outputs: ["backButtonClick", "tabChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs", "ariaLabel"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig", "forcedHiddenFieldKeys", "forcedDisabledFieldKeys", "preserveForcedHiddenValues", "visibleSectionKeys", "externalValues"], outputs: ["runtimeMessagesChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: FormulaBuilder, selector: "mt-formula-builder", inputs: ["propertiesByPath", "levelSchemaId", "moduleId", "contextKey", "contextEntityTypeKey", "templateId", "placeholder", "hideToolbar", "hideStatusBar", "toolbarTabs", "codeOnly", "builderOnly", "valueMode", "isProcessBuilder"], outputs: ["validationChange", "tokensChange"] }, { kind: "component", type: ApiConfiguration, selector: "mt-api-configuration" }, { kind: "component", type: CheckListFormConfiguration, selector: "mt-check-list-form-configuration" }, { kind: "component", type: EntityListConfiguration, selector: "mt-entity-list-configuration" }, { kind: "component", type: LocationConfiguration, selector: "mt-location-configuration" }, { kind: "component", type: LookupConfiguration, selector: "mt-lookup-configuration" }, { kind: "component", type: PercentageConfiguration, selector: "mt-percentage-configuration" }, { kind: "component", type: StatusConfiguration, selector: "mt-status-configuration", inputs: ["propertyId", "contextKey", "levelSchemaId", "moduleId"] }, { kind: "component", type: UserConfiguration, selector: "mt-user-configuration" }, { kind: "component", type: AttachmentConfiguration, selector: "mt-attachment-configuration" }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i2$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
3526
3539
  }
3527
3540
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: PropertyForm, decorators: [{
3528
3541
  type: Component,