@osfarm/itineraire-technique 1.1.4 → 1.1.6
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/README.md +16 -2
- package/css/styles-editor.css +1 -1
- package/css/styles-editor.css.map +1 -1
- package/editor.html +13 -0
- package/images/Logo Triple Performance - blanc - vectoriel.svg +1 -0
- package/images/Tika.svg +7 -0
- package/index.html +353 -0
- package/js/chart-render.js +177 -103
- package/js/editor-crops.js +1 -0
- package/js/editor-interventions.js +63 -3
- package/package.json +1 -1
- package/scss/styles-editor.scss +10 -0
- package/test/test donut no transcript.json +324 -0
- package/test/test horizontal no transcript.json +324 -0
- package/test/test.json +424 -320
- package/images/rendu_frise.png +0 -0
- package/images/rendu_rotation.png +0 -0
package/js/chart-render.js
CHANGED
|
@@ -35,14 +35,14 @@ class RotationRenderer {
|
|
|
35
35
|
<div class="col-auto left-transcript"><div class="transcript"></div></div>
|
|
36
36
|
<div class="col col-auto chart-div"><div class="charts"></div></div>
|
|
37
37
|
<div class="col col-12 bottom-transcript"><div class="transcript"></div></div>
|
|
38
|
-
</div>`);
|
|
38
|
+
</div>`);
|
|
39
39
|
}
|
|
40
40
|
} else {
|
|
41
41
|
if (this.itk_container.find('.mainITKContainer').length == 0) {
|
|
42
42
|
this.itk_container.append(`<div class="row mainITKContainer">
|
|
43
43
|
<div class="col col-12 chart-div"><div class="charts"></div></div>
|
|
44
|
-
</div>`);
|
|
45
|
-
}
|
|
44
|
+
</div>`);
|
|
45
|
+
}
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
@@ -278,6 +278,8 @@ class RotationRenderer {
|
|
|
278
278
|
let self = this;
|
|
279
279
|
let data = [];
|
|
280
280
|
|
|
281
|
+
let bHasSecondaryCrops = steps.some(item => item.secondary_crop);
|
|
282
|
+
|
|
281
283
|
steps.forEach((item, index) => {
|
|
282
284
|
if (item.name == Number(item.name))
|
|
283
285
|
item.name = "Etape " + item.name; // Force the item name to be a string
|
|
@@ -295,7 +297,9 @@ class RotationRenderer {
|
|
|
295
297
|
item.startDate.valueOf(), // Date de début
|
|
296
298
|
item.endDate.valueOf(), // Date de fin
|
|
297
299
|
item.name, // Nom
|
|
298
|
-
'rotation_item' // Type
|
|
300
|
+
'rotation_item', // Type
|
|
301
|
+
item.secondary_crop ? true : false,
|
|
302
|
+
bHasSecondaryCrops ? true : false
|
|
299
303
|
],
|
|
300
304
|
itemStyle: {
|
|
301
305
|
color: item.color
|
|
@@ -316,7 +320,7 @@ class RotationRenderer {
|
|
|
316
320
|
intervention.type == 'intervention_top' ? 'intervention_top' : 'intervention_bottom' // Type
|
|
317
321
|
],
|
|
318
322
|
divId: 'Intervention_' + index + '_' + interventionIndex,
|
|
319
|
-
interventionDate: new Date(item.startDate.valueOf()),
|
|
323
|
+
interventionDate: new Date(item.startDate.valueOf() + intervention.day * 86400000),
|
|
320
324
|
interventionDays: intervention.day,
|
|
321
325
|
itemStyle: {
|
|
322
326
|
color: item.color
|
|
@@ -327,6 +331,55 @@ class RotationRenderer {
|
|
|
327
331
|
}
|
|
328
332
|
});
|
|
329
333
|
|
|
334
|
+
function wrapText(echarts, text, maxWidth, maxHeight) {
|
|
335
|
+
const words = text.split(' ');
|
|
336
|
+
let line = '';
|
|
337
|
+
let lines = [];
|
|
338
|
+
|
|
339
|
+
for (let word of words) {
|
|
340
|
+
const testLine = line + word + ' ';
|
|
341
|
+
let testWidth = echarts.format.getTextRect(testLine).width;
|
|
342
|
+
if (testWidth > maxWidth && line !== '') {
|
|
343
|
+
lines.push(line);
|
|
344
|
+
line = word + ' ';
|
|
345
|
+
} else {
|
|
346
|
+
line = testLine;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Avoid words that are too long
|
|
350
|
+
testWidth = echarts.format.getTextRect(line).width;
|
|
351
|
+
while (testWidth > maxWidth) {
|
|
352
|
+
line = line.slice(0, -1);
|
|
353
|
+
testWidth = echarts.format.getTextRect(line).width;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (line.length > 0) {
|
|
358
|
+
lines.push(line);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
let wrapped = '';
|
|
362
|
+
let wrappedText = false;
|
|
363
|
+
lines.forEach(l => {
|
|
364
|
+
if (wrappedText)
|
|
365
|
+
return;
|
|
366
|
+
|
|
367
|
+
let test = wrapped + l;
|
|
368
|
+
if (echarts.format.getTextRect(test).height > maxHeight)
|
|
369
|
+
{
|
|
370
|
+
wrappedText = true;
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
wrapped += l + "\n";
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
if (wrappedText) {
|
|
378
|
+
return wrapped.trim() + '...';
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return lines.join("\n");
|
|
382
|
+
}
|
|
330
383
|
|
|
331
384
|
let maxXPositions = new Map();
|
|
332
385
|
|
|
@@ -337,6 +390,8 @@ class RotationRenderer {
|
|
|
337
390
|
var end = api.coord([api.value(2), categoryIndex]);
|
|
338
391
|
var name = api.value(3);
|
|
339
392
|
var type = api.value(4);
|
|
393
|
+
let secondary_crop = api.value(5);
|
|
394
|
+
let bHasSecondaryCrops = api.value(6);
|
|
340
395
|
|
|
341
396
|
const x = start[0];
|
|
342
397
|
let y = start[1];
|
|
@@ -373,25 +428,45 @@ class RotationRenderer {
|
|
|
373
428
|
// params.coordSys.width, // largeur du canva
|
|
374
429
|
// params.coordSys.height // hauteur du canva
|
|
375
430
|
|
|
376
|
-
|
|
431
|
+
let height = self.barHeight - 20; // 20 px margin top and bottom
|
|
432
|
+
let top = y - height / 2;
|
|
433
|
+
let textXMargin = 2;
|
|
434
|
+
let textYMargin = 10;
|
|
435
|
+
|
|
436
|
+
if (bHasSecondaryCrops) {
|
|
437
|
+
height = self.barHeight - 40; // 20 px margin top and bottom
|
|
438
|
+
top = y - height / 2 - 15;
|
|
439
|
+
textXMargin = 2;
|
|
440
|
+
textYMargin = 10;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if (secondary_crop) {
|
|
444
|
+
// Move secondary crops a bit down and reduce their size
|
|
445
|
+
top = top + height + 5;
|
|
446
|
+
height = height / 3;
|
|
447
|
+
textXMargin = 5;
|
|
448
|
+
textYMargin = 5;
|
|
449
|
+
}
|
|
450
|
+
|
|
377
451
|
const arrowWidth = height / 3;
|
|
378
452
|
const border = 3;
|
|
379
|
-
const textMargin = 10;
|
|
380
453
|
|
|
381
454
|
var points = [
|
|
382
|
-
[x,
|
|
383
|
-
[end[0] - border,
|
|
384
|
-
[end[0] + arrowWidth - border,
|
|
385
|
-
[end[0] - border,
|
|
386
|
-
[x,
|
|
387
|
-
[x + arrowWidth,
|
|
455
|
+
[x, top],
|
|
456
|
+
[end[0] - border, top],
|
|
457
|
+
[end[0] + arrowWidth - border, top + height / 2],
|
|
458
|
+
[end[0] - border, top + height],
|
|
459
|
+
[x, top + height],
|
|
460
|
+
[x + arrowWidth, top + height / 2],
|
|
388
461
|
];
|
|
389
462
|
|
|
390
|
-
const itemLabelWidth = echarts.format.getTextRect(name).width + textMargin * 2;
|
|
463
|
+
//const itemLabelWidth = echarts.format.getTextRect(name).width + textMargin * 2;
|
|
391
464
|
const itemWidth = end[0] - x;
|
|
392
465
|
|
|
393
|
-
if (itemLabelWidth > itemWidth)
|
|
394
|
-
|
|
466
|
+
// if (itemLabelWidth > itemWidth)
|
|
467
|
+
// name = ''; // Hide the label as we won't have the room to show it
|
|
468
|
+
|
|
469
|
+
name = wrapText(echarts, name, itemWidth - arrowWidth, height);
|
|
395
470
|
|
|
396
471
|
// See this for clip regions : https://stackoverflow.com/questions/71735038/setting-border-and-label-in-custom-apache-echarts
|
|
397
472
|
// https://stackoverflow.com/questions/73653691/how-to-draw-a-custom-triangle-in-renderitem-in-apache-echarts
|
|
@@ -413,7 +488,7 @@ class RotationRenderer {
|
|
|
413
488
|
},
|
|
414
489
|
},
|
|
415
490
|
textConfig: {
|
|
416
|
-
position: [arrowWidth +
|
|
491
|
+
position: [arrowWidth + textXMargin, textYMargin]
|
|
417
492
|
},
|
|
418
493
|
textContent: {
|
|
419
494
|
style: {
|
|
@@ -430,7 +505,6 @@ class RotationRenderer {
|
|
|
430
505
|
if (type == 'intervention_bottom' || type == 'intervention_top') {
|
|
431
506
|
|
|
432
507
|
const height = 20;
|
|
433
|
-
const border = 3;
|
|
434
508
|
const margin = 10;
|
|
435
509
|
const textMargin = 5;
|
|
436
510
|
|
|
@@ -478,8 +552,8 @@ class RotationRenderer {
|
|
|
478
552
|
|
|
479
553
|
const arrowWidth = 3;
|
|
480
554
|
|
|
481
|
-
let arrowTop = y +
|
|
482
|
-
let arrowBottom = y -
|
|
555
|
+
let arrowTop = y + 55;
|
|
556
|
+
let arrowBottom = y - 55;
|
|
483
557
|
|
|
484
558
|
y = margin + y + trackToUse * (height + margin) - (self.barHeight / 2);
|
|
485
559
|
|
|
@@ -542,28 +616,28 @@ class RotationRenderer {
|
|
|
542
616
|
}
|
|
543
617
|
|
|
544
618
|
return [
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
619
|
+
{
|
|
620
|
+
type: 'custom',
|
|
621
|
+
renderItem: renderItem,
|
|
622
|
+
clip: true,
|
|
623
|
+
itemStyle: {
|
|
624
|
+
opacity: 0.8
|
|
625
|
+
},
|
|
626
|
+
encode: {
|
|
627
|
+
x: [1, 2],
|
|
628
|
+
y: 0
|
|
629
|
+
},
|
|
630
|
+
data: data
|
|
631
|
+
}
|
|
632
|
+
];
|
|
559
633
|
}
|
|
560
634
|
|
|
561
635
|
getCategoriesLabels() {
|
|
562
636
|
let self = this;
|
|
563
637
|
|
|
564
638
|
let categories = [self.chartOptions.title_bottom_interventions ?? '',
|
|
565
|
-
|
|
566
|
-
|
|
639
|
+
self.chartOptions.title_steps ?? '',
|
|
640
|
+
self.chartOptions.title_top_interventions ?? ''];
|
|
567
641
|
|
|
568
642
|
// simulate some wrapping of the category labels
|
|
569
643
|
categories = categories.map((item) => {
|
|
@@ -584,7 +658,7 @@ class RotationRenderer {
|
|
|
584
658
|
if (item.interventions?.length > 0 || item.attributes?.length > 0)
|
|
585
659
|
visibility = "visible";
|
|
586
660
|
|
|
587
|
-
let collapseButton = '<div class="collapse-button '+visibility+ '"><i class="fa fa-chevron-down" aria-hidden="true"></i></div>';
|
|
661
|
+
let collapseButton = '<div class="collapse-button ' + visibility + '"><i class="fa fa-chevron-down" aria-hidden="true"></i></div>';
|
|
588
662
|
|
|
589
663
|
let start = item.startDate.toLocaleDateString('fr-FR', { day: 'numeric', month: 'short', year: '2-digit' });
|
|
590
664
|
let end = item.endDate.toLocaleDateString('fr-FR', { day: 'numeric', month: 'short', year: '2-digit' });
|
|
@@ -595,7 +669,7 @@ class RotationRenderer {
|
|
|
595
669
|
+ collapseButton
|
|
596
670
|
+ '<div class="step_dates">' + dates + '</div>'
|
|
597
671
|
+ '<h4 class="">' + item.name + '<i class="fa fa-pencil step-edit" aria-hidden="true"></i></h4>'
|
|
598
|
-
+ '</div><p class="step_description clearfix">' + (item.description
|
|
672
|
+
+ '</div><p class="step_description clearfix">' + self.getHTMLFormatedDescription(item.description) + '</p>'
|
|
599
673
|
+ '<div class="details">'
|
|
600
674
|
+ (item.attributes?.length > 0 ? item.attributes.map((attribute) => { return '<p><dt>' + attribute.name + '</dt><dd>' + attribute.value + '</dd></p>' }).join('') : '');
|
|
601
675
|
|
|
@@ -605,9 +679,9 @@ class RotationRenderer {
|
|
|
605
679
|
let intDate = new Date(item.startDate.valueOf() + intervention.day * 86400000).toLocaleDateString('fr-FR', { day: 'numeric', month: 'short', year: 'numeric' });
|
|
606
680
|
let days = intervention.day;
|
|
607
681
|
if (days >= 0)
|
|
608
|
-
intDate += ' (J+' + days + ')';
|
|
682
|
+
intDate += ' (J+' + (days == 0 ? '0' : days) + ')';
|
|
609
683
|
else
|
|
610
|
-
intDate += ' (J' + days + ')';
|
|
684
|
+
intDate += ' (J-' + days + ')';
|
|
611
685
|
|
|
612
686
|
let title = intervention.name;
|
|
613
687
|
|
|
@@ -615,8 +689,8 @@ class RotationRenderer {
|
|
|
615
689
|
title = title + '⚠️';
|
|
616
690
|
|
|
617
691
|
html += '<div class="Intervention_' + index + '_' + interventionIndex + ' intervention"><span class="intervention_title">' + title + '</span>'
|
|
618
|
-
|
|
619
|
-
|
|
692
|
+
+ '<span class="intervention_date badge rounded-pill">' + intDate + '</span>'
|
|
693
|
+
+ '<div class="intervention_description">' + intervention.description + '</div></div>';
|
|
620
694
|
});
|
|
621
695
|
}
|
|
622
696
|
|
|
@@ -665,16 +739,16 @@ class RotationRenderer {
|
|
|
665
739
|
},
|
|
666
740
|
data: []
|
|
667
741
|
};
|
|
668
|
-
|
|
742
|
+
|
|
669
743
|
let lastDayOfPreviousStep = null;
|
|
670
744
|
|
|
671
745
|
steps.forEach((item, index) => {
|
|
672
|
-
|
|
746
|
+
|
|
673
747
|
if (lastDayOfPreviousStep) {
|
|
674
748
|
// If there's a gap between the end of the previous step and the start of the new step, we add an dummy pie item:
|
|
675
749
|
let days = Math.round((item.startDate - lastDayOfPreviousStep) / (1000 * 60 * 60 * 24));
|
|
676
750
|
if (days > 0) {
|
|
677
|
-
|
|
751
|
+
|
|
678
752
|
let pieItem = {
|
|
679
753
|
'name': '',
|
|
680
754
|
'value': days,
|
|
@@ -684,18 +758,18 @@ class RotationRenderer {
|
|
|
684
758
|
'endDate': new Date(item.startDate.valueOf()), // Date de fin
|
|
685
759
|
'duration': Math.round(days / 30),
|
|
686
760
|
'description': '',
|
|
687
|
-
'emphasis': {'disabled': true},
|
|
688
|
-
'select': {'disabled': true},
|
|
689
|
-
'tooltip': {'show': false},
|
|
761
|
+
'emphasis': { 'disabled': true },
|
|
762
|
+
'select': { 'disabled': true },
|
|
763
|
+
'tooltip': { 'show': false },
|
|
690
764
|
'itemStyle': {
|
|
691
765
|
'color': '#FFFFFF'
|
|
692
|
-
}
|
|
766
|
+
}
|
|
693
767
|
};
|
|
694
768
|
|
|
695
769
|
crops.data.push(pieItem);
|
|
696
770
|
}
|
|
697
771
|
}
|
|
698
|
-
|
|
772
|
+
|
|
699
773
|
|
|
700
774
|
let days = Math.round((item.endDate - item.startDate) / (1000 * 60 * 60 * 24));
|
|
701
775
|
lastDayOfPreviousStep = new Date(item.endDate.valueOf());
|
|
@@ -762,18 +836,18 @@ class RotationRenderer {
|
|
|
762
836
|
const monthName = startMonth.toLocaleDateString(undefined, { month: 'short' });
|
|
763
837
|
const year = startMonth.getFullYear();
|
|
764
838
|
|
|
765
|
-
months.data.push({
|
|
766
|
-
'name': monthName,
|
|
839
|
+
months.data.push({
|
|
840
|
+
'name': monthName,
|
|
767
841
|
'value': 1,
|
|
768
842
|
'itemStyle': {
|
|
769
843
|
'color': monthsColorScale[startMonth.getMonth()]
|
|
770
|
-
}
|
|
844
|
+
}
|
|
771
845
|
});
|
|
772
846
|
|
|
773
847
|
let currentMonthsPerYear = monthsPerYear.get(year);
|
|
774
848
|
if (currentMonthsPerYear == undefined)
|
|
775
849
|
currentMonthsPerYear = 0;
|
|
776
|
-
|
|
850
|
+
monthsPerYear.set(year, ++currentMonthsPerYear);
|
|
777
851
|
|
|
778
852
|
// increment the current month
|
|
779
853
|
startMonth.setMonth(startMonth.getMonth() + 1);
|
|
@@ -802,9 +876,9 @@ class RotationRenderer {
|
|
|
802
876
|
};
|
|
803
877
|
|
|
804
878
|
monthsPerYear.forEach((nbMonths, year) => {
|
|
805
|
-
years.data.push({
|
|
806
|
-
'name': year,
|
|
807
|
-
'value': nbMonths
|
|
879
|
+
years.data.push({
|
|
880
|
+
'name': year,
|
|
881
|
+
'value': nbMonths
|
|
808
882
|
});
|
|
809
883
|
});
|
|
810
884
|
|
|
@@ -845,60 +919,60 @@ class RotationRenderer {
|
|
|
845
919
|
}
|
|
846
920
|
|
|
847
921
|
option.tooltip = {
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
922
|
+
extraCssText: "text-wrap: wrap;",
|
|
923
|
+
className: "rotation-tooltip",
|
|
924
|
+
formatter: function (params) {
|
|
925
|
+
if (params.data.type == 'rotation_item') {
|
|
926
|
+
let start = params.data.startDate.toLocaleDateString('fr-FR', { day: 'numeric', month: 'short', year: '2-digit' });
|
|
927
|
+
let end = params.data.endDate.toLocaleDateString('fr-FR', { day: 'numeric', month: 'short', year: '2-digit' });
|
|
928
|
+
|
|
929
|
+
return params.marker + params.name + ' : ' + params.data.duration + ' mois (' + start + ' ➜ ' + end + ')<br>' + params.data.description;
|
|
930
|
+
}
|
|
931
|
+
else {
|
|
932
|
+
let interventionDate = params.data.interventionDate;
|
|
933
|
+
const days = params.data.interventionDays;
|
|
934
|
+
let dateString = interventionDate.toLocaleDateString('fr-FR', { day: 'numeric', month: 'short' });
|
|
861
935
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
936
|
+
if (days >= 0)
|
|
937
|
+
dateString += ' (J+' + (days == 0 ? '0' : days) + ')';
|
|
938
|
+
else
|
|
939
|
+
dateString += ' (J-' + days + ')';
|
|
866
940
|
|
|
867
|
-
|
|
868
|
-
}
|
|
941
|
+
return params.marker + params.name + ' - ' + dateString + '<br>' + params.data.description;
|
|
869
942
|
}
|
|
870
|
-
}
|
|
943
|
+
}
|
|
944
|
+
};
|
|
871
945
|
|
|
872
946
|
option.toolbox = {
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
947
|
+
"itemSize": 25,
|
|
948
|
+
"iconStyle": {
|
|
949
|
+
"borderColor": "#AAA",
|
|
950
|
+
"borderWidth": 1
|
|
951
|
+
},
|
|
952
|
+
"feature": {
|
|
953
|
+
"myTool1": {
|
|
954
|
+
"show": true,
|
|
955
|
+
"title": 'Rotation',
|
|
956
|
+
"icon": 'path://M18.15,12.99c-.06-.07-.14-.13-.23-.17l-.38-.15c.33-.93.51-1.92.51-2.96,0-3-1.49-5.65-3.77-7.26l-3.03,2.72c1.72.79,2.91,2.53,2.91,4.54,0,.54-.09,1.07-.25,1.56l-.44-.17c-.3-.12-.64.03-.76.33-.04.1-.05.21-.03.31l.79,4.82c.06.32.36.53.68.47.1-.02.19-.06.27-.13l3.66-3.1c.25-.21.28-.58.07-.82ZM6.94,5.24c.46-.23.97-.39,1.5-.47l.13.59c.07.32.38.52.69.45.1-.02.2-.07.28-.14l3.59-3.31c.23-.22.24-.59.02-.83-.07-.07-.16-.13-.26-.16L8.3.02c-.31-.09-.63.09-.73.39-.03.09-.03.19-.01.29l.06.27c-1.12.2-2.16.6-3.1,1.17l2.41,3.09ZM5.88,5.96l-2.39-3.06c-.98.82-1.79,1.84-2.34,3.01l3.62,1.44c.29-.53.66-1,1.11-1.39ZM4.17,9.72c0-.41.05-.81.14-1.19l-3.63-1.44c-.18.57-.3,1.16-.35,1.77l3.84,1.1c0-.08,0-.16,0-.24ZM9.17,14.72c-1.59,0-3-.74-3.92-1.9l.42-.38c.24-.22.26-.59.04-.83-.07-.08-.16-.14-.26-.17l-4.66-1.47c-.31-.09-.64.08-.73.39-.03.1-.03.2,0,.3l1.12,4.66c.07.31.39.51.7.43.09-.02.18-.07.25-.13l.23-.21c1.63,1.94,4.07,3.18,6.8,3.18,1.3,0,2.54-.28,3.66-.79l-.8-3.99c-.81.56-1.79.9-2.86.9Z',
|
|
957
|
+
onclick: function () {
|
|
958
|
+
self.initialLayout = 'donut';
|
|
959
|
+
self.renderChart();
|
|
960
|
+
}
|
|
877
961
|
},
|
|
878
|
-
"
|
|
879
|
-
"
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
self.renderChart();
|
|
886
|
-
}
|
|
887
|
-
},
|
|
888
|
-
"myTool2": {
|
|
889
|
-
"show": true,
|
|
890
|
-
"title": 'Frise',
|
|
891
|
-
"icon": 'path://M4.63,0H0v10.01h4.97c.07,0,.13-.05.19-.14l2.61-4.14c.17-.28.23-.89.12-1.35-.03-.15-.08-.27-.13-.35L5.16.12c-.05-.08-.11-.12-.17-.12h-.37ZM11.9,4.38c-.03-.15-.08-.27-.13-.35L9.17.12c-.05-.08-.11-.12-.17-.12h-.37s-2.26,0-2.26,0v.03s.06.05.08.09l2.6,3.9c.06.08.1.21.13.35.1.47.05,1.07-.12,1.35l-2.61,4.14s-.05.07-.08.09v.04h2.6c.07,0,.13-.05.19-.14l2.61-4.14c.17-.28.23-.89.12-1.35ZM18.28,4.38c-.03-.15-.08-.27-.13-.35L15.55.12c-.05-.08-.11-.12-.17-.12h-.37s-4.63,0-4.63,0v.03s.06.05.08.09l2.6,3.9c.06.08.1.21.13.35.1.47.05,1.07-.12,1.35l-2.61,4.14s-.05.07-.08.09v.04h4.97c.07,0,.13-.05.19-.14l2.61-4.14c.17-.28.23-.89.12-1.35Z',
|
|
892
|
-
onclick: function (){
|
|
893
|
-
self.initialLayout = 'horizontal';
|
|
894
|
-
self.renderChart();
|
|
895
|
-
}
|
|
896
|
-
},
|
|
897
|
-
"saveAsImage": {
|
|
898
|
-
'excludeComponents': ["dataZoom", "toolbox"]
|
|
962
|
+
"myTool2": {
|
|
963
|
+
"show": true,
|
|
964
|
+
"title": 'Frise',
|
|
965
|
+
"icon": 'path://M4.63,0H0v10.01h4.97c.07,0,.13-.05.19-.14l2.61-4.14c.17-.28.23-.89.12-1.35-.03-.15-.08-.27-.13-.35L5.16.12c-.05-.08-.11-.12-.17-.12h-.37ZM11.9,4.38c-.03-.15-.08-.27-.13-.35L9.17.12c-.05-.08-.11-.12-.17-.12h-.37s-2.26,0-2.26,0v.03s.06.05.08.09l2.6,3.9c.06.08.1.21.13.35.1.47.05,1.07-.12,1.35l-2.61,4.14s-.05.07-.08.09v.04h2.6c.07,0,.13-.05.19-.14l2.61-4.14c.17-.28.23-.89.12-1.35ZM18.28,4.38c-.03-.15-.08-.27-.13-.35L15.55.12c-.05-.08-.11-.12-.17-.12h-.37s-4.63,0-4.63,0v.03s.06.05.08.09l2.6,3.9c.06.08.1.21.13.35.1.47.05,1.07-.12,1.35l-2.61,4.14s-.05.07-.08.09v.04h4.97c.07,0,.13-.05.19-.14l2.61-4.14c.17-.28.23-.89.12-1.35Z',
|
|
966
|
+
onclick: function () {
|
|
967
|
+
self.initialLayout = 'horizontal';
|
|
968
|
+
self.renderChart();
|
|
899
969
|
}
|
|
970
|
+
},
|
|
971
|
+
"saveAsImage": {
|
|
972
|
+
'excludeComponents': ["dataZoom", "toolbox"]
|
|
900
973
|
}
|
|
901
|
-
}
|
|
974
|
+
}
|
|
975
|
+
};
|
|
902
976
|
|
|
903
977
|
return option;
|
|
904
978
|
}
|
package/js/editor-crops.js
CHANGED
|
@@ -28,6 +28,7 @@ function loadSelectedStepToEditor(aStep) {
|
|
|
28
28
|
setInputValue("cropStartDate", aStep.getStep().startDate.toISOString().split('T')[0]);
|
|
29
29
|
setInputValue("cropEndDate", aStep.getStep().endDate.toISOString().split('T')[0]);
|
|
30
30
|
setInputValue("cropDescription", aStep.getStep().description);
|
|
31
|
+
document.getElementById("cropSecondary").checked = aStep.getStep().secondary_crop || false;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
function refreshStepsButtonList() {
|
|
@@ -71,6 +71,18 @@ function createInterventionForm(id, day, name, type, description, row) {
|
|
|
71
71
|
type = type || "";
|
|
72
72
|
description = description || "";
|
|
73
73
|
|
|
74
|
+
// Calculate absolute date from relative day
|
|
75
|
+
let absoluteDate = "";
|
|
76
|
+
if (day == "")
|
|
77
|
+
day = 0;
|
|
78
|
+
|
|
79
|
+
if (selectedStep && selectedStep.getStep().startDate) {
|
|
80
|
+
const stepStartDate = new Date(selectedStep.getStep().startDate);
|
|
81
|
+
const interventionDate = new Date(stepStartDate);
|
|
82
|
+
interventionDate.setDate(stepStartDate.getDate() + parseInt(day));
|
|
83
|
+
absoluteDate = interventionDate.toISOString().split('T')[0];
|
|
84
|
+
}
|
|
85
|
+
|
|
74
86
|
const formContainer = document.createElement("div");
|
|
75
87
|
formContainer.innerHTML =
|
|
76
88
|
`<form id="interventionForm">
|
|
@@ -84,11 +96,15 @@ function createInterventionForm(id, day, name, type, description, row) {
|
|
|
84
96
|
<textarea id="interventionDescription" class="form-control"
|
|
85
97
|
placeholder="Ajouter une description">${description}</textarea>
|
|
86
98
|
</div>
|
|
87
|
-
<div class="col-
|
|
88
|
-
<label for="interventionDay" class="form-label">
|
|
89
|
-
<input type="number" id="interventionDay" class="form-control" placeholder="Jour"
|
|
99
|
+
<div class="col-4 mb-2">
|
|
100
|
+
<label for="interventionDay" class="form-label">Jour relatif</label>
|
|
101
|
+
<input type="number" id="interventionDay" class="form-control text-right" placeholder="Jour"
|
|
90
102
|
value="${day}">
|
|
91
103
|
</div>
|
|
104
|
+
<div class="col-8 mb-2">
|
|
105
|
+
<label for="interventionDate" class="form-label">Date absolue</label>
|
|
106
|
+
<input type="date" id="interventionDate" class="form-control" value="${absoluteDate}">
|
|
107
|
+
</div>
|
|
92
108
|
<div class="col-12 mb-2">
|
|
93
109
|
<select id="interventionType" class="form-select" aria-label="Type">
|
|
94
110
|
<option value="intervention_top"
|
|
@@ -113,5 +129,49 @@ function createInterventionForm(id, day, name, type, description, row) {
|
|
|
113
129
|
document.getElementById("newInterventionButton").classList.add("d-none");
|
|
114
130
|
}
|
|
115
131
|
|
|
132
|
+
// Add event listeners for date synchronization
|
|
133
|
+
setupInterventionDateListeners();
|
|
134
|
+
|
|
116
135
|
$("#interventionName").focus();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function setupInterventionDateListeners() {
|
|
139
|
+
// When relative day changes, update absolute date
|
|
140
|
+
$("#interventionDay").on("input change", function() {
|
|
141
|
+
updateAbsoluteDateFromRelative();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// When absolute date changes, update relative day
|
|
145
|
+
$("#interventionDate").on("change", function() {
|
|
146
|
+
updateRelativeDayFromAbsolute();
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function updateAbsoluteDateFromRelative() {
|
|
151
|
+
const relativeDay = $("#interventionDay").val();
|
|
152
|
+
if (relativeDay == "")
|
|
153
|
+
relativeDay = 0;
|
|
154
|
+
|
|
155
|
+
if (selectedStep && selectedStep.getStep().startDate) {
|
|
156
|
+
const stepStartDate = new Date(selectedStep.getStep().startDate);
|
|
157
|
+
const interventionDate = new Date(stepStartDate);
|
|
158
|
+
interventionDate.setDate(stepStartDate.getDate() + parseInt(relativeDay));
|
|
159
|
+
|
|
160
|
+
const absoluteDateStr = interventionDate.toISOString().split('T')[0];
|
|
161
|
+
$("#interventionDate").val(absoluteDateStr);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function updateRelativeDayFromAbsolute() {
|
|
166
|
+
const absoluteDate = $("#interventionDate").val();
|
|
167
|
+
if (absoluteDate !== "" && selectedStep && selectedStep.getStep().startDate) {
|
|
168
|
+
const stepStartDate = new Date(selectedStep.getStep().startDate);
|
|
169
|
+
const interventionDate = new Date(absoluteDate);
|
|
170
|
+
|
|
171
|
+
// Calculate difference in days
|
|
172
|
+
const timeDiff = interventionDate.getTime() - stepStartDate.getTime();
|
|
173
|
+
const dayDiff = Math.round(timeDiff / (1000 * 60 * 60 * 24));
|
|
174
|
+
|
|
175
|
+
$("#interventionDay").val(dayDiff);
|
|
176
|
+
}
|
|
117
177
|
}
|
package/package.json
CHANGED
package/scss/styles-editor.scss
CHANGED
|
@@ -74,6 +74,10 @@ $header-height: 3rem;
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
.intervention-row {
|
|
78
|
+
background: #e0e0e0;
|
|
79
|
+
}
|
|
80
|
+
|
|
77
81
|
.primary-button {
|
|
78
82
|
color: $button-text-color;
|
|
79
83
|
background-color: $button-color;
|
|
@@ -103,4 +107,10 @@ $header-height: 3rem;
|
|
|
103
107
|
margin-right: 10px;
|
|
104
108
|
vertical-align: middle;
|
|
105
109
|
cursor: grab;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.form-control {
|
|
113
|
+
&.text-right {
|
|
114
|
+
text-align: right;
|
|
115
|
+
}
|
|
106
116
|
}
|