@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
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DefaultLoader - Parent class for WikiLoader and ItineraLoader
|
|
3
|
+
* Provides common functionality for import/export and button setup
|
|
4
|
+
*/
|
|
5
|
+
class DefaultLoader {
|
|
6
|
+
constructor(tikaeditorInstance = null) {
|
|
7
|
+
this.tikaeditorInstance = tikaeditorInstance;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Setup buttons dynamically in the toolbar
|
|
12
|
+
* Default implementation for standalone mode (NonWikiButtons)
|
|
13
|
+
* Can be overridden by child classes for Wiki/Itinera specific buttons
|
|
14
|
+
*/
|
|
15
|
+
setupButtons() {
|
|
16
|
+
const self = this;
|
|
17
|
+
const container = '#toolbar-buttons-container';
|
|
18
|
+
|
|
19
|
+
// Create the NonWikiButtons div structure for standalone mode
|
|
20
|
+
const nonWikiButtonsDiv = $(`
|
|
21
|
+
<div id="NonWikiButtons" class="">
|
|
22
|
+
<div class="btn-group me-2" role="group">
|
|
23
|
+
<button type="button" class="btn btn-outline-primary primary-button btn-import-json">
|
|
24
|
+
<i class="fa fa-upload" aria-hidden="true"></i> Charger une rotation
|
|
25
|
+
</button>
|
|
26
|
+
<button type="button" class="btn btn-outline-primary primary-button dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
|
|
27
|
+
<span class="visually-hidden">Autres options de chargement</span>
|
|
28
|
+
</button>
|
|
29
|
+
<ul class="dropdown-menu">
|
|
30
|
+
<li><a class="dropdown-item btn-import-test" href="#"><i class="fa fa-lightbulb-o" aria-hidden="true"></i> Charger un exemple</a></li>
|
|
31
|
+
</ul>
|
|
32
|
+
</div>
|
|
33
|
+
<button type="button" class="btn btn-outline-primary primary-button me-2 btn-export-json">
|
|
34
|
+
<i class="fa fa-download" aria-hidden="true"></i> Exporter (JSON)
|
|
35
|
+
</button>
|
|
36
|
+
</div>
|
|
37
|
+
`);
|
|
38
|
+
|
|
39
|
+
// Clear container and append the new buttons
|
|
40
|
+
$(container).empty().append(nonWikiButtonsDiv);
|
|
41
|
+
|
|
42
|
+
// Attach event handlers
|
|
43
|
+
nonWikiButtonsDiv.find('.btn-import-json').on('click', function(e) {
|
|
44
|
+
e.preventDefault();
|
|
45
|
+
self.importFromJsonFile();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
nonWikiButtonsDiv.find('.btn-import-test').on('click', function(e) {
|
|
49
|
+
e.preventDefault();
|
|
50
|
+
self.importFromTestJson();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
nonWikiButtonsDiv.find('.btn-export-json').on('click', function(e) {
|
|
54
|
+
e.preventDefault();
|
|
55
|
+
self.doExportToJsonFile();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Add wipe button
|
|
59
|
+
this.addWipeButton();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Add the wipe button dynamically to the toolbar
|
|
64
|
+
*/
|
|
65
|
+
addWipeButton() {
|
|
66
|
+
const self = this;
|
|
67
|
+
const container = '#toolbar-buttons-container';
|
|
68
|
+
|
|
69
|
+
const wipeButton = $(`
|
|
70
|
+
<button type="button" id="wipe-button" class="btn btn-outline-primary primary-button">
|
|
71
|
+
<i class="fa fa-trash" aria-hidden="true"></i> Tout effacer
|
|
72
|
+
</button>
|
|
73
|
+
`);
|
|
74
|
+
|
|
75
|
+
$(container).append(wipeButton);
|
|
76
|
+
|
|
77
|
+
wipeButton.on('click', function(e) {
|
|
78
|
+
e.preventDefault();
|
|
79
|
+
self.wipe();
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Export crops to JSON file
|
|
85
|
+
*/
|
|
86
|
+
doExportToJsonFile() {
|
|
87
|
+
let jsonName = this.tikaeditorInstance.system.title.replace(/\s+/g, '-').toLowerCase() + ".json";
|
|
88
|
+
this.exportToJsonFile(this.tikaeditorInstance.system, jsonName);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Export data to JSON file
|
|
93
|
+
*/
|
|
94
|
+
exportToJsonFile(data, fileName = 'export-itk.json') {
|
|
95
|
+
const jsonData = JSON.stringify(data, null, 2);
|
|
96
|
+
const blob = new Blob([jsonData], { type: 'application/json' });
|
|
97
|
+
const url = URL.createObjectURL(blob);
|
|
98
|
+
|
|
99
|
+
const a = document.createElement('a');
|
|
100
|
+
a.href = url;
|
|
101
|
+
a.download = fileName;
|
|
102
|
+
a.click();
|
|
103
|
+
|
|
104
|
+
URL.revokeObjectURL(url);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Import from JSON file with confirmation
|
|
109
|
+
*/
|
|
110
|
+
importFromJsonFile() {
|
|
111
|
+
this.showConfirmationModal(() => {
|
|
112
|
+
this.openFileInput();
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Import from test JSON with confirmation
|
|
118
|
+
*/
|
|
119
|
+
importFromTestJson() {
|
|
120
|
+
this.showConfirmationModal(() => {
|
|
121
|
+
this.importTestJSON();
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Load and import test JSON file
|
|
127
|
+
*/
|
|
128
|
+
importTestJSON() {
|
|
129
|
+
const self = this;
|
|
130
|
+
|
|
131
|
+
fetch('test/test.json')
|
|
132
|
+
.then(response => {
|
|
133
|
+
if (!response.ok) {
|
|
134
|
+
throw new Error("Erreur HTTP " + response.status);
|
|
135
|
+
}
|
|
136
|
+
return response.json();
|
|
137
|
+
})
|
|
138
|
+
.then(data => {
|
|
139
|
+
console.log("Données JSON :", data);
|
|
140
|
+
data.steps.forEach(step => {
|
|
141
|
+
let sm = new StepModel(step);
|
|
142
|
+
sm.setAsEdited();
|
|
143
|
+
});
|
|
144
|
+
self.tikaeditorInstance.reloadCropsFromJson(data);
|
|
145
|
+
})
|
|
146
|
+
.catch(error => {
|
|
147
|
+
console.error("Impossible de charger le JSON :", error);
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Wipe/reset all crops data
|
|
153
|
+
*/
|
|
154
|
+
wipe() {
|
|
155
|
+
const self = this;
|
|
156
|
+
|
|
157
|
+
const DEFAULT_TITLE = "Nouvel itinéraire technique";
|
|
158
|
+
this.showConfirmationModal(() => {
|
|
159
|
+
let crops = {
|
|
160
|
+
"title": DEFAULT_TITLE,
|
|
161
|
+
"options": {
|
|
162
|
+
"view": "horizontal",
|
|
163
|
+
"show_transcript": true,
|
|
164
|
+
"title_top_interventions": "Contrôle adventices",
|
|
165
|
+
"title_bottom_interventions": "Autres interventions",
|
|
166
|
+
"title_steps": "Étapes de la rotation dans la parcelle",
|
|
167
|
+
},
|
|
168
|
+
"steps": []
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
self.tikaeditorInstance.reloadCropsFromJson(crops);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Open file input dialog for JSON import
|
|
177
|
+
*/
|
|
178
|
+
openFileInput() {
|
|
179
|
+
const self = this;
|
|
180
|
+
const input = document.createElement('input');
|
|
181
|
+
input.type = 'file';
|
|
182
|
+
input.accept = '.json';
|
|
183
|
+
|
|
184
|
+
input.addEventListener('change', (event) => {
|
|
185
|
+
const file = event.target.files[0];
|
|
186
|
+
if (file) {
|
|
187
|
+
const reader = new FileReader();
|
|
188
|
+
reader.onload = () => {
|
|
189
|
+
try {
|
|
190
|
+
const jsonData = JSON.parse(reader.result);
|
|
191
|
+
jsonData.steps.forEach(step => {
|
|
192
|
+
let sm = new StepModel(step);
|
|
193
|
+
sm.setAsEdited();
|
|
194
|
+
});
|
|
195
|
+
self.tikaeditorInstance.reloadCropsFromJson(jsonData);
|
|
196
|
+
} catch (error) {
|
|
197
|
+
console.error("Error parsing JSON file:", error);
|
|
198
|
+
this.showJsonErrorModal(error.message);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
reader.readAsText(file);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
input.click();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Show JSON error modal
|
|
210
|
+
*/
|
|
211
|
+
showJsonErrorModal(errorMessage) {
|
|
212
|
+
const errorModal = new bootstrap.Modal(document.getElementById('jsonErrorModal'));
|
|
213
|
+
document.getElementById('jsonErrorMessage').textContent = errorMessage;
|
|
214
|
+
errorModal.show();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Show confirmation modal before potentially destructive operations
|
|
219
|
+
*/
|
|
220
|
+
showConfirmationModal(onConfirm) {
|
|
221
|
+
if (this.tikaeditorInstance.system?.steps.length === 0)
|
|
222
|
+
return onConfirm();
|
|
223
|
+
|
|
224
|
+
const confirmationModal = new bootstrap.Modal(document.getElementById('confirmationModal'));
|
|
225
|
+
const confirmButton = document.getElementById('confirmImport');
|
|
226
|
+
|
|
227
|
+
// Avoid multiple event listeners
|
|
228
|
+
const newConfirmButton = confirmButton.cloneNode(true);
|
|
229
|
+
confirmButton.replaceWith(newConfirmButton);
|
|
230
|
+
|
|
231
|
+
newConfirmButton.addEventListener('click', () => {
|
|
232
|
+
confirmationModal.hide();
|
|
233
|
+
onConfirm();
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
confirmationModal.show();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// Encapsulate the wiki editor functionality
|
|
2
|
+
class ItineraLoader extends DefaultLoader {
|
|
3
|
+
constructor(tikaeditorInstance = null) {
|
|
4
|
+
super(tikaeditorInstance);
|
|
5
|
+
|
|
6
|
+
// Initialize any properties if needed
|
|
7
|
+
this.systemID = null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Setup the Itinera buttons dynamically in the toolbar
|
|
12
|
+
*/
|
|
13
|
+
setupButtons() {
|
|
14
|
+
const self = this;
|
|
15
|
+
const container = '#toolbar-buttons-container';
|
|
16
|
+
|
|
17
|
+
// Create the ItineraButtons div structure
|
|
18
|
+
const itineraButtonsDiv = $(`
|
|
19
|
+
<div id="ItineraButtons" class="">
|
|
20
|
+
<button type="button" class="btn btn-outline-primary primary-button btn-save-itinera">
|
|
21
|
+
<i class="fa fa-download" aria-hidden="true"></i> Enregistrer dans Itinera
|
|
22
|
+
</button>
|
|
23
|
+
</div>
|
|
24
|
+
`);
|
|
25
|
+
|
|
26
|
+
// Clear container and append the new buttons
|
|
27
|
+
$(container).empty().append(itineraButtonsDiv);
|
|
28
|
+
|
|
29
|
+
// Attach event handler
|
|
30
|
+
itineraButtonsDiv.find('.btn-save-itinera').on('click', function(e) {
|
|
31
|
+
e.preventDefault();
|
|
32
|
+
self.saveToItinera();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Don't add wipe button in Itinera mode
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* When the page loads, get the URL paremeter with the target page title we want to edit:
|
|
40
|
+
* @returns
|
|
41
|
+
*/
|
|
42
|
+
loadPageFromURL() {
|
|
43
|
+
|
|
44
|
+
const self = this;
|
|
45
|
+
|
|
46
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
47
|
+
self.systemID = urlParams.get('itinera');
|
|
48
|
+
|
|
49
|
+
if (!self.systemID)
|
|
50
|
+
return; // No page title provided, we are not in wiki edit mode
|
|
51
|
+
|
|
52
|
+
// If a page title is provided, load its content from /api/systems/1
|
|
53
|
+
fetch(`/api/systems/${encodeURIComponent(self.systemID)}`, {
|
|
54
|
+
credentials: 'same-origin'
|
|
55
|
+
})
|
|
56
|
+
.then(response => {
|
|
57
|
+
let res = response.json();
|
|
58
|
+
return res;
|
|
59
|
+
})
|
|
60
|
+
.then(data => {
|
|
61
|
+
if (data.json) {
|
|
62
|
+
try {
|
|
63
|
+
const content = data.json;
|
|
64
|
+
content.steps.forEach(step => {
|
|
65
|
+
let sm = new StepModel(step)
|
|
66
|
+
sm.setAsEdited();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
self.tikaeditorInstance.reloadCropsFromJson(content);
|
|
70
|
+
|
|
71
|
+
let codeSnippet = `{{Graphique Triple Performance \n| title=${content.title} \n| json=${self.systemID} \n| type=Rotation }}`;
|
|
72
|
+
$('#code-snippet').val(codeSnippet).on('focus', function() {
|
|
73
|
+
$(this).select();
|
|
74
|
+
});
|
|
75
|
+
$('#codeSnippetDiv').show();
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
} catch (e) {
|
|
79
|
+
console.error("Erreur lors de l'analyse du JSON de la page :", e);
|
|
80
|
+
$('#jsonErrorMessage').text("Le contenu de la page n'est pas un JSON valide.");
|
|
81
|
+
const jsonErrorModal = new bootstrap.Modal(document.getElementById('jsonErrorModal'));
|
|
82
|
+
jsonErrorModal.show();
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
wipe();
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Save a page back to the wiki. The page title must have been set previously.
|
|
93
|
+
*/
|
|
94
|
+
async saveToItinera() {
|
|
95
|
+
const self = this;
|
|
96
|
+
|
|
97
|
+
if (!self.systemID) {
|
|
98
|
+
// Error ?
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Proceed to save
|
|
103
|
+
const response = await fetch(`/api/systems/${encodeURIComponent(self.systemID)}`, {
|
|
104
|
+
method: 'PATCH',
|
|
105
|
+
headers: {
|
|
106
|
+
'Content-Type': 'application/json'
|
|
107
|
+
},
|
|
108
|
+
credentials: 'same-origin',
|
|
109
|
+
body: JSON.stringify({
|
|
110
|
+
json: self.tikaeditorInstance.system
|
|
111
|
+
})
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
if (response.ok) {
|
|
115
|
+
// Successfully saved - show a toast
|
|
116
|
+
const toast = $('#liveToast');
|
|
117
|
+
|
|
118
|
+
// Update the time and message
|
|
119
|
+
const now = new Date();
|
|
120
|
+
const hours = now.getHours().toString().padStart(2, '0');
|
|
121
|
+
const minutes = now.getMinutes().toString().padStart(2, '0');
|
|
122
|
+
toast.find('small').text(`${hours}:${minutes}`);
|
|
123
|
+
toast.find('.toast-body').text('Sauvegardé dans Itinéra !');
|
|
124
|
+
|
|
125
|
+
const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toast);
|
|
126
|
+
toastBootstrap.show();
|
|
127
|
+
|
|
128
|
+
} else {
|
|
129
|
+
// Error saving
|
|
130
|
+
const errorModal = new bootstrap.Modal(document.getElementById('saveErrorModal'));
|
|
131
|
+
errorModal.show();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
}
|
|
@@ -1,10 +1,98 @@
|
|
|
1
1
|
// Encapsulate the wiki editor functionality
|
|
2
|
-
class
|
|
3
|
-
constructor() {
|
|
2
|
+
class WikiLoader extends DefaultLoader {
|
|
3
|
+
constructor(tikaeditorInstance = null) {
|
|
4
|
+
super(tikaeditorInstance);
|
|
5
|
+
|
|
4
6
|
// Initialize any properties if needed
|
|
5
7
|
this.pageTitle = null;
|
|
6
8
|
}
|
|
7
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Setup the Wiki buttons dynamically in the toolbar
|
|
12
|
+
*/
|
|
13
|
+
setupButtons() {
|
|
14
|
+
const self = this;
|
|
15
|
+
const container = '#toolbar-buttons-container';
|
|
16
|
+
|
|
17
|
+
// Create the WikiButtons div structure
|
|
18
|
+
const wikiButtonsDiv = $(`
|
|
19
|
+
<div id="WikiButtons" class="">
|
|
20
|
+
<div class="btn-group me-2" role="group">
|
|
21
|
+
<button type="button" class="btn btn-outline-primary primary-button btn-load-wiki">
|
|
22
|
+
<i class="fa fa-upload" aria-hidden="true"></i> Charger une rotation
|
|
23
|
+
</button>
|
|
24
|
+
<button type="button" class="btn btn-outline-primary primary-button dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
|
|
25
|
+
<span class="visually-hidden">Autres options de chargement</span>
|
|
26
|
+
</button>
|
|
27
|
+
<ul class="dropdown-menu">
|
|
28
|
+
<li><a class="dropdown-item btn-import-test" href="#"><i class="fa fa-lightbulb-o" aria-hidden="true"></i> Charger un exemple</a></li>
|
|
29
|
+
<li><a class="dropdown-item btn-import-json" href="#"><i class="fa fa-upload" aria-hidden="true"></i> Importer (JSON)</a></li>
|
|
30
|
+
</ul>
|
|
31
|
+
</div>
|
|
32
|
+
<div class="btn-group me-2" role="group">
|
|
33
|
+
<button type="button" class="btn btn-outline-primary primary-button btn-save-wiki">
|
|
34
|
+
<i class="fa fa-download" aria-hidden="true"></i> Enregistrer dans le wiki
|
|
35
|
+
</button>
|
|
36
|
+
<button type="button" class="btn btn-outline-primary primary-button dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
|
|
37
|
+
<span class="visually-hidden">Autres options d'enregistrement</span>
|
|
38
|
+
</button>
|
|
39
|
+
<ul class="dropdown-menu">
|
|
40
|
+
<li><a class="dropdown-item btn-save-as" href="#"><i class="fa fa-save" aria-hidden="true"></i> Enregistrer sous</a></li>
|
|
41
|
+
<li><a class="dropdown-item btn-export-json" href="#"><i class="fa fa-download" aria-hidden="true"></i> Exporter</a></li>
|
|
42
|
+
</ul>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
`);
|
|
46
|
+
|
|
47
|
+
// Clear container and append the new buttons
|
|
48
|
+
$(container).empty().append(wikiButtonsDiv);
|
|
49
|
+
|
|
50
|
+
// Attach event handlers
|
|
51
|
+
wikiButtonsDiv.find('.btn-load-wiki').on('click', function(e) {
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
self.showConfirmationModal(() => {
|
|
54
|
+
self.loadFromWiki();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
wikiButtonsDiv.find('.btn-save-wiki').on('click', function(e) {
|
|
59
|
+
e.preventDefault();
|
|
60
|
+
self.saveToWiki();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
wikiButtonsDiv.find('.btn-save-as').on('click', function(e) {
|
|
64
|
+
e.preventDefault();
|
|
65
|
+
self.showSaveAsModal();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
wikiButtonsDiv.find('.btn-import-test').on('click', function(e) {
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
self.importFromTestJson();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
wikiButtonsDiv.find('.btn-import-json').on('click', function(e) {
|
|
74
|
+
e.preventDefault();
|
|
75
|
+
self.importFromJsonFile();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
wikiButtonsDiv.find('.btn-export-json').on('click', function(e) {
|
|
79
|
+
e.preventDefault();
|
|
80
|
+
self.doExportToJsonFile();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Add wipe button
|
|
84
|
+
this.addWipeButton();
|
|
85
|
+
|
|
86
|
+
// Setup Save As modal event listeners
|
|
87
|
+
$('#saveAsUseExistingPage').on('change', function() {
|
|
88
|
+
$('#saveAsPageSelect').prop('disabled', !this.checked);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
$('#saveAsConfirmBtn').off('click').on('click', function() {
|
|
92
|
+
self.saveAs();
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
8
96
|
/**
|
|
9
97
|
* When the page loads, get the URL paremeter with the target page title we want to edit:
|
|
10
98
|
* @returns
|
|
@@ -35,14 +123,14 @@ class WikiEditor {
|
|
|
35
123
|
let sm = new StepModel(step)
|
|
36
124
|
sm.setAsEdited();
|
|
37
125
|
});
|
|
38
|
-
reloadCropsFromJson(content);
|
|
126
|
+
self.tikaeditorInstance.reloadCropsFromJson(content);
|
|
39
127
|
|
|
40
128
|
let codeSnippet = `{{Graphique Triple Performance \n| title=${content.title} \n| json=${self.pageTitle} \n| type=Rotation }}`;
|
|
41
129
|
$('#code-snippet').val(codeSnippet).on('focus', function() {
|
|
42
130
|
$(this).select();
|
|
43
131
|
});
|
|
44
|
-
|
|
45
|
-
|
|
132
|
+
|
|
133
|
+
$('#codeSnippetDiv').show();
|
|
46
134
|
|
|
47
135
|
} catch (e) {
|
|
48
136
|
console.error("Erreur lors de l'analyse du JSON de la page :", e);
|
|
@@ -78,7 +166,7 @@ class WikiEditor {
|
|
|
78
166
|
}
|
|
79
167
|
|
|
80
168
|
// If a page title is provided, save to that page
|
|
81
|
-
self.savePageToWiki(self.pageTitle, JSON.stringify(
|
|
169
|
+
self.savePageToWiki(self.pageTitle, JSON.stringify(self.tikaeditorInstance.system, null, 2))
|
|
82
170
|
.then(async () => {
|
|
83
171
|
alert("Itinéraire technique enregistré avec succès !");
|
|
84
172
|
})
|
|
@@ -278,8 +366,8 @@ class WikiEditor {
|
|
|
278
366
|
|
|
279
367
|
// Set default filename from title if it's been changed
|
|
280
368
|
const filenameInput = $('#saveAsFilename');
|
|
281
|
-
const currentTitle =
|
|
282
|
-
if (
|
|
369
|
+
const currentTitle = self.tikaeditorInstance.system.title || '';
|
|
370
|
+
if (self.tikaeditorInstance.system.defaultTitle === false) {
|
|
283
371
|
filenameInput.val(currentTitle);
|
|
284
372
|
} else {
|
|
285
373
|
filenameInput.val('');
|
|
@@ -315,8 +403,8 @@ class WikiEditor {
|
|
|
315
403
|
// Build the final URL: subpagename/filename.json
|
|
316
404
|
const finalUrl = `${subpageName}/${filename}.json`;
|
|
317
405
|
|
|
318
|
-
if (
|
|
319
|
-
|
|
406
|
+
if (self.tikaeditorInstance.system.defaultTitle !== false) {
|
|
407
|
+
self.tikaeditorInstance.system.title = filename;
|
|
320
408
|
}
|
|
321
409
|
|
|
322
410
|
return finalUrl;
|
|
@@ -340,7 +428,7 @@ class WikiEditor {
|
|
|
340
428
|
self.pageTitle = url;
|
|
341
429
|
|
|
342
430
|
// Save to the wiki first
|
|
343
|
-
await self.savePageToWiki(self.pageTitle, JSON.stringify(
|
|
431
|
+
await self.savePageToWiki(self.pageTitle, JSON.stringify(self.tikaeditorInstance.system, null, 2));
|
|
344
432
|
|
|
345
433
|
// Close the modal
|
|
346
434
|
const modal = bootstrap.Modal.getInstance(document.getElementById('saveAsModal'));
|