@agridea/suibi-module 0.1.0-preview.b3c1d3c → 0.1.0-preview.c3246cc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/elements/browser/main.js +69 -69
- package/dist/elements/browser/styles.css +1 -1
- package/dist/elements/browser/suibi-module-latest.css +1 -1
- package/dist/elements/browser/suibi-module-latest.js +69 -69
- package/dist/elements/browser/{suibi-module.v0.1.0-preview.b3c1d3c.css → suibi-module.v0.1.0-preview.c3246cc.css} +1 -1
- package/dist/elements/browser/suibi-module.v0.1.0-preview.c3246cc.js +78 -0
- package/dist/elements/browser/version.txt +1 -1
- package/dist/elements/browser/wc-global-utilities.css +1 -1
- package/dist/types/app/components/data-preview/data-preview.component.d.ts +222 -0
- package/dist/types/app/components/inline-table/inline-table.component.d.ts +48 -3
- package/dist/types/app/components/inline-table/inline-table.types.d.ts +53 -2
- package/dist/types/app/core/navigation/navigation.service.d.ts +7 -0
- package/dist/types/app/core/planning/planning-balance.service.d.ts +6 -0
- package/dist/types/app/core/utils/custom-unit.util.d.ts +38 -0
- package/dist/types/app/core/utils/object.util.d.ts +5 -9
- package/dist/types/app/core/validation/ajv-custom.d.ts +1 -0
- package/dist/types/app/core/validation/global-validation.service.d.ts +2 -0
- package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-master-detail/farm-manure-trading-master-detail.component.d.ts +9 -15
- package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-table/farm-manure-trading-table.component.d.ts +35 -0
- package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-table/farm-manure-trading-table.config.d.ts +24 -0
- package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading.types.d.ts +4 -0
- package/dist/types/app/nutrient-cycle/farm-manure-trading/index.d.ts +2 -2
- package/dist/types/app/nutrient-cycle/farm-manure-trading/transaction-unit.util.d.ts +2 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/arable-land-table/arable-land-table.component.d.ts +3 -2
- package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation-master-detail/field-cultivation-master-detail.component.d.ts +1 -1
- package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation.types.d.ts +5 -1
- package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation.util.d.ts +4 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/fodder-cropland-table/fodder-cropland-table.component.d.ts +3 -2
- package/dist/types/app/nutrient-cycle/field-cultivation/special-crops-table/special-crops-table.component.d.ts +5 -5
- package/dist/types/app/nutrient-cycle/field-cultivation/special-crops-table/special-crops-table.config.d.ts +22 -32
- package/dist/types/app/nutrient-cycle/field-spreading/fertiliser-table/fertiliser-table.component.d.ts +16 -7
- package/dist/types/app/nutrient-cycle/field-spreading/field-spreading.component.d.ts +2 -0
- package/dist/types/app/nutrient-cycle/field-spreading/field-spreading.types.d.ts +1 -0
- package/dist/types/app/nutrient-cycle/field-spreading/recycling-table/recycling-table.component.d.ts +10 -9
- package/dist/types/app/nutrient-cycle/fodder/fodder-table/fodder-table.component.d.ts +5 -3
- package/package.json +1 -1
- package/dist/elements/browser/suibi-module.v0.1.0-preview.b3c1d3c.js +0 -78
- package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-detail/farm-manure-trading-detail.component.d.ts +0 -26
- package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-list/farm-manure-trading-list.component.d.ts +0 -22
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.0-preview.
|
|
1
|
+
0.1.0-preview.c3246cc c3246cc
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.cdk-overlay-container{position:fixed;inset:0;z-index:1200;pointer-events:none}.cdk-overlay-container:empty{display:none}.cdk-global-overlay-wrapper{position:fixed;inset:0;display:flex;align-items:flex-start;justify-content:center;pointer-events:none}.cdk-overlay-connected-position-bounding-box{position:absolute;z-index:1200;display:flex;flex-direction:column;min-width:1px;min-height:1px}.cdk-overlay-pane{position:absolute;pointer-events:auto;box-sizing:border-box;z-index:1200}.cdk-overlay-backdrop{position:fixed;inset:0;z-index:1199;pointer-events:auto}.cdk-overlay-transparent-backdrop{background:transparent}.cdk-overlay-dark-backdrop{background:#00000052}.mat-mdc-select-panel.mdc-menu-surface{background:#fff;--mdc-theme-surface: #fff;--mdc-menu-container-color: #fff;--mat-select-panel-background-color: #fff;box-shadow:0 4px 16px #00000040;border-radius:4px;outline:0;opacity:1!important;filter:none!important}
|
|
1
|
+
.cdk-overlay-container{position:fixed;inset:0;z-index:1200;pointer-events:none}.cdk-overlay-container:empty{display:none}.cdk-global-overlay-wrapper{position:fixed;inset:0;display:flex;align-items:flex-start;justify-content:center;pointer-events:none}.cdk-overlay-connected-position-bounding-box{position:absolute;z-index:1200;display:flex;flex-direction:column;min-width:1px;min-height:1px}.cdk-overlay-pane{position:absolute;pointer-events:auto;box-sizing:border-box;z-index:1200}.cdk-overlay-backdrop{position:fixed;inset:0;z-index:1199;pointer-events:auto}.cdk-overlay-transparent-backdrop{background:transparent}.cdk-overlay-dark-backdrop{background:#00000052}.mat-mdc-select-panel.mdc-menu-surface{background:#fff;--mdc-theme-surface: #fff;--mdc-menu-container-color: #fff;--mat-select-panel-background-color: #fff;box-shadow:0 4px 16px #00000040;border-radius:4px;outline:0;opacity:1!important;filter:none!important}.mat-mdc-option.mdc-list-item{height:auto;min-height:48px}.mat-mdc-option .mdc-list-item__primary-text{white-space:normal;overflow:visible;text-overflow:clip;line-height:1.35}
|
|
@@ -3,9 +3,231 @@ import { PlanningBalanceService } from '../../core/planning/planning-balance.ser
|
|
|
3
3
|
export declare class DataPreviewComponent {
|
|
4
4
|
private readonly host;
|
|
5
5
|
private readonly emitter;
|
|
6
|
+
private readonly clipboard;
|
|
6
7
|
readonly planning: PlanningBalanceService;
|
|
7
8
|
readonly naebi: NaebiDataService;
|
|
8
9
|
readonly metadataPreview: import("@angular/core").Signal<import("../../../public-api").SuibiDataEventMetadata>;
|
|
10
|
+
/** Exact payload that runPlanning will POST (same builder as the real request). */
|
|
11
|
+
readonly apiPayload: import("@angular/core").Signal<{
|
|
12
|
+
nutrientCycle: {
|
|
13
|
+
animalStock: {
|
|
14
|
+
order: string;
|
|
15
|
+
animalCategoryPRIF: number;
|
|
16
|
+
selfReportedLivestock: {
|
|
17
|
+
averageQuantity: number;
|
|
18
|
+
};
|
|
19
|
+
durationCorrectionQuantity: number;
|
|
20
|
+
durationCorrectionDays: number;
|
|
21
|
+
utilisation: number;
|
|
22
|
+
formOfDetention: {
|
|
23
|
+
hasGrazing: boolean;
|
|
24
|
+
pasture: {
|
|
25
|
+
days: number;
|
|
26
|
+
hoursPerDay: number;
|
|
27
|
+
};
|
|
28
|
+
stall: {
|
|
29
|
+
stableSystem: string;
|
|
30
|
+
stableVentilationType: number;
|
|
31
|
+
hasStableDeepLitter: boolean;
|
|
32
|
+
hasStableManureBeltDrying: boolean;
|
|
33
|
+
stableManureRemovalFrequency: number;
|
|
34
|
+
stableWaterSupply: number;
|
|
35
|
+
hasStableManureAndSlurryProduction: boolean;
|
|
36
|
+
hasStableFeedingStationElevated: boolean;
|
|
37
|
+
hasStableFloorSlopedUrineDrainage: boolean;
|
|
38
|
+
hasYard: boolean;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
hasImpexDerivedExcretion: boolean;
|
|
42
|
+
hasLinearCorrectionDerivedExcretion: boolean;
|
|
43
|
+
feeding: {
|
|
44
|
+
fodderConsumption: number;
|
|
45
|
+
concentratedFeedstuffConsumption: number;
|
|
46
|
+
concentratedFeedStuffConsumption: number;
|
|
47
|
+
winterFeeding: {
|
|
48
|
+
feedingRoutine: {
|
|
49
|
+
typeOfFeedstuffProduct: string;
|
|
50
|
+
transactionUnit: string;
|
|
51
|
+
quantity: number;
|
|
52
|
+
}[];
|
|
53
|
+
dailyConcentratedFeedstuff: {
|
|
54
|
+
quantity: number;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
summerFeeding: {
|
|
58
|
+
feedingRoutine: {
|
|
59
|
+
typeOfFeedstuffProduct: string;
|
|
60
|
+
transactionUnit: string;
|
|
61
|
+
quantity: number;
|
|
62
|
+
}[];
|
|
63
|
+
dailyConcentratedFeedstuff: {
|
|
64
|
+
quantity: number;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
}[];
|
|
69
|
+
storage: {
|
|
70
|
+
stableStrawLitter: number;
|
|
71
|
+
slurrySupplyProportionStored: number;
|
|
72
|
+
createFacilitySpecificManureProduct: boolean;
|
|
73
|
+
createFacilitySpecificSlurryProduct: boolean;
|
|
74
|
+
slurryTankQuantity: number;
|
|
75
|
+
dilutionRatio: number;
|
|
76
|
+
manurePit: never[];
|
|
77
|
+
slurryTank: {
|
|
78
|
+
descriptor: string;
|
|
79
|
+
volumeInM3: number;
|
|
80
|
+
depthInM: number;
|
|
81
|
+
cover: number;
|
|
82
|
+
mixingFrequency: number;
|
|
83
|
+
manureDerivation: string[];
|
|
84
|
+
}[];
|
|
85
|
+
};
|
|
86
|
+
farmManureTrading: {
|
|
87
|
+
supply: never[];
|
|
88
|
+
dispense: {
|
|
89
|
+
quantity: number;
|
|
90
|
+
typeOfManureRecyclingProduct: string;
|
|
91
|
+
transactionUnit: string;
|
|
92
|
+
manureDerivation: {
|
|
93
|
+
zoologicalAnimal: string;
|
|
94
|
+
percentageAllocation: number;
|
|
95
|
+
}[];
|
|
96
|
+
ingredient: {
|
|
97
|
+
quantity: number;
|
|
98
|
+
molecularFormula: string;
|
|
99
|
+
unit: string;
|
|
100
|
+
}[];
|
|
101
|
+
}[];
|
|
102
|
+
};
|
|
103
|
+
fieldSpreading: {
|
|
104
|
+
soilPh: number;
|
|
105
|
+
slurry: {
|
|
106
|
+
quantity: number;
|
|
107
|
+
dilutionRatio: number;
|
|
108
|
+
otherApplicationTechnologies: {
|
|
109
|
+
applicationTechnologyType: number;
|
|
110
|
+
proportionOfArea: number;
|
|
111
|
+
}[];
|
|
112
|
+
applicationDuringWarmDays: number;
|
|
113
|
+
proportionAppliedSummerMonths: number;
|
|
114
|
+
proportionAppliedOtherMonths: number;
|
|
115
|
+
proportionAppliedAfter6PM: number;
|
|
116
|
+
dragHoseAreaSize: number;
|
|
117
|
+
};
|
|
118
|
+
manure: {
|
|
119
|
+
applicationIncorporationTime: number;
|
|
120
|
+
proportionAppliedSummerMonths: number;
|
|
121
|
+
proportionAppliedOtherMonths: number;
|
|
122
|
+
};
|
|
123
|
+
fertiliser: {
|
|
124
|
+
descriptor: string;
|
|
125
|
+
fertiliserProductCategory: string;
|
|
126
|
+
quantity: number;
|
|
127
|
+
transactionUnit: string;
|
|
128
|
+
ingredient: {
|
|
129
|
+
molecularFormula: string;
|
|
130
|
+
quantity: number;
|
|
131
|
+
unit: string;
|
|
132
|
+
}[];
|
|
133
|
+
}[];
|
|
134
|
+
recycling: {
|
|
135
|
+
typeOfManureRecyclingProduct: string;
|
|
136
|
+
quantity: number;
|
|
137
|
+
transactionUnit: string;
|
|
138
|
+
ingredient: {
|
|
139
|
+
molecularFormula: string;
|
|
140
|
+
quantity: number;
|
|
141
|
+
unit: string;
|
|
142
|
+
}[];
|
|
143
|
+
}[];
|
|
144
|
+
};
|
|
145
|
+
lifetimePerformance: {
|
|
146
|
+
milkProductionReport: number;
|
|
147
|
+
};
|
|
148
|
+
fodder: {
|
|
149
|
+
trading: {
|
|
150
|
+
supply: {
|
|
151
|
+
typeOfFeedstuffProduct: string;
|
|
152
|
+
quantity: number;
|
|
153
|
+
transactionUnit: string;
|
|
154
|
+
ingredient: {
|
|
155
|
+
quantity: number;
|
|
156
|
+
molecularFormula: string;
|
|
157
|
+
unit: string;
|
|
158
|
+
}[];
|
|
159
|
+
}[];
|
|
160
|
+
dispense: {
|
|
161
|
+
typeOfFeedstuffProduct: string;
|
|
162
|
+
quantity: number;
|
|
163
|
+
transactionUnit: string;
|
|
164
|
+
ingredient: never[];
|
|
165
|
+
}[];
|
|
166
|
+
};
|
|
167
|
+
cropFromNonFodderCropland: {
|
|
168
|
+
typeOfFeedstuffProduct: string;
|
|
169
|
+
quantity: number;
|
|
170
|
+
transactionUnit: string;
|
|
171
|
+
ingredient: {
|
|
172
|
+
quantity: number;
|
|
173
|
+
molecularFormula: string;
|
|
174
|
+
unit: string;
|
|
175
|
+
}[];
|
|
176
|
+
}[];
|
|
177
|
+
proportionStorageLoss: number;
|
|
178
|
+
totalBalanceErrorMargin: number;
|
|
179
|
+
};
|
|
180
|
+
fieldCultivation: {
|
|
181
|
+
buildingZoneAreaSize: number;
|
|
182
|
+
outdoorVegetableMainCropAreaSize: number;
|
|
183
|
+
indoorVegetableMainCropAreaSize: number;
|
|
184
|
+
feedingOfCropHarvest: {
|
|
185
|
+
agronomicCropCategory: string;
|
|
186
|
+
effectiveYield: number;
|
|
187
|
+
}[];
|
|
188
|
+
dispenseOfCropHarvest: {
|
|
189
|
+
agronomicCropCategory: string;
|
|
190
|
+
effectiveYield: number;
|
|
191
|
+
}[];
|
|
192
|
+
fodderCropland: ({
|
|
193
|
+
agronomicCropCategory: string;
|
|
194
|
+
isMainCrop: boolean;
|
|
195
|
+
areaSize: number;
|
|
196
|
+
calculateYieldThroughFodderBalance: boolean;
|
|
197
|
+
yieldPerSquareMeasure?: undefined;
|
|
198
|
+
} | {
|
|
199
|
+
agronomicCropCategory: string;
|
|
200
|
+
isMainCrop: boolean;
|
|
201
|
+
areaSize: number;
|
|
202
|
+
yieldPerSquareMeasure: number;
|
|
203
|
+
calculateYieldThroughFodderBalance?: undefined;
|
|
204
|
+
})[];
|
|
205
|
+
arableLand: {
|
|
206
|
+
agronomicCropCategory: string;
|
|
207
|
+
isMainCrop: boolean;
|
|
208
|
+
areaSize: number;
|
|
209
|
+
yieldPerSquareMeasure: number;
|
|
210
|
+
hasLongTermYieldDivergence: boolean;
|
|
211
|
+
}[];
|
|
212
|
+
special: {
|
|
213
|
+
agronomicCropCategory: string;
|
|
214
|
+
userSpecificPlantName: string;
|
|
215
|
+
isMainCrop: boolean;
|
|
216
|
+
areaSize: number;
|
|
217
|
+
requirementCorrection: {
|
|
218
|
+
quantity: number;
|
|
219
|
+
molecularFormula: string;
|
|
220
|
+
unit: string;
|
|
221
|
+
}[];
|
|
222
|
+
}[];
|
|
223
|
+
};
|
|
224
|
+
generateReport: boolean;
|
|
225
|
+
};
|
|
226
|
+
calculationVersion: {
|
|
227
|
+
version: string;
|
|
228
|
+
};
|
|
229
|
+
}>;
|
|
9
230
|
setPlanningEndpoint(value: string | null): void;
|
|
10
231
|
emitData(): void;
|
|
232
|
+
copyJson(getValue: () => unknown): void;
|
|
11
233
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MatCheckboxChange } from '@angular/material/checkbox';
|
|
2
2
|
import { BaseCodeListEntry } from '../../jsonforms/shared/option-sources/code-lists';
|
|
3
|
-
import { InlineColumnDef, InlineTableConfig } from './inline-table.types';
|
|
3
|
+
import { InlineColumnDef, InlineTableConfig, InlineCellErrorResolver } from './inline-table.types';
|
|
4
4
|
/**
|
|
5
5
|
* InlineTableComponent — generic inline-editable table for array-of-objects data.
|
|
6
6
|
*
|
|
@@ -27,6 +27,8 @@ import { InlineColumnDef, InlineTableConfig } from './inline-table.types';
|
|
|
27
27
|
*/
|
|
28
28
|
export declare class InlineTableComponent {
|
|
29
29
|
private readonly i18n;
|
|
30
|
+
private readonly host;
|
|
31
|
+
constructor();
|
|
30
32
|
/** Table configuration — columns, labels, and the row factory. Acts as the "uischema". */
|
|
31
33
|
readonly config: import("@angular/core").InputSignal<InlineTableConfig>;
|
|
32
34
|
/** Current array of row objects. Each key maps to a column's `key` or sub-array path. */
|
|
@@ -39,17 +41,35 @@ export declare class InlineTableComponent {
|
|
|
39
41
|
/**
|
|
40
42
|
* Optional business-logic transform applied after every cell edit — before emission.
|
|
41
43
|
*
|
|
42
|
-
* Signature: `(changedKey, newValue, updatedRow) => transformedRow`
|
|
44
|
+
* Signature: `(changedKey, newValue, updatedRow, previousRow) => transformedRow`
|
|
43
45
|
*
|
|
44
46
|
* - `changedKey`: the `InlineColumnDef.key` of the edited column.
|
|
45
47
|
* - `newValue`: the raw new value (string, number, or null).
|
|
46
48
|
* - `updatedRow`: the row object already reflecting the edit.
|
|
49
|
+
* - `previousRow`: the row as it was before the edit — needed when the side-effect
|
|
50
|
+
* depends on the replaced value (e.g. converting a quantity on a unit switch).
|
|
47
51
|
* - Return the row (possibly further mutated) that should be stored.
|
|
48
52
|
*
|
|
49
53
|
* Use this for cross-field side-effects such as pre-populating nutrient % columns
|
|
50
54
|
* when a product is selected. For forms without such logic, omit this input.
|
|
51
55
|
*/
|
|
52
|
-
readonly rowTransform: import("@angular/core").InputSignal<((changedKey: string, newValue: unknown, row: Record<string, unknown>) => Record<string, unknown>) | null>;
|
|
56
|
+
readonly rowTransform: import("@angular/core").InputSignal<((changedKey: string, newValue: unknown, row: Record<string, unknown>, previousRow?: Record<string, unknown>) => Record<string, unknown>) | null>;
|
|
57
|
+
/**
|
|
58
|
+
* Optional per-cell validation resolver — returns a translated error message
|
|
59
|
+
* shown under the cell (cell turns red via `mat-form-field-invalid`), or `null`
|
|
60
|
+
* when valid. Inline tables bypass JSONForms/AJV, so business rules that must
|
|
61
|
+
* be visible while typing (e.g. percentage caps) are surfaced through this hook.
|
|
62
|
+
*/
|
|
63
|
+
readonly cellError: import("@angular/core").InputSignal<InlineCellErrorResolver | null>;
|
|
64
|
+
/**
|
|
65
|
+
* Index of the row to visually highlight (e.g. after a validation-error deep-link).
|
|
66
|
+
* Also triggers a scrollIntoView so the row is on screen.
|
|
67
|
+
*/
|
|
68
|
+
readonly highlightRowIndex: import("@angular/core").InputSignal<number | null>;
|
|
69
|
+
/** Resolves the per-cell error message via the optional `cellError` input (null = valid). */
|
|
70
|
+
errorForCell(row: Record<string, unknown>, col: InlineColumnDef): string | null;
|
|
71
|
+
/** True when any column of the row reports an error — drives the row-level red tint. */
|
|
72
|
+
rowHasError(row: Record<string, unknown>): boolean;
|
|
53
73
|
/** Extracts a px value from a grid-format width string (e.g. 'minmax(120px, 1fr)' → '120px'). */
|
|
54
74
|
colMinWidth(width?: string): string;
|
|
55
75
|
/** Total table width = sum of all column px values + 40px for the delete column. */
|
|
@@ -106,6 +126,31 @@ export declare class InlineTableComponent {
|
|
|
106
126
|
addRow(): void;
|
|
107
127
|
/** Removes the row at `idx` from the array. */
|
|
108
128
|
removeRow(idx: number): void;
|
|
129
|
+
/** Ids of the expanded sub-rows panels, keyed `${rowIdx}:${col.key}` (UI-only state). */
|
|
130
|
+
private readonly expandedSubrows;
|
|
131
|
+
isSubrowsExpanded(rowIdx: number, col: InlineColumnDef): boolean;
|
|
132
|
+
toggleSubrows(rowIdx: number, col: InlineColumnDef): void;
|
|
133
|
+
/** Reads the nested key/value entries of a sub-rows column (never null). */
|
|
134
|
+
getSubEntries(row: Record<string, unknown>, col: InlineColumnDef): Record<string, unknown>[];
|
|
135
|
+
/** Options for the key select of a sub-rows column. */
|
|
136
|
+
getSubrowOptions(col: InlineColumnDef): BaseCodeListEntry[];
|
|
137
|
+
/** Localized label for a sub-entry key (descriptor designation, id as fallback). */
|
|
138
|
+
subrowKeyLabel(col: InlineColumnDef, keyValue: unknown): string;
|
|
139
|
+
/** Collapsed-cell summary, e.g. "Bovins 25 %, Porcs 75 %" ('–' when empty). */
|
|
140
|
+
subrowsSummary(row: Record<string, unknown>, col: InlineColumnDef): string;
|
|
141
|
+
/** Sum of the value fields of all sub-entries. */
|
|
142
|
+
subEntryTotal(row: Record<string, unknown>, col: InlineColumnDef): number;
|
|
143
|
+
/** Whether the sub-entry values sum to the configured expected total. */
|
|
144
|
+
subEntryTotalOk(row: Record<string, unknown>, col: InlineColumnDef): boolean;
|
|
145
|
+
addSubEntry(rowIdx: number, col: InlineColumnDef): void;
|
|
146
|
+
removeSubEntry(rowIdx: number, col: InlineColumnDef, subIdx: number): void;
|
|
147
|
+
onSubEntryKeyChange(rowIdx: number, col: InlineColumnDef, subIdx: number, value: unknown): void;
|
|
148
|
+
/** Commits on every keystroke (not on blur) — same rationale as `onNumberChange`.
|
|
149
|
+
* When `expectedTotal` is set, the value is clamped to the remaining share so the
|
|
150
|
+
* sum can never exceed it; smaller intermediate keystrokes still go through. */
|
|
151
|
+
onSubEntryValueChange(rowIdx: number, col: InlineColumnDef, subIdx: number, event: Event): void;
|
|
152
|
+
/** Writes the sub-entry array back to the row, runs rowTransform, emits rowsChange. */
|
|
153
|
+
private updateSubEntries;
|
|
109
154
|
/**
|
|
110
155
|
* Core change handler: sets the new value on the row, applies the optional
|
|
111
156
|
* `rowTransform` for any cross-field side-effects, then emits the updated array.
|
|
@@ -15,8 +15,54 @@ import type { BaseCodeListEntry } from '../../jsonforms/shared/option-sources/co
|
|
|
15
15
|
/** Supported cell widget types. Extend with new literal types as needed.
|
|
16
16
|
* 'readonly' renders the resolved value as plain text (no input) — for columns
|
|
17
17
|
* that are fully derived from other fields and must not be user-editable.
|
|
18
|
-
* 'checkbox' renders a boolean mat-checkbox bound to a true/false row field.
|
|
19
|
-
|
|
18
|
+
* 'checkbox' renders a boolean mat-checkbox bound to a true/false row field.
|
|
19
|
+
* 'subrows' renders an expandable editor for a nested list of key/percentage
|
|
20
|
+
* pairs (e.g. manureDerivation[]) — see `InlineSubrowsConfig`. */
|
|
21
|
+
export type InlineCellType = 'select' | 'number' | 'text' | 'readonly' | 'checkbox' | 'subrows';
|
|
22
|
+
/**
|
|
23
|
+
* Per-cell validation resolver — returns a translated error message to display
|
|
24
|
+
* under the cell, or `null` when the cell is valid. Passed as the `cellError`
|
|
25
|
+
* input of InlineTableComponent for domain tables that bypass JSONForms/AJV
|
|
26
|
+
* (inline tables are not schema-validated, so business rules like percentage
|
|
27
|
+
* caps must be surfaced visually through this hook).
|
|
28
|
+
*/
|
|
29
|
+
export type InlineCellErrorResolver = (row: Record<string, unknown>, col: InlineColumnDef) => string | null;
|
|
30
|
+
/**
|
|
31
|
+
* Configuration for a `type: 'subrows'` column — an expandable editor for a nested
|
|
32
|
+
* array of `{ key, value }` entries (e.g. manureDerivation: zoologicalAnimal +
|
|
33
|
+
* percentageAllocation). The collapsed cell shows a joined summary; expanding it
|
|
34
|
+
* opens a floating panel with one select + number input per entry, an add button,
|
|
35
|
+
* and a total indicator (green when the sum matches `expectedTotal`).
|
|
36
|
+
*/
|
|
37
|
+
export interface InlineSubrowsConfig {
|
|
38
|
+
/** Path to the nested array on the row object (e.g. `'manureDerivation'`). */
|
|
39
|
+
arrayPath: string;
|
|
40
|
+
/** Field holding the code-list key in each sub-entry (e.g. `'zoologicalAnimal'`). */
|
|
41
|
+
keyField: string;
|
|
42
|
+
/** Key into the shared `CODE_LISTS` map for the key select options. */
|
|
43
|
+
keyCodeListKey: string;
|
|
44
|
+
/** i18n key for the key sub-column header inside the panel. */
|
|
45
|
+
keyLabelKey: string;
|
|
46
|
+
/** Field holding the numeric share in each sub-entry (e.g. `'percentageAllocation'`). */
|
|
47
|
+
valueField: string;
|
|
48
|
+
/** i18n key for the value sub-column header inside the panel. */
|
|
49
|
+
valueLabelKey: string;
|
|
50
|
+
/** i18n key for the "add sub-entry" button label. */
|
|
51
|
+
addLabelKey: string;
|
|
52
|
+
/** i18n key for the expand toggle label (collapsed state). */
|
|
53
|
+
expandLabelKey: string;
|
|
54
|
+
/** i18n key for the collapse toggle label (expanded state). */
|
|
55
|
+
collapseLabelKey: string;
|
|
56
|
+
/** i18n key for the total indicator label. */
|
|
57
|
+
totalLabelKey: string;
|
|
58
|
+
/** Expected sum of the value fields (e.g. 100) — the indicator turns green on exact
|
|
59
|
+
* match (no more, no less) and entered values are clamped so the sum never exceeds it. */
|
|
60
|
+
expectedTotal?: number;
|
|
61
|
+
/** Min for the value number input (default 0). */
|
|
62
|
+
valueMin?: number;
|
|
63
|
+
/** Max for the value number input (default: none). */
|
|
64
|
+
valueMax?: number;
|
|
65
|
+
}
|
|
20
66
|
/**
|
|
21
67
|
* Definition for a single column in an inline table.
|
|
22
68
|
*
|
|
@@ -124,6 +170,11 @@ export interface InlineColumnDef {
|
|
|
124
170
|
arrayKeyField?: string;
|
|
125
171
|
arrayKeyValue?: string;
|
|
126
172
|
arrayValueField?: string;
|
|
173
|
+
/**
|
|
174
|
+
* Sub-rows editor config — required when `type: 'subrows'`, ignored otherwise.
|
|
175
|
+
* Drives the expandable key/percentage pair editor (see `InlineSubrowsConfig`).
|
|
176
|
+
*/
|
|
177
|
+
subrows?: InlineSubrowsConfig;
|
|
127
178
|
}
|
|
128
179
|
/**
|
|
129
180
|
* Full configuration for one inline-table instance — the "uischema" equivalent.
|
|
@@ -58,6 +58,11 @@ export declare class NavigationService {
|
|
|
58
58
|
type: StorageEntryType;
|
|
59
59
|
index: number;
|
|
60
60
|
} | null>;
|
|
61
|
+
/** Selected field spreading row context (category/tab + row index) — used by validation deep-links */
|
|
62
|
+
readonly selectedFieldSpreadingDetail: import("@angular/core").WritableSignal<{
|
|
63
|
+
category: FieldSpreadingCategory;
|
|
64
|
+
index: number;
|
|
65
|
+
} | null>;
|
|
61
66
|
/** True if currently viewing animal stock detail (not list) */
|
|
62
67
|
readonly isAnimalStockDetailView: import("@angular/core").Signal<boolean>;
|
|
63
68
|
/** True if currently on animal stock page (list or detail) */
|
|
@@ -81,6 +86,8 @@ export declare class NavigationService {
|
|
|
81
86
|
navigateToFodderDetail(mode: FodderMode, index: number, category?: FodderCategory): void;
|
|
82
87
|
navigateToFodderList(): void;
|
|
83
88
|
navigateToFieldSpreading(category?: FieldSpreadingCategory): void;
|
|
89
|
+
/** Deep-link to a specific row of a field spreading tab (e.g. from a validation error). */
|
|
90
|
+
navigateToFieldSpreadingDetail(category: FieldSpreadingCategory, index: number): void;
|
|
84
91
|
navigateToFieldCultivationDetail(tab: Exclude<FieldCultivationTab, 'general'>, index: number): void;
|
|
85
92
|
navigateToFieldCultivationList(tab?: FieldCultivationTab): void;
|
|
86
93
|
navigateToStorageDetail(type: StorageEntryType, index: number): void;
|
|
@@ -33,6 +33,12 @@ export declare class PlanningBalanceService {
|
|
|
33
33
|
};
|
|
34
34
|
readonly selectedEndpoint: import("@angular/core").Signal<PlanningEndpoint>;
|
|
35
35
|
setSelectedEndpoint(endpoint: PlanningEndpoint): void;
|
|
36
|
+
/**
|
|
37
|
+
* Builds the exact payload posted to the planning API: calculationVersion stamped from
|
|
38
|
+
* the current metadata, empty ingredient/routine slots stripped, null optional fields
|
|
39
|
+
* and host-only fields removed, custom display units converted to base units.
|
|
40
|
+
*/
|
|
41
|
+
buildApiPayload(data: NaebiData): NaebiData;
|
|
36
42
|
/** Fire a new planning-balance request with the current NAEBI data payload. */
|
|
37
43
|
runPlanning(data: NaebiData, endpoint?: PlanningEndpoint): void;
|
|
38
44
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface CustomUnit {
|
|
2
|
+
/** Unit code stored on the row (e.g. 'ha', 't', 'dt'). */
|
|
3
|
+
code: string;
|
|
4
|
+
/** API base unit this custom unit converts to (e.g. 'm2', 'kg'). */
|
|
5
|
+
baseUnit: string;
|
|
6
|
+
/** Multiplier from the custom unit to its base unit (1 ha = 10'000 m2 → 10000). */
|
|
7
|
+
factor: number;
|
|
8
|
+
descriptor?: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
export declare const CUSTOM_UNITS: readonly CustomUnit[];
|
|
11
|
+
/** True when the unit code is a custom display unit (not an API base unit). */
|
|
12
|
+
export declare function isCustomUnit(unit: unknown): boolean;
|
|
13
|
+
/** Base unit a quantity can be converted to: the custom unit's `baseUnit`, or the unit
|
|
14
|
+
* itself when it already is a base (or unknown) unit. */
|
|
15
|
+
export declare function baseUnitOf(unit: string | null | undefined): string | null | undefined;
|
|
16
|
+
/** Custom units convertible to the given base unit (e.g. 'kg' → [t, dt]). */
|
|
17
|
+
export declare function customUnitsForBaseUnit(baseUnit: string): CustomUnit[];
|
|
18
|
+
/**
|
|
19
|
+
* Builds a filter (compatible with the inline table's `optionsFilter`) keeping only the
|
|
20
|
+
* units compatible with the given context base unit — i.e. the base unit itself plus its
|
|
21
|
+
* custom units. Pass a nullable base (e.g. derived from a product's matterState): `null`
|
|
22
|
+
* keeps the full list (nothing derived yet).
|
|
23
|
+
*
|
|
24
|
+
* Works on any entry shape exposing `id` (and `baseUnit` for custom units).
|
|
25
|
+
*/
|
|
26
|
+
export declare function unitOptionsForBaseUnit<T extends {
|
|
27
|
+
id: string | number;
|
|
28
|
+
}>(contextBaseUnit: string | null | undefined): (entry: T) => boolean;
|
|
29
|
+
/** Converts a quantity expressed in a custom unit to its base unit; pass-through for
|
|
30
|
+
* base/unknown units and null quantities. */
|
|
31
|
+
export declare function convertToBaseUnit(quantity: number | null | undefined, unit: string | null | undefined): {
|
|
32
|
+
quantity: number | null | undefined;
|
|
33
|
+
unit: string | null | undefined;
|
|
34
|
+
};
|
|
35
|
+
/** Converts a quantity between two units sharing the same base unit (kg ↔ t ↔ dt,
|
|
36
|
+
* m2 ↔ ha). Returns the quantity unchanged when either unit is missing or the units
|
|
37
|
+
* are incompatible (different base units). */
|
|
38
|
+
export declare function convertQuantityBetween(quantity: number | null | undefined, fromUnit: string | null | undefined, toUnit: string | null | undefined): number | null | undefined;
|
|
@@ -22,15 +22,6 @@ export declare function deepEqual(a: unknown, b: unknown): boolean;
|
|
|
22
22
|
* @returns A deep copy of the value
|
|
23
23
|
*/
|
|
24
24
|
export declare function deepClone<T>(value: T): T;
|
|
25
|
-
/**
|
|
26
|
-
* Recursively drops `ingredient[]` entries whose `quantity` is null/undefined.
|
|
27
|
-
*
|
|
28
|
-
* Inline tables (fertiliser/recycling) pre-populate every nutrient slot in `ingredient[]`
|
|
29
|
-
* so the UI always shows all formula columns, but slots the user never fills in stay as
|
|
30
|
-
* `{ molecularFormula, quantity: null, unit }`. The calculation API rejects any ingredient
|
|
31
|
-
* entry that's present but incomplete, so submitted payloads must omit those still-empty
|
|
32
|
-
* slots entirely rather than send them with a null quantity.
|
|
33
|
-
*/
|
|
34
25
|
export declare function stripIncompleteIngredients<T>(value: T): T;
|
|
35
26
|
/**
|
|
36
27
|
* Sanitizes the planning payload: the calculation API (OpenAPI, no `nullable: true`
|
|
@@ -43,6 +34,11 @@ export declare function stripIncompleteIngredients<T>(value: T): T;
|
|
|
43
34
|
* feedingOfCropHarvest, dispenseOfCropHarvest): any null property is dropped
|
|
44
35
|
* (fieldName, userSpecificPlantName, yieldPerSquareMeasure, effectiveYield, …)
|
|
45
36
|
* - `nutrientCycle.fodder.trading.<collection>[].quantity`: null → dropped
|
|
37
|
+
* - `nutrientCycle.animalStock[].feeding.(winter|summer)Feeding`: never-filled routine
|
|
38
|
+
* slots (`{}` rows pre-created by the inline tables) and null fields are dropped;
|
|
39
|
+
* a season — and `feeding` itself — is removed when nothing filled-in remains
|
|
40
|
+
* - `nutrientCycle.fieldSpreading`: null fields dropped (`soilPh`, `slurry.*`,
|
|
41
|
+
* `manure.*`); `slurry`/`manure` removed when nothing filled-in remains
|
|
46
42
|
*/
|
|
47
43
|
export declare function sanitizePlanningPayload(data: NaebiDataLike): NaebiDataLike;
|
|
48
44
|
/** Structural type so object.util stays free of a NaebiData import (circular-safe). */
|
|
@@ -9,6 +9,7 @@ import Ajv from 'ajv';
|
|
|
9
9
|
*
|
|
10
10
|
* Custom keywords:
|
|
11
11
|
* - `permittedStableSystem`: Validates stable system against animal category constraints
|
|
12
|
+
* - `proportionSum`: Validates the sum of one numeric field across array items
|
|
12
13
|
*
|
|
13
14
|
* @param options - Additional AJV options to merge with defaults
|
|
14
15
|
*/
|
|
@@ -25,6 +25,8 @@ export interface EnrichedValidationError extends ErrorObject {
|
|
|
25
25
|
targetFodderCategory?: FodderCategory;
|
|
26
26
|
/** Category tab inside field spreading */
|
|
27
27
|
targetFieldSpreadingCategory?: FieldSpreadingCategory;
|
|
28
|
+
/** Row index inside a field spreading tab (fertiliser/recycling) */
|
|
29
|
+
targetFieldSpreadingIndex?: number;
|
|
28
30
|
/** Category tab inside field cultivation */
|
|
29
31
|
targetFieldCultivationTab?: FieldCultivationTab;
|
|
30
32
|
/** Field cultivation detail index */
|
|
@@ -1,25 +1,19 @@
|
|
|
1
|
-
import { TradingMode } from '../farm-manure-trading-list/farm-manure-trading-list.component';
|
|
2
1
|
import { FarmManureTradingSupply, FarmManureTradingDispense } from '../farm-manure-trading.types';
|
|
2
|
+
/**
|
|
3
|
+
* Farm manure trading page — two inline tables (supply "Reprises" / dispense
|
|
4
|
+
* "Cessions") editing `nutrientCycle.farmManureTrading` directly. The former
|
|
5
|
+
* master-detail round-trip (list + JSONForms detail pane) was replaced by inline
|
|
6
|
+
* editing, so validation deep-links (`selectedFarmManureTrading`) are merely
|
|
7
|
+
* consumed and cleared — there is no detail pane left to open (fodder pattern).
|
|
8
|
+
*/
|
|
3
9
|
export declare class FarmManureTradingMasterDetailComponent {
|
|
4
10
|
private readonly dataSvc;
|
|
5
11
|
private readonly navigationSvc;
|
|
6
12
|
constructor();
|
|
7
13
|
readonly supplyRows: import("@angular/core").Signal<FarmManureTradingSupply[]>;
|
|
8
14
|
readonly dispenseRows: import("@angular/core").Signal<FarmManureTradingDispense[]>;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
readonly selectedDispenseIndex: import("@angular/core").WritableSignal<number | null>;
|
|
12
|
-
readonly currentDetail: import("@angular/core").Signal<FarmManureTradingSupply | null>;
|
|
13
|
-
readonly currentIndex: import("@angular/core").Signal<number | null>;
|
|
14
|
-
readonly detailOpen: import("@angular/core").Signal<boolean>;
|
|
15
|
-
readonly activeTabIndex: import("@angular/core").Signal<0 | 1>;
|
|
16
|
-
onTabChange(index: number): void;
|
|
17
|
-
openDetail(mode: TradingMode, index: number): void;
|
|
18
|
-
closeDetail(): void;
|
|
19
|
-
addEntry(mode: TradingMode): void;
|
|
20
|
-
deleteEntry(mode: TradingMode, index: number): void;
|
|
21
|
-
onDetailChange(payload: FarmManureTradingSupply | FarmManureTradingDispense): void;
|
|
22
|
-
private createEmptyEntry;
|
|
15
|
+
onSupplyChange(rows: FarmManureTradingSupply[]): void;
|
|
16
|
+
onDispenseChange(rows: FarmManureTradingDispense[]): void;
|
|
23
17
|
private patchRows;
|
|
24
18
|
private cloneTrading;
|
|
25
19
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { InlineTableConfig } from '../../../components/inline-table/inline-table.types';
|
|
2
|
+
import { FarmManureTradingMode } from '../../../core/navigation/navigation.service';
|
|
3
|
+
import { FarmManureTradingSupply, FarmManureTradingDispense } from '../farm-manure-trading.types';
|
|
4
|
+
type TradingRow = FarmManureTradingSupply | FarmManureTradingDispense;
|
|
5
|
+
/**
|
|
6
|
+
* FarmManureTradingTableComponent — thin wrapper around InlineTableComponent.
|
|
7
|
+
*
|
|
8
|
+
* Responsibilities:
|
|
9
|
+
* 1. Provides the per-mode column/section config (the "uischema").
|
|
10
|
+
* 2. Bridges typed `FarmManureTradingSupply[]`/`Dispense[]` to/from the generic
|
|
11
|
+
* `Record<string, unknown>[]` API of InlineTableComponent.
|
|
12
|
+
* 3. Supplies `deriveUnits` as a `rowTransform` — the base `transactionUnit` ('kg'/'m3')
|
|
13
|
+
* and every ingredient's `unit` ('kg/t'/'kg/m3') are derived from the selected
|
|
14
|
+
* product's matterState; the user may switch to a custom unit sharing the same base
|
|
15
|
+
* (t, dt for kg), which converts the entered quantity on the fly.
|
|
16
|
+
*/
|
|
17
|
+
export declare class FarmManureTradingTableComponent {
|
|
18
|
+
readonly mode: import("@angular/core").InputSignal<FarmManureTradingMode>;
|
|
19
|
+
readonly entries: import("@angular/core").InputSignal<TradingRow[]>;
|
|
20
|
+
readonly entriesChange: import("@angular/core").OutputEmitterRef<TradingRow[]>;
|
|
21
|
+
protected readonly config: import("@angular/core").Signal<InlineTableConfig>;
|
|
22
|
+
/** Cast typed entries to generic Record[] for InlineTableComponent. */
|
|
23
|
+
readonly rowsForTable: import("@angular/core").Signal<Record<string, unknown>[]>;
|
|
24
|
+
/** Cast generic output back to typed trading rows. */
|
|
25
|
+
onRowsChange(rows: Record<string, unknown>[]): void;
|
|
26
|
+
/**
|
|
27
|
+
* Row transform deriving the ingredient units from the product's matterState on each
|
|
28
|
+
* edit, and handling `transactionUnit`:
|
|
29
|
+
* - product change (or missing unit on legacy rows): reset to the derived base unit,
|
|
30
|
+
* - unit switch: convert the entered quantity from the previous to the new unit
|
|
31
|
+
* (both share the same base), so the transacted amount is preserved.
|
|
32
|
+
*/
|
|
33
|
+
readonly deriveUnits: (changedKey: string, newValue: unknown, row: Record<string, unknown>, previousRow?: Record<string, unknown>) => Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Column and section configuration for the Farm Manure Trading inline tables.
|
|
3
|
+
*
|
|
4
|
+
* This is the "uischema" for the supply ("Reprises") and dispense ("Cessions")
|
|
5
|
+
* tables — one InlineTableConfig per mode, mirroring recycling-table.config.ts.
|
|
6
|
+
* Columns:
|
|
7
|
+
* - Product: typeOfManureRecyclingProduct (code list filtered per mode)
|
|
8
|
+
* - Quantity: quantity (number)
|
|
9
|
+
* - Unit: transactionUnit (readonly — derived from the product's
|
|
10
|
+
* matterState, never user-editable, per the API spec)
|
|
11
|
+
* - Origin: manureDerivation[] (expandable key/share pair editor,
|
|
12
|
+
* expected total 100 %)
|
|
13
|
+
* - Nutrients: Ntot, Nsol (molecularFormula 'Nlos'), P₂O₅, K₂O, Mg read/written
|
|
14
|
+
* via the ingredient[] sub-array (same 5 nutrients as recycling).
|
|
15
|
+
* - Nutrient unit: readonly, derived from the product's matterState (kg/t | kg/m³).
|
|
16
|
+
*/
|
|
17
|
+
import type { InlineTableConfig } from '../../../components/inline-table/inline-table.types';
|
|
18
|
+
import type { FarmManureTradingMode } from '../../../core/navigation/navigation.service';
|
|
19
|
+
/** Nutrient formulas tracked per trading entry, in display order. 'Nlos' = soluble nitrogen
|
|
20
|
+
* (matches the `molecularFormula` enum from assets/master-data/substances.json — there is no 'NSol'). */
|
|
21
|
+
export declare const TRADING_NUTRIENT_COLUMNS: readonly ["Ntot", "Nlos", "P2O5", "K2O", "Mg"];
|
|
22
|
+
export type TradingNutrientFormula = (typeof TRADING_NUTRIENT_COLUMNS)[number];
|
|
23
|
+
/** Builds the inline-table config for one mode ('supply' | 'dispense'). */
|
|
24
|
+
export declare function createTradingTableConfig(mode: FarmManureTradingMode): InlineTableConfig;
|
|
@@ -10,6 +10,8 @@ export interface ManureDerivation {
|
|
|
10
10
|
export interface FarmManureTradingSupply {
|
|
11
11
|
quantity?: number;
|
|
12
12
|
typeOfManureRecyclingProduct?: string;
|
|
13
|
+
/** Host-only free text: persisted in the emitted dossier, stripped before API calls. */
|
|
14
|
+
productDesignation?: string;
|
|
13
15
|
transactionUnit?: string;
|
|
14
16
|
manureDerivation?: ManureDerivation[];
|
|
15
17
|
ingredient?: ManureIngredient[];
|
|
@@ -17,6 +19,8 @@ export interface FarmManureTradingSupply {
|
|
|
17
19
|
export interface FarmManureTradingDispense {
|
|
18
20
|
quantity?: number;
|
|
19
21
|
typeOfManureRecyclingProduct?: string;
|
|
22
|
+
/** Host-only free text: persisted in the emitted dossier, stripped before API calls. */
|
|
23
|
+
productDesignation?: string;
|
|
20
24
|
transactionUnit?: string;
|
|
21
25
|
manureDerivation?: ManureDerivation[];
|
|
22
26
|
ingredient?: ManureIngredient[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from './farm-manure-trading-
|
|
2
|
-
export * from './farm-manure-trading-
|
|
1
|
+
export * from './farm-manure-trading-table/farm-manure-trading-table.component';
|
|
2
|
+
export * from './farm-manure-trading-table/farm-manure-trading-table.config';
|
|
3
3
|
export * from './farm-manure-trading-master-detail/farm-manure-trading-master-detail.component';
|
|
4
4
|
export * from './farm-manure-trading.types';
|
|
@@ -1 +1,3 @@
|
|
|
1
1
|
export declare function deriveTransactionUnit(productCode: string | null | undefined): string | undefined;
|
|
2
|
+
/** Derives the mandatory ingredient unit ('kg/t' or 'kg/m3') from the product's matterState. */
|
|
3
|
+
export declare function deriveTradingIngredientUnit(productCode: string | null | undefined): string | undefined;
|