@osfarm/itineraire-technique 1.1.19 → 1.2.0

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.
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Exemple d'utilisation avec Next.js App Router
3
+ * Fichier: app/itineraire/page.tsx
4
+ */
5
+
6
+ 'use client';
7
+
8
+ import { TikaRenderer } from '@osfarm/itineraire-technique/react';
9
+ import { useEffect, useState } from 'react';
10
+ import type { ItineraireData } from '@osfarm/itineraire-technique/react';
11
+
12
+ export default function ItinerairePage() {
13
+ const [data, setData] = useState<ItineraireData | null>(null);
14
+ const [loading, setLoading] = useState(true);
15
+ const [error, setError] = useState<string | null>(null);
16
+
17
+ useEffect(() => {
18
+ // Charger les données depuis votre API ou fichier JSON
19
+ fetch('/test/test.json')
20
+ .then(response => {
21
+ if (!response.ok) throw new Error('Erreur de chargement');
22
+ return response.json();
23
+ })
24
+ .then(data => {
25
+ setData(data);
26
+ setLoading(false);
27
+ })
28
+ .catch(err => {
29
+ setError(err.message);
30
+ setLoading(false);
31
+ });
32
+ }, []);
33
+
34
+ const handleItemClick = (itemId: string, event: Event) => {
35
+ console.log('Élément cliqué:', itemId);
36
+ // Vous pouvez ajouter votre logique ici (modal, navigation, etc.)
37
+ };
38
+
39
+ const handleItemHover = (itemId: string, event: Event) => {
40
+ console.log('Survol:', itemId);
41
+ };
42
+
43
+ if (loading) {
44
+ return (
45
+ <div className="container py-5 text-center">
46
+ <div className="spinner-border" role="status">
47
+ <span className="visually-hidden">Chargement...</span>
48
+ </div>
49
+ </div>
50
+ );
51
+ }
52
+
53
+ if (error) {
54
+ return (
55
+ <div className="container py-5">
56
+ <div className="alert alert-danger" role="alert">
57
+ Erreur: {error}
58
+ </div>
59
+ </div>
60
+ );
61
+ }
62
+
63
+ if (!data) {
64
+ return (
65
+ <div className="container py-5">
66
+ <div className="alert alert-info" role="alert">
67
+ Aucune donnée à afficher
68
+ </div>
69
+ </div>
70
+ );
71
+ }
72
+
73
+ return (
74
+ <div className="container-fluid py-5">
75
+ <div className="row">
76
+ <div className="col-12">
77
+ <h1 className="mb-4">{data.title}</h1>
78
+ <TikaRenderer
79
+ data={data}
80
+ width="100%"
81
+ height="auto"
82
+ onItemClick={handleItemClick}
83
+ onItemHover={handleItemHover}
84
+ className="shadow-sm"
85
+ />
86
+ </div>
87
+ </div>
88
+ </div>
89
+ );
90
+ }
@@ -117,6 +117,10 @@ class RotationRenderer {
117
117
  }
118
118
  }
119
119
 
120
+ resize() {
121
+ this.chart.resize();
122
+ }
123
+
120
124
  getElementID(element) {
121
125
  return element.classList.values().find(item => item.match(/Intervention_[0-9]+_[0-9]+|Step_[0-9]+/));
122
126
  }
@@ -220,7 +224,8 @@ class RotationRenderer {
220
224
 
221
225
  grid: {
222
226
  height: self.barHeight * 3,
223
- right: 6
227
+ right: 6,
228
+ left: 6
224
229
  },
225
230
 
226
231
  xAxis: {
package/package.json CHANGED
@@ -1,16 +1,89 @@
1
1
  {
2
2
  "name": "@osfarm/itineraire-technique",
3
- "version": "1.1.19",
4
- "description": "A visualisation tool to show agricultural technical itineraries based on Echarts",
5
- "main": "editor.html",
3
+ "version": "1.2.0",
4
+ "description": "A visualisation tool to show agricultural technical itineraries based on Echarts - with React/Next.js components",
5
+ "main": "js/chart-render.js",
6
+ "types": "react/types.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./js/chart-render.js",
10
+ "require": "./js/chart-render.js"
11
+ },
12
+ "./react": {
13
+ "import": "./react/index.ts",
14
+ "require": "./react/index.ts",
15
+ "types": "./react/types.ts"
16
+ },
17
+ "./react/TikaRenderer": {
18
+ "import": "./react/TikaRenderer.jsx",
19
+ "require": "./react/TikaRenderer.jsx"
20
+ },
21
+ "./react/TikaEditor": {
22
+ "import": "./react/TikaEditor.jsx",
23
+ "require": "./react/TikaEditor.jsx"
24
+ },
25
+ "./css/*": "./css/*",
26
+ "./js/*": "./js/*"
27
+ },
28
+ "files": [
29
+ "js",
30
+ "css",
31
+ "react",
32
+ "examples",
33
+ "test",
34
+ "images",
35
+ "*.html",
36
+ "LICENSE",
37
+ "README.md"
38
+ ],
6
39
  "scripts": {
7
40
  "build:scss": "sass --style=compressed scss/styles-editor.scss css/styles-editor.css && sass --style=compressed scss/styles-rendering.scss css/styles-rendering.css",
8
41
  "dev:scss": "sass scss/styles-editor.scss css/styles-editor.css && sass scss/styles-rendering.scss css/styles-rendering.css",
9
42
  "watch:scss": "sass --watch scss/styles-editor.scss:css/styles-editor.css scss/styles-rendering.scss:css/styles-rendering.css",
10
43
  "build": "npm run build:scss",
11
- "start": "npm run watch:scss"
44
+ "start": "npm run watch:scss",
45
+ "setup:react": "bash scripts/setup-react.sh || powershell -ExecutionPolicy Bypass -File scripts/setup-react.ps1",
46
+ "postinstall": "echo '\n✨ Pour utiliser avec React/Next.js, exécutez: npm run setup:react\n'"
47
+ },
48
+ "peerDependencies": {
49
+ "react": ">=16.8.0",
50
+ "react-dom": ">=16.8.0"
51
+ },
52
+ "peerDependenciesMeta": {
53
+ "react": {
54
+ "optional": true
55
+ },
56
+ "react-dom": {
57
+ "optional": true
58
+ }
12
59
  },
13
60
  "devDependencies": {
14
- "sass": "^1.85.1"
15
- }
61
+ "sass": "^1.85.1",
62
+ "@types/react": "^18.0.0",
63
+ "@types/react-dom": "^18.0.0"
64
+ },
65
+ "publishConfig": {
66
+ "access": "public"
67
+ },
68
+ "repository": {
69
+ "type": "git",
70
+ "url": "https://github.com/osfarm/itineraire-technique"
71
+ },
72
+ "homepage": "https://www.osfarm.org/itineraire-technique/",
73
+ "bugs": {
74
+ "url": "https://github.com/osfarm/itineraire-technique/issues"
75
+ },
76
+ "license": "MIT",
77
+ "keywords": [
78
+ "agriculture",
79
+ "echarts",
80
+ "visualization",
81
+ "farming",
82
+ "itineraire-technique",
83
+ "TIKA",
84
+ "react",
85
+ "nextjs",
86
+ "technical-itinerary",
87
+ "crop-rotation"
88
+ ]
16
89
  }
@@ -0,0 +1,172 @@
1
+ # Quick Start - React/Next.js
2
+
3
+ Guide rapide pour intégrer `@osfarm/itineraire-technique` dans votre projet React ou Next.js.
4
+
5
+ ## Installation (5 minutes)
6
+
7
+ ### Étape 1 : Installer le package
8
+
9
+ ```bash
10
+ npm install @osfarm/itineraire-technique
11
+ # ou
12
+ yarn add @osfarm/itineraire-technique
13
+ # ou
14
+ pnpm add @osfarm/itineraire-technique
15
+ ```
16
+
17
+ ### Étape 2 : Copier les fichiers statiques
18
+
19
+ ```bash
20
+ npm run setup:react
21
+ ```
22
+
23
+ Ce script copie automatiquement les fichiers JS, CSS et de test dans votre dossier `public/`.
24
+
25
+ ### Étape 3 : Ajouter les dépendances CDN
26
+
27
+ **Pour Next.js App Router** : Créez ou modifiez `app/layout.tsx` :
28
+
29
+ ```tsx
30
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
31
+ return (
32
+ <html lang="fr">
33
+ <head>
34
+ <script src="https://cdn.jsdelivr.net/npm/echarts@6.0.0/dist/echarts.js"></script>
35
+ <script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
36
+ <script src="https://cdn.jsdelivr.net/npm/underscore@1.13.7/underscore-umd-min.js"></script>
37
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
38
+ <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet" />
39
+
40
+ <script src="/js/chart-render.js"></script>
41
+ <link href="/css/styles-rendering.css" rel="stylesheet" />
42
+ </head>
43
+ <body>{children}</body>
44
+ </html>
45
+ );
46
+ }
47
+ ```
48
+
49
+ **Pour Next.js Pages Router** : Créez ou modifiez `pages/_document.tsx` (voir [exemple complet](../examples/nextjs-_document.tsx))
50
+
51
+ ## Utilisation - Visualiseur Simple
52
+
53
+ Créez un composant pour afficher un itinéraire :
54
+
55
+ ```tsx
56
+ 'use client'; // Pour Next.js App Router uniquement
57
+
58
+ import { TikaRenderer } from '@osfarm/itineraire-technique/react';
59
+ import { useEffect, useState } from 'react';
60
+
61
+ export default function MyItineraire() {
62
+ const [data, setData] = useState(null);
63
+
64
+ useEffect(() => {
65
+ // Charger les données de test
66
+ fetch('/test/test.json')
67
+ .then(res => res.json())
68
+ .then(setData);
69
+ }, []);
70
+
71
+ if (!data) return <div>Chargement...</div>;
72
+
73
+ return (
74
+ <div className="container">
75
+ <h1>{data.title}</h1>
76
+ <TikaRenderer data={data} />
77
+ </div>
78
+ );
79
+ }
80
+ ```
81
+
82
+ ## Utilisation - Éditeur Simple
83
+
84
+ ```tsx
85
+ 'use client';
86
+
87
+ import { useItineraire } from '@osfarm/itineraire-technique/react';
88
+ import { TikaRenderer } from '@osfarm/itineraire-technique/react';
89
+
90
+ export default function MyEditor() {
91
+ const { data, addStep, exportToJson } = useItineraire({
92
+ title: "Ma rotation",
93
+ options: { view: "horizontal", show_transcript: true },
94
+ steps: []
95
+ });
96
+
97
+ const handleAddCrop = () => {
98
+ addStep({
99
+ id: crypto.randomUUID(),
100
+ name: 'Nouvelle culture',
101
+ startDate: new Date().toISOString(),
102
+ endDate: new Date(Date.now() + 90*24*60*60*1000).toISOString(),
103
+ color: '#4CAF50',
104
+ interventions: []
105
+ });
106
+ };
107
+
108
+ return (
109
+ <div className="container">
110
+ <button className="btn btn-primary" onClick={handleAddCrop}>
111
+ Ajouter une culture
112
+ </button>
113
+ <button className="btn btn-secondary" onClick={() => console.log(exportToJson())}>
114
+ Exporter JSON
115
+ </button>
116
+
117
+ {data && <TikaRenderer data={data} />}
118
+ </div>
119
+ );
120
+ }
121
+ ```
122
+
123
+ ## TypeScript Support
124
+
125
+ Types inclus ! Importez-les directement :
126
+
127
+ ```tsx
128
+ import type { ItineraireData, Step, Intervention } from '@osfarm/itineraire-technique/react';
129
+
130
+ const myRotation: ItineraireData = {
131
+ title: "Ma rotation bio",
132
+ options: {
133
+ view: "horizontal",
134
+ show_transcript: true
135
+ },
136
+ steps: []
137
+ };
138
+ ```
139
+
140
+ ## Exemples Complets
141
+
142
+ Consultez le dossier [`examples/`](../examples/) pour :
143
+ - ✅ Visualiseur Next.js App Router
144
+ - ✅ Éditeur Next.js App Router
145
+ - ✅ Configuration `_document.tsx`
146
+ - ✅ API Routes pour sauvegarder/charger des données
147
+
148
+ ## Troubleshooting
149
+
150
+ ### "RotationRenderer is not defined"
151
+
152
+ ➡️ Vérifiez que `/js/chart-render.js` est bien chargé dans votre HTML/layout
153
+ ➡️ Utilisez le hook `useItineraireDependencies` pour vérifier le chargement
154
+
155
+ ### Les styles ne s'appliquent pas
156
+
157
+ ➡️ Assurez-vous d'avoir chargé `/css/styles-rendering.css`
158
+ ➡️ Vérifiez que Bootstrap CSS est aussi chargé
159
+
160
+ ### Erreur "use client" manquant
161
+
162
+ ➡️ Ajoutez `'use client';` en haut de vos composants qui utilisent des hooks React
163
+
164
+ ## Documentation Complète
165
+
166
+ 📚 [Documentation React complète](README.md)
167
+
168
+ ## Besoin d'aide ?
169
+
170
+ - 🐛 [Signaler un bug](https://github.com/osfarm/itineraire-technique/issues)
171
+ - 💬 [Questions et discussions](https://github.com/osfarm/itineraire-technique/discussions)
172
+ - 📖 [Documentation Triple Performance](https://wiki.tripleperformance.fr/)
@@ -0,0 +1,305 @@
1
+ # Utilisation avec React et Next.js
2
+
3
+ Ce package peut être utilisé dans des applications React et Next.js. Voici comment l'intégrer.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @osfarm/itineraire-technique
9
+ ```
10
+
11
+ ## Dépendances à inclure
12
+
13
+ Les composants React dépendent de plusieurs bibliothèques externes qui doivent être chargées. Vous avez deux options :
14
+
15
+ ### Option 1 : Via CDN (recommandé pour Next.js)
16
+
17
+ Dans votre `_document.tsx` ou `_app.tsx` (Next.js) ou dans votre `index.html` (React) :
18
+
19
+ ```tsx
20
+ // pages/_document.tsx (Next.js)
21
+ import { Html, Head, Main, NextScript } from 'next/document'
22
+
23
+ export default function Document() {
24
+ return (
25
+ <Html>
26
+ <Head>
27
+ {/* ECharts */}
28
+ <script src="https://cdn.jsdelivr.net/npm/echarts@6.0.0/dist/echarts.js"></script>
29
+
30
+ {/* jQuery */}
31
+ <script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
32
+ <script src="https://cdn.jsdelivr.net/npm/jquery-ui@1.14.1/dist/jquery-ui.min.js"></script>
33
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-ui@1.14.1/themes/base/jquery-ui.css" />
34
+
35
+ {/* Underscore */}
36
+ <script src="https://cdn.jsdelivr.net/npm/underscore@1.13.7/underscore-umd-min.js"></script>
37
+
38
+ {/* Bootstrap (pour l'éditeur) */}
39
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
40
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
41
+
42
+ {/* Font Awesome */}
43
+ <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet" />
44
+
45
+ {/* Scripts TIKA */}
46
+ <script src="/chart-render.js"></script>
47
+ <script src="/editor-attributes.js"></script>
48
+ <script src="/editor-interventions.js"></script>
49
+ <script src="/editor-crops.js"></script>
50
+ <script src="/editor-export.js"></script>
51
+ <script src="/editor-wiki-editor.js"></script>
52
+
53
+ {/* Styles TIKA */}
54
+ <link href="/styles-rendering.css" rel="stylesheet" />
55
+ <link href="/styles-editor.css" rel="stylesheet" />
56
+ </Head>
57
+ <body>
58
+ <Main />
59
+ <NextScript />
60
+ </body>
61
+ </Html>
62
+ )
63
+ }
64
+ ```
65
+
66
+ ### Option 2 : Via NPM
67
+
68
+ ```bash
69
+ npm install echarts jquery jquery-ui underscore bootstrap
70
+ ```
71
+
72
+ Puis importez-les dans votre application.
73
+
74
+ ## Copier les fichiers statiques
75
+
76
+ Copiez les fichiers JS et CSS depuis `node_modules/@osfarm/itineraire-technique/` vers votre dossier `public/` :
77
+
78
+ ```bash
79
+ # Créer les dossiers
80
+ mkdir -p public/js public/css
81
+
82
+ # Copier les fichiers JS
83
+ cp node_modules/@osfarm/itineraire-technique/js/*.js public/
84
+
85
+ # Copier les fichiers CSS
86
+ cp node_modules/@osfarm/itineraire-technique/css/*.css public/
87
+ ```
88
+
89
+ ## Utilisation du composant de visualisation
90
+
91
+ ```tsx
92
+ 'use client'; // Pour Next.js App Router
93
+
94
+ import { TikaRenderer } from '@osfarm/itineraire-technique/react';
95
+ import { useEffect, useState } from 'react';
96
+
97
+ export default function ItinerairePage() {
98
+ const [data, setData] = useState(null);
99
+ const [loading, setLoading] = useState(true);
100
+
101
+ useEffect(() => {
102
+ // Charger vos données depuis une API ou un fichier
103
+ fetch('/api/itineraire')
104
+ .then(res => res.json())
105
+ .then(data => {
106
+ setData(data);
107
+ setLoading(false);
108
+ });
109
+ }, []);
110
+
111
+ if (loading) return <div>Chargement...</div>;
112
+ if (!data) return <div>Aucune donnée</div>;
113
+
114
+ return (
115
+ <div className="container">
116
+ <h1>Itinéraire Technique</h1>
117
+ <TikaRenderer
118
+ data={data}
119
+ width="100%"
120
+ height="600px"
121
+ onItemClick={(itemId, event) => {
122
+ console.log('Item clicked:', itemId);
123
+ }}
124
+ />
125
+ </div>
126
+ );
127
+ }
128
+ ```
129
+
130
+ ## Utilisation du composant éditeur
131
+
132
+ ```tsx
133
+ 'use client';
134
+
135
+ import { TikaEditor } from '@osfarm/itineraire-technique/react';
136
+ import { useState } from 'react';
137
+
138
+ export default function EditorPage() {
139
+ const [data, setData] = useState({
140
+ title: "Ma rotation",
141
+ options: {
142
+ view: "horizontal",
143
+ show_transcript: true,
144
+ title_top_interventions: "Cultures principales",
145
+ title_bottom_interventions: "Couverts",
146
+ title_steps: "Rotation",
147
+ region: "France"
148
+ },
149
+ steps: []
150
+ });
151
+
152
+ const handleSave = (newData) => {
153
+ console.log('Données sauvegardées:', newData);
154
+ setData(newData);
155
+
156
+ // Envoyer à votre API
157
+ fetch('/api/itineraire', {
158
+ method: 'POST',
159
+ headers: { 'Content-Type': 'application/json' },
160
+ body: JSON.stringify(newData)
161
+ });
162
+ };
163
+
164
+ const handleExport = (data) => {
165
+ // Télécharger le JSON
166
+ const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
167
+ const url = URL.createObjectURL(blob);
168
+ const a = document.createElement('a');
169
+ a.href = url;
170
+ a.download = 'itineraire.json';
171
+ a.click();
172
+ };
173
+
174
+ return (
175
+ <div className="container">
176
+ <h1>Éditeur d'Itinéraire Technique</h1>
177
+ <TikaEditor
178
+ initialData={data}
179
+ onSave={handleSave}
180
+ onExport={handleExport}
181
+ enableAutoSave={true}
182
+ autoSaveInterval={10000}
183
+ />
184
+ </div>
185
+ );
186
+ }
187
+ ```
188
+
189
+ ## Utilisation avec le hook personnalisé
190
+
191
+ ```tsx
192
+ 'use client';
193
+
194
+ import { useItineraire } from '@osfarm/itineraire-technique/react';
195
+ import { TikaRenderer } from '@osfarm/itineraire-technique/react';
196
+
197
+ export default function MyComponent() {
198
+ const {
199
+ data,
200
+ loading,
201
+ error,
202
+ addStep,
203
+ updateStep,
204
+ deleteStep,
205
+ exportToJson
206
+ } = useItineraire(initialData);
207
+
208
+ const handleAddStep = () => {
209
+ const newStep = {
210
+ id: crypto.randomUUID(),
211
+ name: 'Nouvelle culture',
212
+ startDate: new Date().toISOString(),
213
+ endDate: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toISOString(),
214
+ color: '#4CAF50',
215
+ interventions: []
216
+ };
217
+ addStep(newStep);
218
+ };
219
+
220
+ if (loading) return <div>Chargement...</div>;
221
+ if (error) return <div>Erreur: {error.message}</div>;
222
+ if (!data) return <div>Aucune donnée</div>;
223
+
224
+ return (
225
+ <div>
226
+ <button onClick={handleAddStep}>Ajouter une étape</button>
227
+ <button onClick={() => console.log(exportToJson())}>Exporter JSON</button>
228
+ <TikaRenderer data={data} />
229
+ </div>
230
+ );
231
+ }
232
+ ```
233
+
234
+ ## TypeScript
235
+
236
+ Les types TypeScript sont inclus. Importez-les depuis le package :
237
+
238
+ ```tsx
239
+ import type {
240
+ ItineraireData,
241
+ Step,
242
+ Intervention
243
+ } from '@osfarm/itineraire-technique/react';
244
+
245
+ const myData: ItineraireData = {
246
+ title: "Ma rotation",
247
+ options: {
248
+ view: "horizontal",
249
+ show_transcript: true
250
+ },
251
+ steps: []
252
+ };
253
+ ```
254
+
255
+ ## Configuration Next.js
256
+
257
+ Si vous utilisez Next.js 13+ avec App Router, assurez-vous que vos composants sont marqués avec `'use client'` car ils utilisent des hooks React et accèdent au DOM.
258
+
259
+ ### next.config.js
260
+
261
+ ```javascript
262
+ /** @type {import('next').NextConfig} */
263
+ const nextConfig = {
264
+ // Permettre les scripts externes
265
+ experimental: {
266
+ externalDir: true
267
+ }
268
+ }
269
+
270
+ module.exports = nextConfig
271
+ ```
272
+
273
+ ## Exemples complets
274
+
275
+ Consultez le dossier `examples/` pour des exemples complets d'intégration avec :
276
+ - Next.js App Router
277
+ - Next.js Pages Router
278
+ - Create React App
279
+ - Vite + React
280
+
281
+ ## Troubleshooting
282
+
283
+ ### "RotationRenderer is not defined"
284
+
285
+ Assurez-vous que `chart-render.js` est chargé avant le rendu de votre composant. Utilisez `useItineraireDependencies` pour vérifier :
286
+
287
+ ```tsx
288
+ import { useItineraireDependencies } from '@osfarm/itineraire-technique/react';
289
+
290
+ function MyComponent() {
291
+ const { loaded, error } = useItineraireDependencies();
292
+
293
+ if (!loaded) return <div>Chargement des dépendances...</div>;
294
+ if (error) return <div>Erreur: {error.message}</div>;
295
+
296
+ return <TikaRenderer data={data} />;
297
+ }
298
+ ```
299
+
300
+ ### Problèmes de styles
301
+
302
+ Assurez-vous que les fichiers CSS sont bien importés :
303
+ - `styles-rendering.css` pour le visualiseur
304
+ - `styles-editor.css` pour l'éditeur
305
+ - Bootstrap pour l'interface de l'éditeur