@osfarm/itineraire-technique 1.1.20 → 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.
- package/README.md +34 -2
- package/examples/README.md +137 -0
- package/examples/nextjs-_document.tsx +66 -0
- package/examples/nextjs-api-route.ts +122 -0
- package/examples/nextjs-app-router-editor.tsx +304 -0
- package/examples/nextjs-app-router-viewer.tsx +90 -0
- package/package.json +59 -6
- package/react/QUICKSTART.md +172 -0
- package/react/README.md +305 -0
- package/react/TikaEditor.jsx +212 -0
- package/react/TikaRenderer.jsx +116 -0
- package/react/hooks.ts +217 -0
- package/react/index.ts +19 -0
- package/react/types.ts +152 -0
- package/.github/copilot-instructions.md +0 -56
- package/.github/workflows/publish.yml +0 -34
- package/scss/styles-editor.scss +0 -149
- package/scss/styles-rendering.scss +0 -184
|
@@ -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
|
+
}
|
package/package.json
CHANGED
|
@@ -1,17 +1,66 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@osfarm/itineraire-technique",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "A visualisation tool to show agricultural technical itineraries based on Echarts",
|
|
5
|
-
"main": "
|
|
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"
|
|
61
|
+
"sass": "^1.85.1",
|
|
62
|
+
"@types/react": "^18.0.0",
|
|
63
|
+
"@types/react-dom": "^18.0.0"
|
|
15
64
|
},
|
|
16
65
|
"publishConfig": {
|
|
17
66
|
"access": "public"
|
|
@@ -31,6 +80,10 @@
|
|
|
31
80
|
"visualization",
|
|
32
81
|
"farming",
|
|
33
82
|
"itineraire-technique",
|
|
34
|
-
"TIKA"
|
|
83
|
+
"TIKA",
|
|
84
|
+
"react",
|
|
85
|
+
"nextjs",
|
|
86
|
+
"technical-itinerary",
|
|
87
|
+
"crop-rotation"
|
|
35
88
|
]
|
|
36
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/)
|
package/react/README.md
ADDED
|
@@ -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
|