simondh commited on
Commit
5bc350f
·
verified ·
1 Parent(s): 28f2bff

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +772 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Classifications
3
- emoji: 🚀
4
- colorFrom: pink
5
- colorTo: yellow
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: classifications
3
+ emoji: 🐳
4
+ colorFrom: red
5
+ colorTo: red
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,772 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="fr">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Système de Classification Textuelle</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ .dropzone {
11
+ border: 2px dashed #cbd5e0;
12
+ transition: all 0.3s ease;
13
+ }
14
+ .dropzone.active {
15
+ border-color: #4f46e5;
16
+ background-color: #eef2ff;
17
+ }
18
+ .progress-bar {
19
+ transition: width 0.3s ease;
20
+ }
21
+ .category-chip {
22
+ transition: all 0.2s ease;
23
+ }
24
+ .category-chip:hover {
25
+ transform: translateY(-2px);
26
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
27
+ }
28
+ .fade-in {
29
+ animation: fadeIn 0.5s ease-in-out;
30
+ }
31
+ @keyframes fadeIn {
32
+ from { opacity: 0; transform: translateY(10px); }
33
+ to { opacity: 1; transform: translateY(0); }
34
+ }
35
+ </style>
36
+ </head>
37
+ <body class="bg-gray-50 min-h-screen">
38
+ <div class="container mx-auto px-4 py-8">
39
+ <!-- Header -->
40
+ <header class="mb-8 text-center">
41
+ <h1 class="text-3xl font-bold text-indigo-700 mb-2">
42
+ <i class="fas fa-project-diagram mr-2"></i>Système de Classification Textuelle
43
+ </h1>
44
+ <p class="text-gray-600 max-w-2xl mx-auto">
45
+ Un outil simple et transparent pour classifier automatiquement vos données textuelles
46
+ </p>
47
+ </header>
48
+
49
+ <!-- Main Content -->
50
+ <div class="bg-white rounded-xl shadow-md overflow-hidden">
51
+ <!-- Process Steps -->
52
+ <div class="flex justify-between px-6 py-4 border-b">
53
+ <div class="step flex-1 text-center relative" data-step="1">
54
+ <div class="w-10 h-10 mx-auto rounded-full bg-indigo-600 text-white flex items-center justify-center font-bold mb-2">
55
+ 1
56
+ </div>
57
+ <p class="text-sm font-medium text-indigo-600">Import des données</p>
58
+ <div class="absolute bottom-0 left-0 right-0 h-1 bg-indigo-600"></div>
59
+ </div>
60
+ <div class="step flex-1 text-center relative" data-step="2">
61
+ <div class="w-10 h-10 mx-auto rounded-full bg-gray-200 text-gray-600 flex items-center justify-center font-bold mb-2">
62
+ 2
63
+ </div>
64
+ <p class="text-sm font-medium text-gray-500">Configuration</p>
65
+ <div class="absolute bottom-0 left-0 right-0 h-1 bg-gray-200"></div>
66
+ </div>
67
+ <div class="step flex-1 text-center relative" data-step="3">
68
+ <div class="w-10 h-10 mx-auto rounded-full bg-gray-200 text-gray-600 flex items-center justify-center font-bold mb-2">
69
+ 3
70
+ </div>
71
+ <p class="text-sm font-medium text-gray-500">Classification</p>
72
+ <div class="absolute bottom-0 left-0 right-0 h-1 bg-gray-200"></div>
73
+ </div>
74
+ <div class="step flex-1 text-center relative" data-step="4">
75
+ <div class="w-10 h-10 mx-auto rounded-full bg-gray-200 text-gray-600 flex items-center justify-center font-bold mb-2">
76
+ 4
77
+ </div>
78
+ <p class="text-sm font-medium text-gray-500">Résultats</p>
79
+ <div class="absolute bottom-0 left-0 right-0 h-1 bg-gray-200"></div>
80
+ </div>
81
+ </div>
82
+
83
+ <!-- Step 1 Content -->
84
+ <div id="step-1" class="p-6 fade-in">
85
+ <h2 class="text-xl font-semibold mb-4 text-gray-800">
86
+ <i class="fas fa-file-import mr-2 text-indigo-500"></i>Importez vos données
87
+ </h2>
88
+
89
+ <div class="mb-6">
90
+ <div id="dropzone" class="dropzone rounded-lg p-8 text-center cursor-pointer">
91
+ <div class="mx-auto w-16 h-16 bg-indigo-100 rounded-full flex items-center justify-center mb-4">
92
+ <i class="fas fa-cloud-upload-alt text-indigo-500 text-2xl"></i>
93
+ </div>
94
+ <h3 class="text-lg font-medium text-gray-700 mb-1">Glissez-déposez votre fichier</h3>
95
+ <p class="text-gray-500 mb-4">ou cliquez pour sélectionner</p>
96
+ <input type="file" id="fileInput" class="hidden" accept=".csv,.xlsx,.xls">
97
+ <button id="selectFileBtn" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 transition">
98
+ <i class="fas fa-folder-open mr-2"></i>Sélectionner un fichier
99
+ </button>
100
+ <p class="text-xs text-gray-400 mt-3">Formats supportés: CSV, XLSX, XLS</p>
101
+ </div>
102
+ </div>
103
+
104
+ <div id="filePreview" class="hidden border rounded-lg overflow-hidden">
105
+ <div class="bg-gray-50 px-4 py-3 border-b flex justify-between items-center">
106
+ <div>
107
+ <span id="fileName" class="font-medium"></span>
108
+ <span id="fileSize" class="text-sm text-gray-500 ml-2"></span>
109
+ </div>
110
+ <button id="removeFileBtn" class="text-red-500 hover:text-red-700">
111
+ <i class="fas fa-times"></i>
112
+ </button>
113
+ </div>
114
+ <div class="overflow-x-auto">
115
+ <table class="min-w-full divide-y divide-gray-200">
116
+ <thead class="bg-gray-100">
117
+ <tr>
118
+ <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Colonnes détectées</th>
119
+ </tr>
120
+ </thead>
121
+ <tbody id="columnsList" class="bg-white divide-y divide-gray-200">
122
+ <!-- Columns will be added here by JS -->
123
+ </tbody>
124
+ </table>
125
+ </div>
126
+ </div>
127
+
128
+ <div class="flex justify-end mt-6">
129
+ <button id="nextStep1" class="px-6 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 transition disabled:opacity-50 disabled:cursor-not-allowed" disabled>
130
+ Suivant <i class="fas fa-arrow-right ml-2"></i>
131
+ </button>
132
+ </div>
133
+ </div>
134
+
135
+ <!-- Step 2 Content -->
136
+ <div id="step-2" class="hidden p-6">
137
+ <h2 class="text-xl font-semibold mb-4 text-gray-800">
138
+ <i class="fas fa-cog mr-2 text-indigo-500"></i>Configurez la classification
139
+ </h2>
140
+
141
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
142
+ <div>
143
+ <label class="block text-sm font-medium text-gray-700 mb-1">Colonne à classifier</label>
144
+ <select id="textColumnSelect" class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
145
+ <option value="">Sélectionnez une colonne</option>
146
+ </select>
147
+ </div>
148
+
149
+ <div>
150
+ <label class="block text-sm font-medium text-gray-700 mb-1">Méthode de classification</label>
151
+ <select id="classificationMethod" class="w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
152
+ <option value="keywords">Mots-clés</option>
153
+ <option value="ai">IA (recommandé)</option>
154
+ <option value="regex">Expressions régulières</option>
155
+ </select>
156
+ </div>
157
+ </div>
158
+
159
+ <div id="keywordsConfig" class="mb-6">
160
+ <div class="flex justify-between items-center mb-2">
161
+ <label class="block text-sm font-medium text-gray-700">Catégories et mots-clés</label>
162
+ <button id="addCategoryBtn" class="text-sm text-indigo-600 hover:text-indigo-800 flex items-center">
163
+ <i class="fas fa-plus-circle mr-1"></i> Ajouter une catégorie
164
+ </button>
165
+ </div>
166
+
167
+ <div id="categoriesContainer" class="space-y-3">
168
+ <div class="category-group border rounded-lg p-4 bg-gray-50">
169
+ <div class="flex justify-between items-center mb-3">
170
+ <input type="text" placeholder="Nom de la catégorie" class="category-name flex-1 border-b border-gray-300 focus:border-indigo-500 focus:outline-none bg-transparent py-1">
171
+ <button class="remove-category text-red-500 hover:text-red-700 ml-2">
172
+ <i class="fas fa-trash"></i>
173
+ </button>
174
+ </div>
175
+ <div class="flex flex-wrap gap-2">
176
+ <div class="keyword-chip flex items-center bg-white px-3 py-1 rounded-full text-sm shadow-sm">
177
+ <span>exemple</span>
178
+ <button class="remove-keyword ml-1 text-gray-400 hover:text-red-500">
179
+ <i class="fas fa-times text-xs"></i>
180
+ </button>
181
+ </div>
182
+ <input type="text" placeholder="Ajouter un mot-clé" class="keyword-input flex-1 min-w-[100px] border-b border-gray-300 focus:border-indigo-500 focus:outline-none bg-transparent py-1">
183
+ </div>
184
+ </div>
185
+ </div>
186
+ </div>
187
+
188
+ <div id="aiConfig" class="hidden mb-6">
189
+ <div class="bg-blue-50 border border-blue-200 rounded-lg p-4">
190
+ <div class="flex">
191
+ <div class="flex-shrink-0">
192
+ <i class="fas fa-robot text-blue-500 text-xl"></i>
193
+ </div>
194
+ <div class="ml-3">
195
+ <h3 class="text-sm font-medium text-blue-800">Classification par IA</h3>
196
+ <div class="mt-2 text-sm text-blue-700">
197
+ <p>Notre système d'IA analysera automatiquement le contenu textuel et proposera des catégories pertinentes. Vous pourrez ajuster les résultats après la classification initiale.</p>
198
+ </div>
199
+ </div>
200
+ </div>
201
+ </div>
202
+ </div>
203
+
204
+ <div id="regexConfig" class="hidden mb-6">
205
+ <div class="bg-purple-50 border border-purple-200 rounded-lg p-4">
206
+ <div class="flex">
207
+ <div class="flex-shrink-0">
208
+ <i class="fas fa-code text-purple-500 text-xl"></i>
209
+ </div>
210
+ <div class="ml-3">
211
+ <h3 class="text-sm font-medium text-purple-800">Expressions régulières</h3>
212
+ <div class="mt-2 text-sm text-purple-700">
213
+ <p>Définissez des motifs complexes pour classifier vos données. Requiert une connaissance des expressions régulières.</p>
214
+ </div>
215
+ </div>
216
+ </div>
217
+ </div>
218
+
219
+ <div class="mt-4">
220
+ <label class="block text-sm font-medium text-gray-700 mb-1">Ajouter une règle Regex</label>
221
+ <div class="flex space-x-2">
222
+ <input type="text" placeholder="Nom de la catégorie" class="flex-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
223
+ <input type="text" placeholder="Expression régulière" class="flex-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
224
+ <button class="px-3 py-1 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">
225
+ <i class="fas fa-plus"></i>
226
+ </button>
227
+ </div>
228
+ </div>
229
+ </div>
230
+
231
+ <div class="flex justify-between mt-6">
232
+ <button id="prevStep2" class="px-6 py-2 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 transition">
233
+ <i class="fas fa-arrow-left mr-2"></i> Précédent
234
+ </button>
235
+ <button id="nextStep2" class="px-6 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 transition disabled:opacity-50 disabled:cursor-not-allowed" disabled>
236
+ Suivant <i class="fas fa-arrow-right ml-2"></i>
237
+ </button>
238
+ </div>
239
+ </div>
240
+
241
+ <!-- Step 3 Content -->
242
+ <div id="step-3" class="hidden p-6">
243
+ <h2 class="text-xl font-semibold mb-4 text-gray-800">
244
+ <i class="fas fa-tasks mr-2 text-indigo-500"></i>Classification en cours
245
+ </h2>
246
+
247
+ <div class="bg-gray-50 rounded-lg p-6 text-center">
248
+ <div class="w-24 h-24 mx-auto mb-6 relative">
249
+ <div class="absolute inset-0 flex items-center justify-center">
250
+ <i class="fas fa-cog text-indigo-400 text-4xl animate-spin"></i>
251
+ </div>
252
+ <svg class="w-full h-full" viewBox="0 0 100 100">
253
+ <circle cx="50" cy="50" r="45" fill="none" stroke="#e5e7eb" stroke-width="10"/>
254
+ <circle id="progressCircle" cx="50" cy="50" r="45" fill="none" stroke="#4f46e5" stroke-width="10" stroke-dasharray="283" stroke-dashoffset="283" stroke-linecap="round" transform="rotate(-90 50 50)"/>
255
+ </svg>
256
+ </div>
257
+
258
+ <h3 id="progressText" class="text-lg font-medium text-gray-700 mb-2">Préparation de la classification...</h3>
259
+ <p id="progressSubtext" class="text-gray-500 mb-4">Veuillez patienter pendant le traitement de vos données</p>
260
+
261
+ <div class="w-full bg-gray-200 rounded-full h-2.5 mb-6">
262
+ <div id="progressBar" class="bg-indigo-600 h-2.5 rounded-full" style="width: 0%"></div>
263
+ </div>
264
+
265
+ <div id="progressDetails" class="hidden text-left bg-white p-4 rounded-lg border mb-4">
266
+ <div class="flex justify-between mb-2">
267
+ <span class="text-sm font-medium">Lignes traitées</span>
268
+ <span id="processedRows" class="text-sm">0/0</span>
269
+ </div>
270
+ <div class="flex justify-between mb-2">
271
+ <span class="text-sm font-medium">Catégories identifiées</span>
272
+ <span id="identifiedCategories" class="text-sm">0</span>
273
+ </div>
274
+ <div class="flex justify-between">
275
+ <span class="text-sm font-medium">Confiance moyenne</span>
276
+ <span id="averageConfidence" class="text-sm">0%</span>
277
+ </div>
278
+ </div>
279
+
280
+ <button id="cancelProcessBtn" class="px-4 py-2 bg-red-100 text-red-600 rounded-md hover:bg-red-200 transition">
281
+ <i class="fas fa-stop-circle mr-2"></i>Annuler
282
+ </button>
283
+ </div>
284
+ </div>
285
+
286
+ <!-- Step 4 Content -->
287
+ <div id="step-4" class="hidden p-6">
288
+ <h2 class="text-xl font-semibold mb-4 text-gray-800">
289
+ <i class="fas fa-chart-bar mr-2 text-indigo-500"></i>Résultats de la classification
290
+ </h2>
291
+
292
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6">
293
+ <div class="bg-white border rounded-lg p-4 shadow-sm">
294
+ <h3 class="text-sm font-medium text-gray-500 mb-2">Résumé</h3>
295
+ <div class="space-y-3">
296
+ <div>
297
+ <p class="text-xs text-gray-400">Fichier analysé</p>
298
+ <p id="resultFileName" class="font-medium">donnees.csv</p>
299
+ </div>
300
+ <div>
301
+ <p class="text-xs text-gray-400">Lignes classifiées</p>
302
+ <p id="resultTotalRows" class="font-medium">1,245</p>
303
+ </div>
304
+ <div>
305
+ <p class="text-xs text-gray-400">Catégories identifiées</p>
306
+ <p id="resultTotalCategories" class="font-medium">8</p>
307
+ </div>
308
+ </div>
309
+ </div>
310
+
311
+ <div class="bg-white border rounded-lg p-4 shadow-sm">
312
+ <h3 class="text-sm font-medium text-gray-500 mb-2">Distribution des catégories</h3>
313
+ <div id="categoryDistributionChart" class="h-40">
314
+ <!-- Chart will be rendered here -->
315
+ <div class="flex items-center justify-center h-full text-gray-400">
316
+ <i class="fas fa-chart-pie text-3xl mr-2"></i>
317
+ <span>Graphique de distribution</span>
318
+ </div>
319
+ </div>
320
+ </div>
321
+
322
+ <div class="bg-white border rounded-lg p-4 shadow-sm">
323
+ <h3 class="text-sm font-medium text-gray-500 mb-2">Actions</h3>
324
+ <div class="space-y-2">
325
+ <button id="exportResultsBtn" class="w-full flex items-center justify-between px-3 py-2 bg-indigo-50 text-indigo-600 rounded hover:bg-indigo-100">
326
+ <span><i class="fas fa-file-export mr-2"></i>Exporter les résultats</span>
327
+ <i class="fas fa-chevron-right"></i>
328
+ </button>
329
+ <button id="adjustCategoriesBtn" class="w-full flex items-center justify-between px-3 py-2 bg-blue-50 text-blue-600 rounded hover:bg-blue-100">
330
+ <span><i class="fas fa-edit mr-2"></i>Ajuster les catégories</span>
331
+ <i class="fas fa-chevron-right"></i>
332
+ </button>
333
+ <button id="newClassificationBtn" class="w-full flex items-center justify-between px-3 py-2 bg-gray-100 text-gray-700 rounded hover:bg-gray-200">
334
+ <span><i class="fas fa-redo mr-2"></i>Nouvelle classification</span>
335
+ <i class="fas fa-chevron-right"></i>
336
+ </button>
337
+ </div>
338
+ </div>
339
+ </div>
340
+
341
+ <div class="bg-white border rounded-lg overflow-hidden mb-6">
342
+ <div class="bg-gray-50 px-4 py-3 border-b flex justify-between items-center">
343
+ <div class="flex items-center">
344
+ <span class="font-medium">Résultats détaillés</span>
345
+ <span class="ml-2 text-xs bg-indigo-100 text-indigo-800 px-2 py-1 rounded-full">1,245 éléments</span>
346
+ </div>
347
+ <div class="flex space-x-2">
348
+ <div class="relative">
349
+ <input type="text" placeholder="Rechercher..." class="pl-8 pr-3 py-1 border rounded-md text-sm focus:ring-indigo-500 focus:border-indigo-500">
350
+ <i class="fas fa-search absolute left-2.5 top-1/2 transform -translate-y-1/2 text-gray-400"></i>
351
+ </div>
352
+ <select class="border rounded-md text-sm focus:ring-indigo-500 focus:border-indigo-500">
353
+ <option>Trier par catégorie</option>
354
+ <option>Trier par confiance</option>
355
+ </select>
356
+ </div>
357
+ </div>
358
+ <div class="overflow-x-auto">
359
+ <table class="min-w-full divide-y divide-gray-200">
360
+ <thead class="bg-gray-100">
361
+ <tr>
362
+ <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Texte original</th>
363
+ <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Catégorie</th>
364
+ <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Confiance</th>
365
+ <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Actions</th>
366
+ </tr>
367
+ </thead>
368
+ <tbody id="resultsTable" class="bg-white divide-y divide-gray-200">
369
+ <!-- Sample row -->
370
+ <tr>
371
+ <td class="px-4 py-3 text-sm max-w-xs truncate">Ceci est un exemple de texte qui a été classifié dans la catégorie "Exemple"</td>
372
+ <td class="px-4 py-3">
373
+ <span class="px-2 py-1 bg-indigo-100 text-indigo-800 text-xs rounded-full">Exemple</span>
374
+ </td>
375
+ <td class="px-4 py-3">
376
+ <div class="flex items-center">
377
+ <div class="w-16 bg-gray-200 rounded-full h-1.5 mr-2">
378
+ <div class="bg-green-500 h-1.5 rounded-full" style="width: 95%"></div>
379
+ </div>
380
+ <span class="text-xs">95%</span>
381
+ </div>
382
+ </td>
383
+ <td class="px-4 py-3 text-sm">
384
+ <button class="text-indigo-600 hover:text-indigo-900 mr-2">
385
+ <i class="fas fa-edit"></i>
386
+ </button>
387
+ <button class="text-red-600 hover:text-red-900">
388
+ <i class="fas fa-trash"></i>
389
+ </button>
390
+ </td>
391
+ </tr>
392
+ <!-- More rows will be added here -->
393
+ </tbody>
394
+ </table>
395
+ </div>
396
+ <div class="bg-gray-50 px-4 py-3 border-t flex items-center justify-between">
397
+ <div class="text-sm text-gray-500">
398
+ Affichage de <span class="font-medium">1</span> à <span class="font-medium">10</span> sur <span class="font-medium">1,245</span> résultats
399
+ </div>
400
+ <div class="flex space-x-1">
401
+ <button class="px-3 py-1 border rounded-md text-sm font-medium text-gray-700 bg-white hover:bg-gray-50">
402
+ Précédent
403
+ </button>
404
+ <button class="px-3 py-1 border rounded-md text-sm font-medium bg-indigo-600 text-white">
405
+ 1
406
+ </button>
407
+ <button class="px-3 py-1 border rounded-md text-sm font-medium text-gray-700 bg-white hover:bg-gray-50">
408
+ 2
409
+ </button>
410
+ <button class="px-3 py-1 border rounded-md text-sm font-medium text-gray-700 bg-white hover:bg-gray-50">
411
+ Suivant
412
+ </button>
413
+ </div>
414
+ </div>
415
+ </div>
416
+
417
+ <div class="flex justify-end mt-6">
418
+ <button id="finishBtn" class="px-6 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 transition">
419
+ Terminer <i class="fas fa-check ml-2"></i>
420
+ </button>
421
+ </div>
422
+ </div>
423
+ </div>
424
+
425
+ <!-- Help Section -->
426
+ <div class="mt-8 bg-indigo-50 rounded-xl p-6">
427
+ <div class="flex items-start">
428
+ <div class="flex-shrink-0">
429
+ <i class="fas fa-question-circle text-indigo-500 text-2xl"></i>
430
+ </div>
431
+ <div class="ml-4">
432
+ <h3 class="text-lg font-medium text-indigo-800">Besoin d'aide ?</h3>
433
+ <p class="mt-1 text-sm text-indigo-700">
434
+ Consultez notre <a href="#" class="font-medium underline">guide d'utilisation</a> ou contactez notre <a href="#" class="font-medium underline">support technique</a> pour toute question sur le processus de classification.
435
+ </p>
436
+ </div>
437
+ </div>
438
+ </div>
439
+ </div>
440
+
441
+ <script>
442
+ document.addEventListener('DOMContentLoaded', function() {
443
+ // DOM Elements
444
+ const steps = document.querySelectorAll('.step');
445
+ const stepContents = {
446
+ 1: document.getElementById('step-1'),
447
+ 2: document.getElementById('step-2'),
448
+ 3: document.getElementById('step-3'),
449
+ 4: document.getElementById('step-4')
450
+ };
451
+
452
+ const dropzone = document.getElementById('dropzone');
453
+ const fileInput = document.getElementById('fileInput');
454
+ const selectFileBtn = document.getElementById('selectFileBtn');
455
+ const filePreview = document.getElementById('filePreview');
456
+ const fileName = document.getElementById('fileName');
457
+ const fileSize = document.getElementById('fileSize');
458
+ const columnsList = document.getElementById('columnsList');
459
+ const removeFileBtn = document.getElementById('removeFileBtn');
460
+
461
+ const nextStep1 = document.getElementById('nextStep1');
462
+ const prevStep2 = document.getElementById('prevStep2');
463
+ const nextStep2 = document.getElementById('nextStep2');
464
+
465
+ const textColumnSelect = document.getElementById('textColumnSelect');
466
+ const classificationMethod = document.getElementById('classificationMethod');
467
+ const keywordsConfig = document.getElementById('keywordsConfig');
468
+ const aiConfig = document.getElementById('aiConfig');
469
+ const regexConfig = document.getElementById('regexConfig');
470
+ const categoriesContainer = document.getElementById('categoriesContainer');
471
+ const addCategoryBtn = document.getElementById('addCategoryBtn');
472
+
473
+ const progressText = document.getElementById('progressText');
474
+ const progressSubtext = document.getElementById('progressSubtext');
475
+ const progressBar = document.getElementById('progressBar');
476
+ const progressCircle = document.getElementById('progressCircle');
477
+ const progressDetails = document.getElementById('progressDetails');
478
+ const cancelProcessBtn = document.getElementById('cancelProcessBtn');
479
+
480
+ // Variables
481
+ let currentStep = 1;
482
+ let file = null;
483
+
484
+ // Initialize
485
+ updateStepIndicator();
486
+
487
+ // Event Listeners
488
+ selectFileBtn.addEventListener('click', () => fileInput.click());
489
+
490
+ fileInput.addEventListener('change', handleFileSelect);
491
+
492
+ removeFileBtn.addEventListener('click', () => {
493
+ file = null;
494
+ filePreview.classList.add('hidden');
495
+ nextStep1.disabled = true;
496
+ fileInput.value = '';
497
+ });
498
+
499
+ dropzone.addEventListener('dragover', (e) => {
500
+ e.preventDefault();
501
+ dropzone.classList.add('active');
502
+ });
503
+
504
+ dropzone.addEventListener('dragleave', () => {
505
+ dropzone.classList.remove('active');
506
+ });
507
+
508
+ dropzone.addEventListener('drop', (e) => {
509
+ e.preventDefault();
510
+ dropzone.classList.remove('active');
511
+
512
+ if (e.dataTransfer.files.length) {
513
+ fileInput.files = e.dataTransfer.files;
514
+ handleFileSelect({ target: fileInput });
515
+ }
516
+ });
517
+
518
+ nextStep1.addEventListener('click', () => navigateToStep(2));
519
+ prevStep2.addEventListener('click', () => navigateToStep(1));
520
+ nextStep2.addEventListener('click', () => navigateToStep(3));
521
+
522
+ classificationMethod.addEventListener('change', updateClassificationMethodUI);
523
+ addCategoryBtn.addEventListener('click', addNewCategory);
524
+
525
+ // Delegated event listeners for dynamic elements
526
+ categoriesContainer.addEventListener('click', (e) => {
527
+ // Remove category
528
+ if (e.target.closest('.remove-category')) {
529
+ e.target.closest('.category-group').remove();
530
+ checkStep2Completion();
531
+ }
532
+
533
+ // Remove keyword
534
+ if (e.target.closest('.remove-keyword')) {
535
+ e.target.closest('.keyword-chip').remove();
536
+ }
537
+ });
538
+
539
+ categoriesContainer.addEventListener('keydown', (e) => {
540
+ // Add keyword on Enter
541
+ if (e.target.classList.contains('keyword-input') && e.key === 'Enter' && e.target.value.trim()) {
542
+ const keyword = e.target.value.trim();
543
+ const keywordChip = document.createElement('div');
544
+ keywordChip.className = 'keyword-chip flex items-center bg-white px-3 py-1 rounded-full text-sm shadow-sm';
545
+ keywordChip.innerHTML = `
546
+ <span>${keyword}</span>
547
+ <button class="remove-keyword ml-1 text-gray-400 hover:text-red-500">
548
+ <i class="fas fa-times text-xs"></i>
549
+ </button>
550
+ `;
551
+ e.target.before(keywordChip);
552
+ e.target.value = '';
553
+ checkStep2Completion();
554
+ }
555
+
556
+ // Check completion on category name change
557
+ if (e.target.classList.contains('category-name')) {
558
+ setTimeout(checkStep2Completion, 0);
559
+ }
560
+ });
561
+
562
+ // Functions
563
+ function handleFileSelect(event) {
564
+ file = event.target.files[0];
565
+ if (!file) return;
566
+
567
+ fileName.textContent = file.name;
568
+ fileSize.textContent = formatFileSize(file.size);
569
+
570
+ // Simulate reading file columns (in a real app, you'd parse the file)
571
+ const simulatedColumns = ['ID', 'Texte', 'Date', 'Auteur', 'Référence'];
572
+ columnsList.innerHTML = simulatedColumns.map(col => `
573
+ <tr>
574
+ <td class="px-4 py-2 whitespace-nowrap text-sm font-medium text-gray-900">${col}</td>
575
+ </tr>
576
+ `).join('');
577
+
578
+ filePreview.classList.remove('hidden');
579
+ nextStep1.disabled = false;
580
+
581
+ // Populate column select for step 2
582
+ textColumnSelect.innerHTML = '<option value="">Sélectionnez une colonne</option>' +
583
+ simulatedColumns.map(col => `<option value="${col}">${col}</option>`).join('');
584
+ }
585
+
586
+ function formatFileSize(bytes) {
587
+ if (bytes === 0) return '0 Bytes';
588
+ const k = 1024;
589
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
590
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
591
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
592
+ }
593
+
594
+ function navigateToStep(step) {
595
+ // Validation before leaving current step
596
+ if (currentStep === 2 && step === 3 && !validateStep2()) {
597
+ return;
598
+ }
599
+
600
+ // Special handling for step 3 (processing)
601
+ if (step === 3) {
602
+ startProcessing();
603
+ }
604
+
605
+ // Hide current step
606
+ stepContents[currentStep].classList.add('hidden');
607
+
608
+ // Show new step
609
+ stepContents[step].classList.remove('hidden');
610
+ stepContents[step].classList.add('fade-in');
611
+
612
+ // Update current step
613
+ currentStep = step;
614
+ updateStepIndicator();
615
+ }
616
+
617
+ function updateStepIndicator() {
618
+ steps.forEach(step => {
619
+ const stepNum = parseInt(step.dataset.step);
620
+ const circle = step.querySelector('div');
621
+ const text = step.querySelector('p');
622
+ const line = step.querySelector('.absolute');
623
+
624
+ if (stepNum < currentStep) {
625
+ // Completed step
626
+ circle.classList.remove('bg-gray-200', 'text-gray-600');
627
+ circle.classList.add('bg-indigo-600', 'text-white');
628
+ text.classList.remove('text-gray-500');
629
+ text.classList.add('text-indigo-600');
630
+ line.classList.remove('bg-gray-200');
631
+ line.classList.add('bg-indigo-600');
632
+ } else if (stepNum === currentStep) {
633
+ // Current step
634
+ circle.classList.remove('bg-gray-200', 'text-gray-600');
635
+ circle.classList.add('bg-indigo-600', 'text-white');
636
+ text.classList.remove('text-gray-500');
637
+ text.classList.add('text-indigo-600');
638
+ line.classList.remove('bg-indigo-600');
639
+ line.classList.add('bg-gray-200');
640
+ } else {
641
+ // Future step
642
+ circle.classList.remove('bg-indigo-600', 'text-white');
643
+ circle.classList.add('bg-gray-200', 'text-gray-600');
644
+ text.classList.remove('text-indigo-600');
645
+ text.classList.add('text-gray-500');
646
+ line.classList.remove('bg-indigo-600');
647
+ line.classList.add('bg-gray-200');
648
+ }
649
+ });
650
+ }
651
+
652
+ function updateClassificationMethodUI() {
653
+ const method = classificationMethod.value;
654
+
655
+ keywordsConfig.classList.add('hidden');
656
+ aiConfig.classList.add('hidden');
657
+ regexConfig.classList.add('hidden');
658
+
659
+ if (method === 'keywords') {
660
+ keywordsConfig.classList.remove('hidden');
661
+ } else if (method === 'ai') {
662
+ aiConfig.classList.remove('hidden');
663
+ } else if (method === 'regex') {
664
+ regexConfig.classList.remove('hidden');
665
+ }
666
+
667
+ checkStep2Completion();
668
+ }
669
+
670
+ function addNewCategory() {
671
+ const categoryGroup = document.createElement('div');
672
+ categoryGroup.className = 'category-group border rounded-lg p-4 bg-gray-50';
673
+ categoryGroup.innerHTML = `
674
+ <div class="flex justify-between items-center mb-3">
675
+ <input type="text" placeholder="Nom de la catégorie" class="category-name flex-1 border-b border-gray-300 focus:border-indigo-500 focus:outline-none bg-transparent py-1">
676
+ <button class="remove-category text-red-500 hover:text-red-700 ml-2">
677
+ <i class="fas fa-trash"></i>
678
+ </button>
679
+ </div>
680
+ <div class="flex flex-wrap gap-2">
681
+ <input type="text" placeholder="Ajouter un mot-clé" class="keyword-input flex-1 min-w-[100px] border-b border-gray-300 focus:border-indigo-500 focus:outline-none bg-transparent py-1">
682
+ </div>
683
+ `;
684
+ categoriesContainer.appendChild(categoryGroup);
685
+
686
+ // Focus on the new category name input
687
+ categoryGroup.querySelector('.category-name').focus();
688
+ }
689
+
690
+ function checkStep2Completion() {
691
+ let isComplete = true;
692
+
693
+ // Check if text column is selected
694
+ if (!textColumnSelect.value) {
695
+ isComplete = false;
696
+ }
697
+
698
+ // Check if categories are properly defined (for keyword method)
699
+ if (classificationMethod.value === 'keywords') {
700
+ const categoryGroups = categoriesContainer.querySelectorAll('.category-group');
701
+ if (categoryGroups.length === 0) {
702
+ isComplete = false;
703
+ } else {
704
+ categoryGroups.forEach(group => {
705
+ const name = group.querySelector('.category-name').value.trim();
706
+ const keywords = group.querySelectorAll('.keyword-chip');
707
+
708
+ if (!name || keywords.length === 0) {
709
+ isComplete = false;
710
+ }
711
+ });
712
+ }
713
+ }
714
+
715
+ nextStep2.disabled = !isComplete;
716
+ }
717
+
718
+ function validateStep2() {
719
+ // In a real app, this would do more thorough validation
720
+ return !nextStep2.disabled;
721
+ }
722
+
723
+ function startProcessing() {
724
+ progressText.textContent = "Classification en cours...";
725
+ progressSubtext.textContent = "Analyse des données textuelles";
726
+ progressDetails.classList.add('hidden');
727
+
728
+ let progress = 0;
729
+ const interval = setInterval(() => {
730
+ progress += Math.random() * 5;
731
+ if (progress > 100) progress = 100;
732
+
733
+ progressBar.style.width = `${progress}%`;
734
+ progressCircle.style.strokeDashoffset = 283 * (1 - progress/100);
735
+
736
+ // Update progress details
737
+ if (progress > 30 && progress < 70) {
738
+ progressText.textContent = "Identification des catégories...";
739
+ progressSubtext.textContent = "Analyse des motifs récurrents";
740
+ } else if (progress >= 70) {
741
+ progressText.textContent = "Finalisation des résultats...";
742
+ progressSubtext.textContent = "Préparation des données pour l'affichage";
743
+ progressDetails.classList.remove('hidden');
744
+
745
+ document.getElementById('processedRows').textContent =
746
+ `${Math.floor(progress * 12.45)}/1245`;
747
+ document.getElementById('identifiedCategories').textContent =
748
+ `${Math.floor(progress / 15)}`;
749
+ document.getElementById('averageConfidence').textContent =
750
+ `${Math.min(95, Math.floor(70 + progress / 3))}%`;
751
+ }
752
+
753
+ if (progress === 100) {
754
+ clearInterval(interval);
755
+ setTimeout(() => {
756
+ navigateToStep(4);
757
+ }, 1000);
758
+ }
759
+ }, 300);
760
+
761
+ cancelProcessBtn.addEventListener('click', () => {
762
+ clearInterval(interval);
763
+ navigateToStep(2);
764
+ }, { once: true });
765
+ }
766
+
767
+ // Initialize step 2 validation
768
+ textColumnSelect.addEventListener('change', checkStep2Completion);
769
+ });
770
+ </script>
771
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=simondh/classifications" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
772
+ </html>