@osfarm/itineraire-technique 1.2.0 → 1.2.1
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/.github/copilot-instructions.md +56 -0
- package/.github/workflows/publish.yml +34 -0
- package/README.md +2 -34
- package/css/styles-editor.css +1 -1
- package/css/styles-editor.css.map +1 -1
- package/editor.html +38 -748
- package/js/chart-render.js +16 -11
- package/js/editor-interventions.js +315 -189
- package/js/editor-loader-default.js +238 -0
- package/js/editor-loader-itinera.js +135 -0
- package/js/{editor-wiki-editor.js → editor-loader-wiki.js} +99 -11
- package/js/editor-main.js +752 -0
- package/js/intervention.js +12 -0
- package/js/step-model.js +69 -0
- package/package.json +6 -59
- package/scss/styles-editor.scss +145 -0
- package/scss/styles-rendering.scss +184 -0
- package/examples/README.md +0 -137
- package/examples/nextjs-_document.tsx +0 -66
- package/examples/nextjs-api-route.ts +0 -122
- package/examples/nextjs-app-router-editor.tsx +0 -304
- package/examples/nextjs-app-router-viewer.tsx +0 -90
- package/js/editor-attributes.js +0 -99
- package/js/editor-crops.js +0 -136
- package/js/editor-export.js +0 -118
- package/react/QUICKSTART.md +0 -172
- package/react/README.md +0 -305
- package/react/TikaEditor.jsx +0 -212
- package/react/TikaRenderer.jsx +0 -116
- package/react/hooks.ts +0 -217
- package/react/index.ts +0 -19
- package/react/types.ts +0 -152
package/js/chart-render.js
CHANGED
|
@@ -132,6 +132,19 @@ class RotationRenderer {
|
|
|
132
132
|
this.currentFocusIndex = null;
|
|
133
133
|
this.noFocusUpdate = false;
|
|
134
134
|
|
|
135
|
+
// If some steps have the deprecated attribute field, we add them to the description:
|
|
136
|
+
self.data.steps.map(item => {
|
|
137
|
+
if (item.attributes?.length > 0) {
|
|
138
|
+
item.description += "\n\n";
|
|
139
|
+
item.attributes?.forEach(attr => {
|
|
140
|
+
item.description += `${attr.name} : ${attr.value}\n`;
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// remove the attributes field to avoid displaying
|
|
145
|
+
delete item.attributes;
|
|
146
|
+
});
|
|
147
|
+
|
|
135
148
|
if (self.initialLayout == 'horizontal')
|
|
136
149
|
option = this.getStepsOption();
|
|
137
150
|
else
|
|
@@ -425,13 +438,6 @@ class RotationRenderer {
|
|
|
425
438
|
item.name = "Etape " + item.name; // Force the item name to be a string
|
|
426
439
|
|
|
427
440
|
let description = self.getHTMLFormatedDescription(item.description);
|
|
428
|
-
if (item.interventions?.length > 0 || item.attributes?.length > 0) {
|
|
429
|
-
description += '<br/>';
|
|
430
|
-
item.attributes?.forEach(attr => {
|
|
431
|
-
description += `<br><b>${attr.name} :</b> ${attr.value}`;
|
|
432
|
-
});
|
|
433
|
-
}
|
|
434
|
-
|
|
435
441
|
|
|
436
442
|
data.push({
|
|
437
443
|
name: item.name,
|
|
@@ -819,7 +825,7 @@ class RotationRenderer {
|
|
|
819
825
|
self.data.steps.forEach((item, index) => {
|
|
820
826
|
|
|
821
827
|
let visibility = 'invisible';
|
|
822
|
-
if (item.interventions?.length > 0
|
|
828
|
+
if (item.interventions?.length > 0)
|
|
823
829
|
visibility = "visible";
|
|
824
830
|
|
|
825
831
|
let collapseButton = '<div class="collapse-button ' + visibility + '"><i class="fa fa-chevron-down" aria-hidden="true"></i></div>';
|
|
@@ -834,8 +840,7 @@ class RotationRenderer {
|
|
|
834
840
|
+ '<div class="step_dates">' + dates + '</div>'
|
|
835
841
|
+ '<h4 class="">' + item.name + '<i class="fa fa-pencil step-edit" aria-hidden="true"></i></h4>'
|
|
836
842
|
+ '</div><p class="step_description clearfix">' + self.getHTMLFormatedDescription(item.description) + '</p>'
|
|
837
|
-
+ '<div class="details">'
|
|
838
|
-
+ (item.attributes?.length > 0 ? item.attributes.map((attribute) => { return '<p><dt>' + attribute.name + '</dt><dd>' + attribute.value + '</dd></p>' }).join('') : '');
|
|
843
|
+
+ '<div class="details">';
|
|
839
844
|
|
|
840
845
|
if (item.interventions?.length > 0) {
|
|
841
846
|
html += '<h5>Interventions</h5>';
|
|
@@ -1109,7 +1114,7 @@ class RotationRenderer {
|
|
|
1109
1114
|
hideDelay: 1000,
|
|
1110
1115
|
extraCssText: "text-wrap: wrap;",
|
|
1111
1116
|
position: function (pos, params, el, elRect, size) {
|
|
1112
|
-
var obj = {
|
|
1117
|
+
var obj = { bottom: 10 };
|
|
1113
1118
|
obj[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 30;
|
|
1114
1119
|
return obj;
|
|
1115
1120
|
},
|
|
@@ -1,217 +1,343 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
document.getElementById("newInterventionButton").classList.remove("d-none");
|
|
14
|
-
getAndCleanElement("newInterventionContainer");
|
|
1
|
+
/**
|
|
2
|
+
* InterventionTable class - Manages interventions UI and interactions
|
|
3
|
+
*/
|
|
4
|
+
class InterventionTable {
|
|
5
|
+
|
|
6
|
+
// Constructor
|
|
7
|
+
constructor(interventionsTopTitle, interventionsBottomTitle, tikaEditorInstance) {
|
|
8
|
+
this.selectedStep = null;
|
|
9
|
+
|
|
10
|
+
this.interventionsTopTitle = interventionsTopTitle;
|
|
11
|
+
this.interventionsBottomTitle = interventionsBottomTitle;
|
|
12
|
+
this.tikaEditorInstance = tikaEditorInstance;
|
|
15
13
|
}
|
|
16
|
-
refreshAllTables();
|
|
17
|
-
}
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Setup the interventions table div dynamically
|
|
17
|
+
*/
|
|
18
|
+
setupDiv() {
|
|
19
|
+
|
|
20
|
+
// Check if the div already exists
|
|
21
|
+
if ($('#interventionsTable').length > 0) {
|
|
22
|
+
return; // Already created
|
|
23
|
+
}
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
const interventionsTableDiv = $(`
|
|
26
|
+
<div id="interventionsTable" class="row card-holder">
|
|
27
|
+
<div class="col-12">
|
|
28
|
+
<h5>Interventions</h5>
|
|
29
|
+
<div class="row">
|
|
30
|
+
<p id="interventionsTopName" class="h6">${this.interventionsTopTitle}</p>
|
|
31
|
+
<div id="interventionsTopContainer" class="container"></div>
|
|
32
|
+
</div>
|
|
33
|
+
<hr class="my-2">
|
|
34
|
+
<div class="row">
|
|
35
|
+
<p id="interventionsBottomName" class="h6">${this.interventionsBottomTitle}</p>
|
|
36
|
+
<div id="interventionsBottomContainer" class="container"></div>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<button id="newInterventionButton" type="button"
|
|
40
|
+
class="btn btn-primary primary-button w-100"><i class="fa fa-plus-square"
|
|
41
|
+
aria-hidden="true"></i> Ajouter</button>
|
|
42
|
+
<div id="newInterventionContainer"></div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
`);
|
|
46
|
+
|
|
47
|
+
// Insert after the step's details
|
|
48
|
+
$('#cropDetailView').after(interventionsTableDiv);
|
|
26
49
|
|
|
27
|
-
|
|
28
|
-
const rowDiv = createInterventionRow(intervention);
|
|
50
|
+
const self = this;
|
|
29
51
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
interventionsBottomContainer.appendChild(rowDiv);
|
|
34
|
-
}
|
|
52
|
+
$('#newInterventionButton').on('click', function(e) {
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
self.showInterventionForm();
|
|
35
55
|
});
|
|
36
56
|
}
|
|
37
|
-
}
|
|
38
57
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
selectedStep.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
58
|
+
getAndCleanElement(elementId) {
|
|
59
|
+
let element = document.getElementById(elementId);
|
|
60
|
+
element.innerHTML = "";
|
|
61
|
+
return element;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
refreshInterventionsTable(selectedStep) {
|
|
65
|
+
this.selectedStep = selectedStep;
|
|
66
|
+
|
|
67
|
+
let interventionsTopContainer = this.getAndCleanElement("interventionsTopContainer");
|
|
68
|
+
let interventionsBottomContainer = this.getAndCleanElement("interventionsBottomContainer");
|
|
69
|
+
|
|
70
|
+
if (this.selectedStep.getStep().interventions) {
|
|
71
|
+
// Sort all interventions by day
|
|
72
|
+
this.selectedStep.getStep().interventions = this.selectedStep.getStep().interventions.sort((a, b) => a.day - b.day);
|
|
73
|
+
|
|
74
|
+
this.selectedStep.getStep().interventions.forEach((intervention) => {
|
|
75
|
+
const rowDiv = this.createInterventionRow(intervention);
|
|
76
|
+
|
|
77
|
+
if (intervention.type === 'intervention_top') {
|
|
78
|
+
$("#interventionsTopContainer").append(rowDiv);
|
|
79
|
+
} else {
|
|
80
|
+
$("#interventionsBottomContainer").append(rowDiv);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
addEditAndRemoveButtons(rowDiv, deleteId, editFunction, deleteFunction, duplicateFunction, style="btn-group") {
|
|
87
|
+
rowDiv = $(rowDiv);
|
|
88
|
+
|
|
89
|
+
let actionContainer = $(`<div class="col-auto edit-buttons m-1 ${style}" role="group"></div>`);
|
|
90
|
+
|
|
91
|
+
rowDiv.append(actionContainer);
|
|
67
92
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
day: "numeric",
|
|
93
|
+
actionContainer.append($('<button class="edit-button btn btn-outline-primary p-2"><i class="fa fa-pencil"></i></button>').click(function(event) {
|
|
94
|
+
event.stopPropagation();
|
|
95
|
+
editFunction();
|
|
96
|
+
}));
|
|
97
|
+
|
|
98
|
+
rowDiv.find('.col').click(function(event) {
|
|
99
|
+
event.stopPropagation();
|
|
100
|
+
editFunction();
|
|
77
101
|
});
|
|
102
|
+
|
|
103
|
+
if (duplicateFunction != null) {
|
|
104
|
+
actionContainer.append($('<button class="btn btn-outline-secondary p-2"><i class="fa fa-copy"></i></button>').click(function (event) {
|
|
105
|
+
event.stopPropagation();
|
|
106
|
+
duplicateFunction(deleteId);
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
actionContainer.append($('<button class="btn btn-outline-danger p-2"><i class="fa fa-trash"></i></button>').click(function (event) {
|
|
111
|
+
event.stopPropagation();
|
|
112
|
+
deleteFunction(deleteId);
|
|
113
|
+
}));
|
|
78
114
|
}
|
|
79
|
-
|
|
80
|
-
let nameValueDiv = document.createElement("div");
|
|
81
|
-
nameValueDiv.className = "col";
|
|
82
|
-
nameValueDiv.innerHTML = `<strong>${intervention.name}</strong> (${absoluteDate})</br> ${intervention.description}`;
|
|
83
115
|
|
|
84
|
-
|
|
85
|
-
|
|
116
|
+
createInterventionRow(intervention) {
|
|
117
|
+
const self = this;
|
|
118
|
+
let rowDiv = document.createElement("div");
|
|
119
|
+
rowDiv.className = "row mb-2 intervention-row editable-row position-relative";
|
|
120
|
+
rowDiv.id = `interventionRow_${intervention.id}`;
|
|
86
121
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
122
|
+
let nameValueDiv = self.createInterventionNameAndValueColumn(intervention);
|
|
123
|
+
rowDiv.appendChild(nameValueDiv);
|
|
124
|
+
|
|
125
|
+
this.addEditAndRemoveButtons(
|
|
126
|
+
rowDiv,
|
|
127
|
+
intervention.id,
|
|
128
|
+
function () {
|
|
129
|
+
self.showInterventionForm(intervention, rowDiv);
|
|
130
|
+
},
|
|
131
|
+
function(id) {
|
|
132
|
+
self.selectedStep.removeIntervention(id);
|
|
133
|
+
$(`#interventionRow_${id}`).remove();
|
|
134
|
+
self.tikaEditorInstance.renderChart();
|
|
135
|
+
},
|
|
136
|
+
function(id) {
|
|
137
|
+
const newIntervention = self.duplicateIntervention(id);
|
|
138
|
+
const div = self.createInterventionRow(newIntervention);
|
|
139
|
+
if (newIntervention.type === 'intervention_top') {
|
|
140
|
+
$("#interventionsTopContainer").append(div);
|
|
141
|
+
} else {
|
|
142
|
+
$("#interventionsBottomContainer").append(div);
|
|
143
|
+
}
|
|
144
|
+
self.tikaEditorInstance.renderChart();
|
|
145
|
+
},
|
|
146
|
+
'btn-group-vertical'
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
return rowDiv;
|
|
104
150
|
}
|
|
105
151
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
<input type="number" id="interventionDay" class="form-control text-right" placeholder="Jour"
|
|
122
|
-
value="${day}">
|
|
123
|
-
</div>
|
|
124
|
-
<div class="col-8 mb-2">
|
|
125
|
-
<label for="interventionDate" class="form-label">Date absolue</label>
|
|
126
|
-
<input type="date" id="interventionDate" class="form-control" value="${absoluteDate}">
|
|
127
|
-
</div>
|
|
128
|
-
<div class="col-12 mb-2">
|
|
129
|
-
<select id="interventionType" class="form-select" aria-label="Type">
|
|
130
|
-
<option value="intervention_top"
|
|
131
|
-
${type === "intervention_top" ? "selected" : ""}>${crops.options.title_top_interventions}</option>
|
|
132
|
-
<option value="intervention_bottom"
|
|
133
|
-
${type === "intervention_bottom" ? "selected" : ""}>${crops.options.title_bottom_interventions}</option>
|
|
134
|
-
</select>
|
|
135
|
-
</div>
|
|
152
|
+
createInterventionNameAndValueColumn(intervention) {
|
|
153
|
+
let absoluteDate = "";
|
|
154
|
+
if (this.selectedStep && this.selectedStep.getStep().startDate) {
|
|
155
|
+
const stepStartDate = new Date(this.selectedStep.getStep().startDate);
|
|
156
|
+
const interventionDate = new Date(stepStartDate);
|
|
157
|
+
interventionDate.setDate(stepStartDate.getDate() + parseInt(intervention.day));
|
|
158
|
+
absoluteDate = interventionDate.toLocaleDateString('fr-FR', {
|
|
159
|
+
month: "short",
|
|
160
|
+
day: "numeric",
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let nameValueDiv = document.createElement("div");
|
|
165
|
+
nameValueDiv.className = "col";
|
|
166
|
+
nameValueDiv.innerHTML = `<strong>${intervention.name}</strong> (${absoluteDate})</br> ${intervention.description}`;
|
|
136
167
|
|
|
137
|
-
|
|
138
|
-
<button type="button" onclick="addInterventionClickEvent()"
|
|
139
|
-
class="w-100 btn btn-outline-primary primary-button">Valider</button>
|
|
140
|
-
</div>
|
|
141
|
-
</div>
|
|
142
|
-
</form>
|
|
143
|
-
`;
|
|
144
|
-
|
|
145
|
-
if (row) { //we are editing an intervention
|
|
146
|
-
row.replaceWith(formContainer);
|
|
147
|
-
} else { //we are adding an intervention
|
|
148
|
-
document.getElementById("newInterventionContainer").appendChild(formContainer);
|
|
149
|
-
document.getElementById("newInterventionButton").classList.add("d-none");
|
|
168
|
+
return nameValueDiv;
|
|
150
169
|
}
|
|
151
170
|
|
|
152
|
-
|
|
153
|
-
|
|
171
|
+
showInterventionForm(intervention, row) {
|
|
172
|
+
const self = this;
|
|
173
|
+
let id = intervention?.id || "";
|
|
174
|
+
let day = intervention?.day || "";
|
|
175
|
+
let name = intervention?.name || "";
|
|
176
|
+
let type = intervention?.type || "";
|
|
177
|
+
let description = intervention?.description || "";
|
|
154
178
|
|
|
155
|
-
|
|
156
|
-
|
|
179
|
+
// Calculate absolute date from relative day
|
|
180
|
+
let absoluteDate = "";
|
|
181
|
+
if (day === "")
|
|
182
|
+
day = 0;
|
|
183
|
+
|
|
184
|
+
if (this.selectedStep && this.selectedStep.getStep().startDate) {
|
|
185
|
+
const stepStartDate = new Date(this.selectedStep.getStep().startDate);
|
|
186
|
+
const interventionDate = new Date(stepStartDate);
|
|
187
|
+
interventionDate.setDate(stepStartDate.getDate() + parseInt(day));
|
|
188
|
+
absoluteDate = interventionDate.toISOString().split('T')[0];
|
|
189
|
+
}
|
|
157
190
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
191
|
+
const formContainer = document.createElement("div");
|
|
192
|
+
formContainer.innerHTML =
|
|
193
|
+
`<form id="interventionForm">
|
|
194
|
+
<div class="row card-white mb-2">
|
|
195
|
+
<input type="hidden" id="interventionId" value="${id}">
|
|
196
|
+
<div class="col-12 mb-2">
|
|
197
|
+
<label for="interventionName" class="form-label">Nom</label>
|
|
198
|
+
<input type="text" id="interventionName" class="form-control" placeholder="Nom" value="${name}">
|
|
199
|
+
</div>
|
|
200
|
+
<div class="col-12 mb-2">
|
|
201
|
+
<textarea id="interventionDescription" class="form-control"
|
|
202
|
+
placeholder="Ajouter une description">${description}</textarea>
|
|
203
|
+
</div>
|
|
204
|
+
<div class="col-4 mb-2">
|
|
205
|
+
<label for="interventionDay" class="form-label">Jour relatif</label>
|
|
206
|
+
<input type="number" id="interventionDay" class="form-control text-right" placeholder="Jour"
|
|
207
|
+
value="${day}">
|
|
208
|
+
</div>
|
|
209
|
+
<div class="col-8 mb-2">
|
|
210
|
+
<label for="interventionDate" class="form-label">Date absolue</label>
|
|
211
|
+
<input type="date" id="interventionDate" class="form-control" value="${absoluteDate}">
|
|
212
|
+
</div>
|
|
213
|
+
<div class="col-12 mb-2">
|
|
214
|
+
<select id="interventionType" class="form-select" aria-label="Type">
|
|
215
|
+
<option value="intervention_top"
|
|
216
|
+
${type === "intervention_top" ? "selected" : ""}>${this.interventionsTopTitle}</option>
|
|
217
|
+
<option value="intervention_bottom"
|
|
218
|
+
${type === "intervention_bottom" ? "selected" : ""}>${this.interventionsBottomTitle}</option>
|
|
219
|
+
</select>
|
|
220
|
+
</div>
|
|
163
221
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
222
|
+
<div class="col">
|
|
223
|
+
<button type="button" class="ValidateInterventionFormButton w-100 btn btn-outline-primary primary-button">Valider</button>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
</form>
|
|
227
|
+
`;
|
|
169
228
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
229
|
+
// Add the addInterventionClickEvent listener to the button
|
|
230
|
+
const form = $(formContainer);
|
|
231
|
+
form.find(".ValidateInterventionFormButton").on("click", (e) => {
|
|
232
|
+
e.preventDefault();
|
|
174
233
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
234
|
+
let id = form.find("#interventionId").val();
|
|
235
|
+
let name = form.find("#interventionName").val();
|
|
236
|
+
let day = form.find("#interventionDay").val();
|
|
237
|
+
let type = form.find("#interventionType").val();
|
|
238
|
+
let description = form.find("#interventionDescription").val();
|
|
239
|
+
|
|
240
|
+
if (id != "") {
|
|
241
|
+
intervention.name = name;
|
|
242
|
+
intervention.day = day;
|
|
243
|
+
intervention.type = type;
|
|
244
|
+
intervention.description = description;
|
|
245
|
+
|
|
246
|
+
// Also update the row display
|
|
247
|
+
const updatedRowDiv = this.createInterventionRow(this.selectedStep.getStep().interventions.find(itv => itv.id === id));
|
|
248
|
+
$(formContainer).replaceWith(updatedRowDiv);
|
|
249
|
+
|
|
250
|
+
} else {
|
|
251
|
+
this.selectedStep.addIntervention(day, name, type, description);
|
|
252
|
+
|
|
253
|
+
$("#newInterventionButton").show();
|
|
254
|
+
this.getAndCleanElement("newInterventionContainer");
|
|
184
255
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
256
|
+
// Add the new intervention to the table
|
|
257
|
+
const newIntervention = this.selectedStep.getStep().interventions[this.selectedStep.getStep().interventions.length - 1];
|
|
258
|
+
const newRowDiv = this.createInterventionRow(newIntervention);
|
|
259
|
+
if (newIntervention.type === 'intervention_top') {
|
|
260
|
+
$("#interventionsTopContainer").append(newRowDiv);
|
|
261
|
+
} else {
|
|
262
|
+
$("#interventionsBottomContainer").append(newRowDiv);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Remove the form
|
|
266
|
+
formContainer.remove();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
self.tikaEditorInstance.renderChart();
|
|
270
|
+
});
|
|
190
271
|
|
|
191
|
-
//
|
|
192
|
-
|
|
193
|
-
|
|
272
|
+
if (row) { //we are editing an intervention
|
|
273
|
+
row.replaceWith(formContainer);
|
|
274
|
+
} else { //we are adding an intervention
|
|
275
|
+
$("#newInterventionContainer").append(formContainer);
|
|
276
|
+
$("#newInterventionButton").hide();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Add event listeners for date synchronization
|
|
280
|
+
// When relative day changes, update absolute date
|
|
281
|
+
form.find("#interventionDay").on("input change", function() {
|
|
282
|
+
self.updateAbsoluteDateFromRelative();
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// When absolute date changes, update relative day
|
|
286
|
+
form.find("#interventionDate").on("change", function() {
|
|
287
|
+
self.updateRelativeDayFromAbsolute();
|
|
288
|
+
});
|
|
194
289
|
|
|
195
|
-
|
|
290
|
+
form.find("#interventionName").focus();
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
updateAbsoluteDateFromRelative() {
|
|
294
|
+
const relativeDay = $("#interventionDay").val();
|
|
295
|
+
if (relativeDay == "")
|
|
296
|
+
relativeDay = 0;
|
|
297
|
+
|
|
298
|
+
if (this.selectedStep && this.selectedStep.getStep().startDate) {
|
|
299
|
+
const stepStartDate = new Date(this.selectedStep.getStep().startDate);
|
|
300
|
+
const interventionDate = new Date(stepStartDate);
|
|
301
|
+
interventionDate.setDate(stepStartDate.getDate() + parseInt(relativeDay));
|
|
302
|
+
|
|
303
|
+
const absoluteDateStr = interventionDate.toISOString().split('T')[0];
|
|
304
|
+
$("#interventionDate").val(absoluteDateStr);
|
|
305
|
+
}
|
|
196
306
|
}
|
|
197
|
-
}
|
|
198
307
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
308
|
+
updateRelativeDayFromAbsolute() {
|
|
309
|
+
const absoluteDate = $("#interventionDate").val();
|
|
310
|
+
if (absoluteDate !== "" && this.selectedStep && this.selectedStep.getStep().startDate) {
|
|
311
|
+
const stepStartDate = new Date(this.selectedStep.getStep().startDate);
|
|
312
|
+
const interventionDate = new Date(absoluteDate);
|
|
313
|
+
|
|
314
|
+
// Calculate difference in days
|
|
315
|
+
const timeDiff = interventionDate.getTime() - stepStartDate.getTime();
|
|
316
|
+
const dayDiff = Math.round(timeDiff / (1000 * 60 * 60 * 24));
|
|
317
|
+
|
|
318
|
+
$("#interventionDay").val(dayDiff);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
duplicateIntervention(interventionId) {
|
|
323
|
+
if (!this.selectedStep) return;
|
|
324
|
+
|
|
325
|
+
// Find the intervention to duplicate
|
|
326
|
+
let originalIntervention = this.selectedStep.getStep().interventions.find(interv => interv.id === interventionId);
|
|
327
|
+
if (!originalIntervention) return;
|
|
328
|
+
|
|
329
|
+
// Create a copy of the intervention
|
|
330
|
+
let newIntervention = {
|
|
331
|
+
id: crypto.randomUUID(),
|
|
332
|
+
day: Number(originalIntervention.day) + 15, // Offset by 15 days to avoid overlap
|
|
333
|
+
name: originalIntervention.name,
|
|
334
|
+
type: originalIntervention.type,
|
|
335
|
+
description: originalIntervention.description
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
// Add the duplicated intervention to the selected step
|
|
339
|
+
this.selectedStep.getStep().interventions.push(newIntervention);
|
|
340
|
+
|
|
341
|
+
return newIntervention;
|
|
342
|
+
}
|
|
343
|
+
}
|