reneco-advanced-input-module 0.0.1 → 0.0.3

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.
Files changed (94) hide show
  1. package/dist/cjs/loader.cjs.js +1 -1
  2. package/dist/cjs/ocr-file-uploader.voice-input-module.entry.cjs.js.map +1 -0
  3. package/dist/cjs/ocr-file-uploader_2.cjs.entry.js +4486 -0
  4. package/dist/cjs/ocr-file-uploader_2.cjs.entry.js.map +1 -0
  5. package/dist/cjs/voice-input-module.cjs.js +1 -1
  6. package/dist/collection/collection-manifest.json +8 -2
  7. package/dist/collection/components/voice-input-module/voice-input-module.css +76 -0
  8. package/dist/collection/components/voice-input-module/voice-input-module.js +218 -72
  9. package/dist/collection/components/voice-input-module/voice-input-module.js.map +1 -1
  10. package/dist/collection/services/llm.service.js +2 -2
  11. package/dist/collection/services/llm.service.js.map +1 -1
  12. package/dist/collection/services/speech-to-text.service.js +2 -4
  13. package/dist/collection/services/speech-to-text.service.js.map +1 -1
  14. package/dist/collection/utils/schema-converter.js +1 -1
  15. package/dist/collection/utils/schema-converter.js.map +1 -1
  16. package/dist/components/ocr-file-uploader.js +9 -0
  17. package/dist/components/ocr-file-uploader.js.map +1 -0
  18. package/dist/components/{file-uploader2.js → ocr-file-uploader2.js} +16 -12
  19. package/dist/components/ocr-file-uploader2.js.map +1 -0
  20. package/dist/components/voice-input-module.js +3257 -93
  21. package/dist/components/voice-input-module.js.map +1 -1
  22. package/dist/esm/loader.js +1 -1
  23. package/dist/esm/ocr-file-uploader.voice-input-module.entry.js.map +1 -0
  24. package/dist/esm/ocr-file-uploader_2.entry.js +4483 -0
  25. package/dist/esm/ocr-file-uploader_2.entry.js.map +1 -0
  26. package/dist/esm/voice-input-module.js +1 -1
  27. package/dist/types/components/voice-input-module/voice-input-module.d.ts +9 -1
  28. package/dist/types/components.d.ts +8 -31
  29. package/dist/types/services/speech-to-text.service.d.ts +1 -1
  30. package/dist/voice-input-module/ocr-file-uploader.voice-input-module.entry.esm.js.map +1 -0
  31. package/dist/voice-input-module/p-37de1da2.entry.js +3 -0
  32. package/dist/voice-input-module/p-37de1da2.entry.js.map +1 -0
  33. package/dist/voice-input-module/voice-input-module.esm.js +1 -1
  34. package/loader/cdn.js +1 -0
  35. package/loader/index.cjs.js +1 -0
  36. package/loader/index.d.ts +24 -0
  37. package/loader/index.es2017.js +1 -0
  38. package/loader/index.js +2 -0
  39. package/package.json +7 -3
  40. package/www/build/index.esm.js +2 -0
  41. package/www/build/index.esm.js.map +1 -0
  42. package/www/build/loader.esm.js.map +1 -0
  43. package/www/build/ocr-file-uploader.voice-input-module.entry.esm.js.map +1 -0
  44. package/www/build/p-37de1da2.entry.js +3 -0
  45. package/www/build/p-37de1da2.entry.js.map +1 -0
  46. package/www/build/p-6438474d.js +2 -0
  47. package/www/build/p-DQuL1Twl.js +2 -0
  48. package/www/build/p-DQuL1Twl.js.map +1 -0
  49. package/www/build/p-jmc2yzBp.js +3 -0
  50. package/www/build/p-jmc2yzBp.js.map +1 -0
  51. package/www/build/voice-input-module.esm.js +2 -0
  52. package/www/build/voice-input-module.esm.js.map +1 -0
  53. package/www/build/voice-input-module.js +33 -0
  54. package/www/host.config.json +15 -0
  55. package/www/index.html +1662 -0
  56. package/.editorconfig +0 -15
  57. package/.prettierrc.json +0 -13
  58. package/api-key-inject.js +0 -46
  59. package/dist/cjs/file-uploader.voice-input-module.entry.cjs.js.map +0 -1
  60. package/dist/cjs/file-uploader_2.cjs.entry.js +0 -1319
  61. package/dist/cjs/file-uploader_2.cjs.entry.js.map +0 -1
  62. package/dist/collection/components/file-uploader/file-uploader.css +0 -26
  63. package/dist/collection/components/file-uploader/file-uploader.js +0 -130
  64. package/dist/collection/components/file-uploader/file-uploader.js.map +0 -1
  65. package/dist/components/file-uploader.d.ts +0 -11
  66. package/dist/components/file-uploader.js +0 -9
  67. package/dist/components/file-uploader.js.map +0 -1
  68. package/dist/components/file-uploader2.js.map +0 -1
  69. package/dist/esm/file-uploader.voice-input-module.entry.js.map +0 -1
  70. package/dist/esm/file-uploader_2.entry.js +0 -1316
  71. package/dist/esm/file-uploader_2.entry.js.map +0 -1
  72. package/dist/types/components/file-uploader/file-uploader.d.ts +0 -8
  73. package/dist/voice-input-module/file-uploader.voice-input-module.entry.esm.js.map +0 -1
  74. package/dist/voice-input-module/p-7b4f33ba.entry.js +0 -2
  75. package/dist/voice-input-module/p-7b4f33ba.entry.js.map +0 -1
  76. package/env-config.js +0 -4
  77. package/inject-env.js +0 -20
  78. package/src/components/file-uploader/file-uploader.css +0 -26
  79. package/src/components/file-uploader/file-uploader.tsx +0 -100
  80. package/src/components/file-uploader/readme.md +0 -31
  81. package/src/components/voice-input-module/readme.md +0 -114
  82. package/src/components/voice-input-module/voice-input-module.css +0 -251
  83. package/src/components/voice-input-module/voice-input-module.tsx +0 -731
  84. package/src/components.d.ts +0 -158
  85. package/src/index.html +0 -663
  86. package/src/index.ts +0 -12
  87. package/src/services/audio-recorder.service.ts +0 -74
  88. package/src/services/llm.service.ts +0 -221
  89. package/src/services/speech-to-text.service.ts +0 -72
  90. package/src/types/form-schema.types.ts +0 -78
  91. package/src/types/service-providers.types.ts +0 -22
  92. package/src/utils/schema-converter.ts +0 -494
  93. package/stencil.config.ts +0 -24
  94. package/tsconfig.json +0 -30
@@ -19,7 +19,7 @@ var patchBrowser = () => {
19
19
 
20
20
  patchBrowser().then(async (options) => {
21
21
  await appGlobals.globalScripts();
22
- return index.bootstrapLazy([["file-uploader_2.cjs",[[257,"voice-input-module",{"formJson":[1,"form-json"],"serviceConfig":[1,"service-config"],"apiKey":[1,"api-key"],"context":[1],"classificationRootUrl":[1,"classification-root-url"],"language":[1],"voiceOrOcr":[1,"voice-or-ocr"],"debug":[4],"renderForm":[4,"render-form"],"displayStatus":[4,"display-status"],"isRecording":[32],"isProcessing":[32],"statusMessage":[32],"hasError":[32],"transcription":[32],"filledData":[32],"debugInfo":[32],"isReadonlyMode":[32],"convertXmlToJson":[64],"convertJsonToXml":[64],"convertXmlToJsonLegacy":[64],"convertJsonToXmlLegacy":[64]},null,{"formJson":["initializeServices"],"serviceConfig":["initializeServices"]}],[257,"file-uploader",{"batch":[4],"callback":[16]}]]]], options);
22
+ return index.bootstrapLazy([["ocr-file-uploader_2.cjs",[[257,"voice-input-module",{"formJson":[1,"form-json"],"serviceConfig":[1,"service-config"],"apiKey":[1,"api-key"],"context":[1],"classificationRootUrl":[1,"classification-root-url"],"language":[1],"inputTypes":[1,"input-types"],"debug":[4],"renderForm":[4,"render-form"],"displayStatus":[4,"display-status"],"isRecording":[32],"isProcessing":[32],"statusMessage":[32],"hasError":[32],"transcription":[32],"filledData":[32],"debugInfo":[32],"isReadonlyMode":[32],"convertXmlToJson":[64],"convertJsonToXml":[64],"convertXmlToJsonLegacy":[64],"convertJsonToXmlLegacy":[64]},null,{"formJson":["initializeServices"],"serviceConfig":["initializeServices"]}],[257,"ocr-file-uploader",{"batch":[4],"callback":[16],"jsonSchema":[1,"json-schema"]}]]]], options);
23
23
  });
24
24
 
25
25
  exports.setNonce = index.setNonce;
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "entries": [
3
- "components/file-uploader/file-uploader.js",
4
3
  "components/voice-input-module/voice-input-module.js"
5
4
  ],
6
5
  "compiler": {
@@ -8,6 +7,13 @@
8
7
  "version": "4.36.2",
9
8
  "typescriptVersion": "5.5.4"
10
9
  },
11
- "collections": [],
10
+ "collections": [
11
+ {
12
+ "name": "ocr-file-uploader",
13
+ "tags": [
14
+ "ocr-file-uploader"
15
+ ]
16
+ }
17
+ ],
12
18
  "bundles": []
13
19
  }
@@ -3,6 +3,11 @@
3
3
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
4
4
  }
5
5
 
6
+ .row-audio-area {
7
+ display: flex;
8
+ flex-direction: row;
9
+ }
10
+
6
11
  .voice-recorder-container {
7
12
  display: flex;
8
13
  flex-direction: column;
@@ -29,6 +34,36 @@
29
34
  margin: 0 auto;
30
35
  }
31
36
 
37
+ .upload-record-container {
38
+ display: inline-block;
39
+ cursor: pointer;
40
+ width: 50px;
41
+ height: 50px;
42
+ }
43
+
44
+ .upload-record-button {
45
+ display: flex;
46
+ align-items: center;
47
+ justify-content: center;
48
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
49
+ user-select: none;
50
+ }
51
+
52
+ .upload-record-button svg {
53
+ width: 50px;
54
+ height: 50px;
55
+ stroke: #4444ee;
56
+ }
57
+
58
+ .upload-record-button svg path {
59
+ fill: #4444ee;
60
+ }
61
+
62
+ .upload-record-button:hover svg {
63
+ transform: scale(1.05);
64
+ stroke: #4444ee;
65
+ }
66
+
32
67
  .record-button {
33
68
  display: flex;
34
69
  align-items: center;
@@ -248,4 +283,45 @@ input[type="date"].form-input {
248
283
  border-radius: 0.25rem;
249
284
  font-size: 0.875rem;
250
285
  color: #374151;
286
+ }
287
+
288
+ .multiselect-container {
289
+ display: flex;
290
+ flex-direction: column;
291
+ gap: 0.5rem;
292
+ padding: 0.5rem;
293
+ border: 1px solid #d1d5db;
294
+ border-radius: 0.375rem;
295
+ background: white;
296
+ }
297
+
298
+ .multiselect-option {
299
+ display: flex;
300
+ align-items: center;
301
+ gap: 0.5rem;
302
+ padding: 0.5rem;
303
+ border-radius: 0.25rem;
304
+ cursor: pointer;
305
+ transition: background 0.2s ease;
306
+ }
307
+
308
+ .multiselect-option:hover {
309
+ background: #f3f4f6;
310
+ }
311
+
312
+ .multiselect-option input[type="checkbox"] {
313
+ width: 18px;
314
+ height: 18px;
315
+ cursor: pointer;
316
+ }
317
+
318
+ .multiselect-option input[type="checkbox"]:checked + .multiselect-label {
319
+ font-weight: 600;
320
+ color: #059669;
321
+ }
322
+
323
+ .multiselect-label {
324
+ font-size: 0.875rem;
325
+ color: #374151;
326
+ user-select: none;
251
327
  }
@@ -3,14 +3,27 @@ import { AudioRecorderService } from "../../services/audio-recorder.service";
3
3
  import { SpeechToTextServiceFactory } from "../../services/speech-to-text.service";
4
4
  import { LLMServiceFactory } from "../../services/llm.service";
5
5
  import { SchemaConverter } from "../../utils/schema-converter";
6
+ import { defineCustomElements } from "ocr-file-uploader/loader";
7
+ // Initialize OCR
8
+ defineCustomElements();
6
9
  export class VoiceFormRecorder {
10
+ get parsedInputTypes() {
11
+ if (!this.inputTypes)
12
+ return [];
13
+ try {
14
+ return JSON.parse(this.inputTypes.replace(/'/g, '"'));
15
+ }
16
+ catch (_a) {
17
+ return this.inputTypes.split(',').map(type => type.trim());
18
+ }
19
+ }
7
20
  constructor() {
8
21
  this.formJson = '{}';
9
22
  this.serviceConfig = '{}';
10
23
  this.context = undefined;
11
24
  this.classificationRootUrl = 'http://localhost';
12
25
  this.language = 'en';
13
- this.voiceOrOcr = undefined;
26
+ this.inputTypes = '';
14
27
  this.debug = false;
15
28
  this.renderForm = false;
16
29
  this.displayStatus = false;
@@ -21,6 +34,18 @@ export class VoiceFormRecorder {
21
34
  this.filledData = null;
22
35
  this.debugInfo = {};
23
36
  this.isReadonlyMode = true; // Start in readonly preview mode
37
+ this.triggerAudioRecordUpload = () => {
38
+ this.fileInputAudioRecord.click();
39
+ };
40
+ this.handleAudioRecordChange = async (event) => {
41
+ const input = event.target;
42
+ if (!input.files || input.files.length === 0)
43
+ return;
44
+ const file = input.files[0];
45
+ // Here you can handle the file upload to your API
46
+ console.log('Selected file:', file);
47
+ this.processAudioContent(file);
48
+ };
24
49
  this.audioRecorder = new AudioRecorderService();
25
50
  }
26
51
  componentWillLoad() {
@@ -51,7 +76,10 @@ export class VoiceFormRecorder {
51
76
  config: this.parsedConfig
52
77
  });
53
78
  this.hasError = false;
54
- this.statusMessage = (this.language == 'en' ? 'Click to start recording' : 'Cliquer pour enregistrer');
79
+ this.statusMessage = (this.language == 'en' ? 'Select an input method' : 'Sélectionner une méthode de saisie');
80
+ if (this.parsedInputTypes.length === 0) {
81
+ this.inputTypes = 'voice';
82
+ }
55
83
  }
56
84
  }
57
85
  catch (error) {
@@ -102,14 +130,17 @@ export class VoiceFormRecorder {
102
130
  });
103
131
  }
104
132
  }
105
- async processJsonForm(jsonForm) {
106
- // console.log("processJsonForm", jsonForm);
133
+ async processJsonForm(ocrData) {
134
+ console.log("processJsonForm", ocrData);
107
135
  try {
108
136
  this.isProcessing = true;
109
137
  this.statusMessage = (this.language == 'en' ? 'Processing json...' : `Traitement du json ...`);
138
+ // Extract content from OCR format
139
+ const extractedData = (ocrData === null || ocrData === void 0 ? void 0 : ocrData.content) || ocrData;
140
+ const jsonForm = JSON.stringify(extractedData);
110
141
  // Fill form using LLM
111
142
  this.statusMessage = (this.language == 'en' ? 'Filling form fields...' : 'Remplissage du formulaire ...');
112
- const trimmedSchema = this.trimSchemaForAI(this.parsedSchema);
143
+ const trimmedSchema = await this.trimSchemaForAI(this.parsedSchema);
113
144
  const filledSchema = await this.llmService.fillFormFromJson(jsonForm, trimmedSchema);
114
145
  // Extract filled data
115
146
  this.filledData = this.extractFilledData(filledSchema);
@@ -133,13 +164,46 @@ export class VoiceFormRecorder {
133
164
  this.formFilled.emit({
134
165
  success: false,
135
166
  error: error.message,
136
- jsonForm: jsonForm
167
+ jsonForm: JSON.stringify(ocrData)
137
168
  });
138
169
  }
139
170
  finally {
140
171
  this.isProcessing = false;
141
172
  }
142
173
  }
174
+ async processAudioContent(audioFile) {
175
+ this.updateDebugInfo('Audio Captured', {
176
+ size: audioFile.size,
177
+ type: audioFile.type
178
+ });
179
+ // Transcribe audio
180
+ this.statusMessage = (this.language == 'en' ? 'Transcribing speech...' : 'Transcription du texte ...');
181
+ const transcription = await this.speechToTextService.transcribe(audioFile, this.language);
182
+ this.transcription = transcription;
183
+ this.updateDebugInfo('Transcription Complete', { transcription });
184
+ if (!transcription.trim()) {
185
+ throw new Error('No speech detected in the recording');
186
+ }
187
+ // Fill form using LLM
188
+ this.statusMessage = (this.language == 'en' ? 'Filling form fields...' : 'Remplissage du formulaire ...');
189
+ const trimmedSchema = await this.trimSchemaForAI(this.parsedSchema);
190
+ const filledSchema = await this.llmService.fillFormFromTranscription(transcription, trimmedSchema);
191
+ // Extract filled data
192
+ this.filledData = this.extractFilledData(filledSchema);
193
+ this.updateDebugInfo('Form Filled', {
194
+ filledSchema,
195
+ extractedData: this.filledData
196
+ });
197
+ this.parsedSchema = this.filledData;
198
+ this.statusMessage = (this.language == 'en' ? 'Form completed!' : 'Formulaire remplis !');
199
+ this.hasError = false;
200
+ // Emit success event
201
+ this.formFilled.emit({
202
+ success: true,
203
+ data: this.filledData,
204
+ transcription: transcription
205
+ });
206
+ }
143
207
  async stopRecordingAndProcess() {
144
208
  try {
145
209
  this.isRecording = false;
@@ -152,37 +216,8 @@ export class VoiceFormRecorder {
152
216
  });
153
217
  // Stop recording and get audio blob
154
218
  const audioBlob = await this.audioRecorder.stopRecording();
155
- this.updateDebugInfo('Audio Captured', {
156
- size: audioBlob.size,
157
- type: audioBlob.type
158
- });
159
- // Transcribe audio
160
- this.statusMessage = (this.language == 'en' ? 'Transcribing speech...' : 'Transcription du texte ...');
161
- const transcription = await this.speechToTextService.transcribe(audioBlob, this.language);
162
- this.transcription = transcription;
163
- this.updateDebugInfo('Transcription Complete', { transcription });
164
- if (!transcription.trim()) {
165
- throw new Error('No speech detected in the recording');
166
- }
167
- // Fill form using LLM
168
- this.statusMessage = (this.language == 'en' ? 'Filling form fields...' : 'Remplissage du formulaire ...');
169
- const trimmedSchema = this.trimSchemaForAI(this.parsedSchema);
170
- const filledSchema = await this.llmService.fillFormFromTranscription(transcription, trimmedSchema);
171
- // Extract filled data
172
- this.filledData = this.extractFilledData(filledSchema);
173
- this.updateDebugInfo('Form Filled', {
174
- filledSchema,
175
- extractedData: this.filledData
176
- });
177
- this.parsedSchema = this.filledData;
178
- this.statusMessage = (this.language == 'en' ? 'Form completed!' : 'Formulaire remplis !');
179
- this.hasError = false;
180
- // Emit success event
181
- this.formFilled.emit({
182
- success: true,
183
- data: this.filledData,
184
- transcription: transcription
185
- });
219
+ const audioContent = new File([audioBlob], 'audio.webm', { type: 'audio/webm' });
220
+ this.processAudioContent(audioContent);
186
221
  }
187
222
  catch (error) {
188
223
  this.hasError = true;
@@ -206,11 +241,13 @@ export class VoiceFormRecorder {
206
241
  // console.log("extractFilledData", filledData);
207
242
  const updatedSchema = JSON.parse(JSON.stringify(this.parsedSchema));
208
243
  switch (this.context) {
244
+ case "ecoteka":
245
+ // console.log("TODO extractFilledData", filledData);
209
246
  case "ng":
210
247
  if (filledData === null || filledData === void 0 ? void 0 : filledData.fields) {
211
248
  // Map AI response back to original schema structure
212
249
  filledData.fields.forEach((field) => {
213
- const originalField = updatedSchema.Children.find((child) => child.System_Name === field.name);
250
+ const originalField = updatedSchema.Children.find((child) => { var _a; return child.System_Name === field.name || ((_a = child.Settings) === null || _a === void 0 ? void 0 : _a.Label) === field.name; });
214
251
  if (originalField && field.value !== undefined && field.value !== null && field.value !== '') {
215
252
  if (!originalField.Settings)
216
253
  originalField.Settings = {};
@@ -233,9 +270,6 @@ export class VoiceFormRecorder {
233
270
  });
234
271
  }
235
272
  break;
236
- case "ecoteka":
237
- // console.log("TODO extractFilledData", filledData);
238
- break;
239
273
  case "track":
240
274
  default:
241
275
  const data = {};
@@ -259,28 +293,33 @@ export class VoiceFormRecorder {
259
293
  // console.log("extractFilledData result", updatedSchema);
260
294
  return updatedSchema;
261
295
  }
262
- trimSchemaForAI(schema) {
296
+ async trimSchemaForAI(schema) {
263
297
  var _a, _b;
264
298
  // console.log("trimSchemaForAI", schema);
265
299
  switch (this.context) {
266
- case 'ng':
300
+ case "ecoteka":
301
+ // console.log("TODO trimSchemaForAI", schema)
302
+ case "ng":
267
303
  const trimmed = { fields: [] };
268
304
  schema.Children.forEach((child) => {
305
+ var _a;
269
306
  if (!child.System_Name || !child.Type)
270
307
  return;
271
308
  const fieldData = {
272
- name: child.System_Name,
309
+ name: child.Label || ((_a = child.Settings) === null || _a === void 0 ? void 0 : _a.Label) || child.System_Name,
273
310
  type: this.mapFieldType(child.Type)
274
311
  };
275
312
  // Add options for classification/select fields
276
- if (child.Type === 'InputClassification' && child.Children && child.Children.length > 0) {
313
+ const selectTypes = ['InputClassification', 'select'];
314
+ if (selectTypes.includes(child.Type) && child.Children && child.Children.length > 0) {
277
315
  fieldData.options = child.Children.map((option) => option.System_Name || option.Label || option.toString());
278
316
  }
317
+ console.log("fieldData", fieldData);
279
318
  trimmed.fields.push(fieldData);
280
319
  });
281
320
  // console.log("Schema apres transformation, contexte NG:", trimmed);
282
321
  return trimmed;
283
- case 'ecoll-veto':
322
+ case "ecoll-veto":
284
323
  // console.log("TODO trimSchemaForAI", schema)
285
324
  const mergedItemsSchema = (this.parsedSchema[0].items).concat(this.parsedSchema[1].items);
286
325
  if (mergedItemsSchema) {
@@ -289,12 +328,37 @@ export class VoiceFormRecorder {
289
328
  description: 'Form Description',
290
329
  schema: {}
291
330
  };
292
- Object.entries(mergedItemsSchema).forEach(([key, field]) => {
331
+ Object.entries(mergedItemsSchema).forEach(async ([key, field]) => {
293
332
  const fieldName = field.name;
294
333
  const fieldType = this.mapFieldType(field.type);
295
334
  const fieldLabel = field.label || fieldName;
296
335
  const isRequired = field.required || false;
297
336
  const fieldValue = ''; //TODO
337
+ if (['position', 'thesaurus'].includes(fieldType)) {
338
+ try {
339
+ const response = await fetch(`${this.classificationRootUrl}/ng/api/v1/classification/getList/${fieldType.toLowerCase() == 'position' ? "Position" : "Thesaurus"}/?StartNodeID=${field.config.options.options.startNode}`);
340
+ if (!response.ok)
341
+ throw new Error(`HTTP error! status: ${response.status}`);
342
+ const data = await response.json();
343
+ if (Array.isArray(data)) {
344
+ const options = data.map(item => ({
345
+ value: item.ID,
346
+ label: item.System_Name
347
+ }));
348
+ if (options.length > 0) {
349
+ field.pickerOptions = options;
350
+ // TODO on degage les quotes simples temporairement, a corriger
351
+ field.options = options.map(option => option.label.replace("'", ""));
352
+ }
353
+ }
354
+ else {
355
+ console.error("Unexpected API response format:", data);
356
+ }
357
+ }
358
+ catch (error) {
359
+ console.error("Error fetching classification data:", error);
360
+ }
361
+ }
298
362
  trimmedSchema.schema[fieldName] = {
299
363
  type: fieldType,
300
364
  title: fieldLabel,
@@ -306,10 +370,7 @@ export class VoiceFormRecorder {
306
370
  // console.log("Schema apres transformation, contexte Track:", trimmedSchema);
307
371
  return trimmedSchema;
308
372
  }
309
- case "ecoteka":
310
- // console.log("TODO trimSchemaForAI", schema)
311
- break;
312
- case 'track':
373
+ case "track":
313
374
  default:
314
375
  // Handle simple schema format (backward compatibility)
315
376
  if ((_a = schema === null || schema === void 0 ? void 0 : schema.schema) !== null && _a !== void 0 ? _a : schema === null || schema === void 0 ? void 0 : schema.fields) {
@@ -345,16 +406,20 @@ export class VoiceFormRecorder {
345
406
  'InputTextArea': 'string',
346
407
  'InputDateTimePicker': 'datetime',
347
408
  'InputDecimal': 'number',
348
- 'InputClassification': 'select',
409
+ 'InputClassification': 'classification',
349
410
  'InputCheckbox': 'boolean',
350
411
  'InputTextTranslation': 'string',
351
- 'thesaurus': 'string',
352
- 'position': 'string',
412
+ 'InputMultiSelect': 'multiselect',
413
+ 'thesaurus': 'thesaurus',
414
+ 'position': 'position',
353
415
  'text': 'string',
354
416
  'textarea': 'string',
355
417
  'number': 'number',
356
418
  'date': 'date',
357
- 'datetime': 'datetime'
419
+ 'datetime': 'datetime',
420
+ 'select': 'select',
421
+ 'multiselect': 'multiselect',
422
+ 'checkbox': 'checkbox'
358
423
  };
359
424
  return typeMapping[type] || 'string';
360
425
  }
@@ -373,12 +438,63 @@ export class VoiceFormRecorder {
373
438
  return SchemaConverter.convertJsonToXmlLegacy(jsonForm);
374
439
  }
375
440
  renderUploadButton() {
376
- if (!['ocr', 'both'].includes(this.voiceOrOcr))
441
+ if (!this.parsedInputTypes.includes('ocr'))
442
+ return;
443
+ return (h("ocr-file-uploader", { batch: false, "json-schema": this.convertSchemaToOcrFormat(this.parsedSchema), callback: (data) => { this.processJsonForm(data); } }));
444
+ }
445
+ convertSchemaToOcrFormat(schema) {
446
+ const ocrSchema = {
447
+ type: "object",
448
+ additionalProperties: false,
449
+ properties: {
450
+ meta: {
451
+ type: "object",
452
+ additionalProperties: false,
453
+ properties: {
454
+ page: { type: "integer" },
455
+ confiance_global: { type: "number" }
456
+ },
457
+ required: ["page", "confiance_global"]
458
+ },
459
+ content: {
460
+ type: "object",
461
+ additionalProperties: false,
462
+ properties: {},
463
+ required: []
464
+ }
465
+ },
466
+ required: ["meta", "content"]
467
+ };
468
+ if (schema === null || schema === void 0 ? void 0 : schema.Children) {
469
+ schema.Children.forEach((child) => {
470
+ var _a;
471
+ if (child.System_Name && child.Type) {
472
+ const fieldLabel = ((_a = child.Settings) === null || _a === void 0 ? void 0 : _a.Label) || child.System_Name;
473
+ const fieldType = this.mapOcrFieldType(child.Type);
474
+ ocrSchema.properties.content.properties[fieldLabel] = {
475
+ anyOf: [{ type: fieldType }, { type: "null" }]
476
+ };
477
+ }
478
+ });
479
+ }
480
+ return JSON.stringify(ocrSchema);
481
+ }
482
+ mapOcrFieldType(type) {
483
+ const typeMapping = {
484
+ 'InputInteger': 'number',
485
+ 'InputDecimal': 'number',
486
+ 'InputDateTimePicker': 'string',
487
+ 'InputCheckbox': 'boolean'
488
+ };
489
+ return typeMapping[type] || 'string';
490
+ }
491
+ renderUploadRecordButton() {
492
+ if (!this.parsedInputTypes.includes('audio'))
377
493
  return;
378
- return (h("file-uploader", { batch: false, callback: (data) => { this.processJsonForm(data); } }));
494
+ return (h("div", { class: "upload-record-container", onClick: this.triggerAudioRecordUpload }, h("input", { type: "file", ref: el => (this.fileInputAudioRecord = el), onChange: this.handleAudioRecordChange, style: { display: 'none' } }), h("div", { class: 'upload-record-button' }, h("svg", { width: "800px", height: "800px", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, h("path", { "fill-rule": "evenodd", "clip-rule": "evenodd", d: "M12 2.75C6.89137 2.75 2.75 6.89137 2.75 12C2.75 17.1086 6.89137 21.25 12 21.25C12.6345 21.25 13.2534 21.1862 13.8508 21.065C14.2567 20.9826 14.6526 21.2448 14.735 21.6508C14.8174 22.0567 14.5551 22.4526 14.1492 22.535C13.4541 22.6761 12.7353 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 12.7353 22.6761 13.4541 22.535 14.1492C22.4526 14.5551 22.0567 14.8174 21.6508 14.735C21.2448 14.6526 20.9826 14.2567 21.065 13.8508C21.1862 13.2534 21.25 12.6345 21.25 12C21.25 6.89137 17.1086 2.75 12 2.75ZM12.7676 8.52584C12.7661 8.53409 12.7604 8.56729 12.7564 8.64336C12.7502 8.76101 12.75 8.91982 12.75 9.17082C12.75 9.27795 12.7501 9.33904 12.7518 9.38529C12.7528 9.41425 12.7542 9.42649 12.7546 9.42955C12.7662 9.48945 12.7993 9.54303 12.8477 9.58021C12.8502 9.58194 12.8606 9.58864 12.886 9.60252C12.9266 9.62468 12.9812 9.65209 13.0771 9.7L14.3938 10.3584C14.6183 10.4706 14.7604 10.5414 14.8684 10.5885C14.9382 10.6189 14.9705 10.6287 14.9785 10.631C15.0885 10.6405 15.1917 10.5767 15.2324 10.4742C15.2339 10.4659 15.2396 10.4327 15.2436 10.3566C15.2498 10.239 15.25 10.0802 15.25 9.82918C15.25 9.72205 15.2499 9.66096 15.2482 9.61471C15.2472 9.58575 15.2458 9.57351 15.2454 9.57045C15.2338 9.51055 15.2007 9.45697 15.1523 9.41979C15.1498 9.41805 15.1394 9.41136 15.114 9.39748C15.0734 9.37533 15.0188 9.34791 14.9229 9.3L13.6062 8.64164C13.3817 8.52939 13.2396 8.45859 13.1316 8.41151C13.0617 8.38107 13.0295 8.37131 13.0215 8.36896C12.9115 8.35945 12.8083 8.42327 12.7676 8.52584ZM12.75 11.2135L13.7396 11.7083C13.9425 11.8098 14.1204 11.8987 14.269 11.9635C14.4199 12.0293 14.5988 12.097 14.7972 12.1202C15.6037 12.2142 16.3689 11.7413 16.6454 10.978C16.7134 10.7901 16.7328 10.5998 16.7415 10.4355C16.75 10.2735 16.75 10.0747 16.75 9.8479V9.82918C16.75 9.81565 16.75 9.80205 16.75 9.78837C16.7503 9.62647 16.7505 9.45474 16.7188 9.28904C16.638 8.86674 16.4045 8.48898 16.0629 8.22783C15.9289 8.12535 15.7752 8.04877 15.6303 7.97658C15.618 7.97048 15.6059 7.96441 15.5938 7.95836L14.2603 7.29164C14.0575 7.19022 13.8796 7.10128 13.731 7.03647C13.5801 6.97071 13.4012 6.90297 13.2028 6.87982C12.3963 6.78575 11.6311 7.25868 11.3546 8.02203C11.2866 8.20986 11.2672 8.40019 11.2585 8.56454C11.2519 8.68919 11.2504 8.83571 11.2501 9L11.25 9.11944C11.25 9.13026 11.25 9.14115 11.25 9.1521V9.17082C11.25 9.18435 11.25 9.19795 11.25 9.21163C11.2499 9.23918 11.2499 9.26701 11.25 9.29505V12.5499C10.875 12.3581 10.4501 12.25 10 12.25C8.48122 12.25 7.25 13.4812 7.25 15C7.25 16.5188 8.48122 17.75 10 17.75C11.5188 17.75 12.75 16.5188 12.75 15V11.2135ZM11.25 15C11.25 14.3096 10.6904 13.75 10 13.75C9.30964 13.75 8.75 14.3096 8.75 15C8.75 15.6904 9.30964 16.25 10 16.25C10.6904 16.25 11.25 15.6904 11.25 15ZM17.4697 14.4697C17.7626 14.1768 18.2374 14.1768 18.5303 14.4697L21.0303 16.9697C21.3232 17.2626 21.3232 17.7374 21.0303 18.0303C20.7374 18.3232 20.2626 18.3232 19.9697 18.0303L18.75 16.8107V22C18.75 22.4142 18.4142 22.75 18 22.75C17.5858 22.75 17.25 22.4142 17.25 22V16.8107L16.0303 18.0303C15.7374 18.3232 15.2626 18.3232 14.9697 18.0303C14.6768 17.7374 14.6768 17.2626 14.9697 16.9697L17.4697 14.4697Z" })))));
379
495
  }
380
496
  renderRecordButton() {
381
- if (!['voice', 'both', undefined].includes(this.voiceOrOcr))
497
+ if (!this.parsedInputTypes.includes('voice'))
382
498
  return;
383
499
  const buttonClass = [
384
500
  'record-button',
@@ -408,6 +524,8 @@ export class VoiceFormRecorder {
408
524
  if (!this.parsedSchema)
409
525
  return null;
410
526
  switch (this.context) {
527
+ case "ecoteka":
528
+ // console.log("TODO renderFormFields", this.parsedSchema);
411
529
  case "ng":
412
530
  return this.parsedSchema.Children.map((child) => {
413
531
  var _a, _b, _c;
@@ -436,11 +554,31 @@ export class VoiceFormRecorder {
436
554
  const fieldLabel = field.label || fieldName;
437
555
  const isRequired = field.required || false;
438
556
  const fieldValue = this.parsedSchema[2][fieldName];
557
+ // if (['position', 'thesaurus'].includes(field.type)) {
558
+ // try {
559
+ // const response = await fetch(`${this.classificationRootUrl}/ng/api/v1/classification/getList/${fieldType.toLowerCase() == 'position' ? "Position" : "Thesaurus"}/?StartNodeID=${field.config.options.options.startNode}`);
560
+ // if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
561
+ // const data = await response.json();
562
+ // if (Array.isArray(data)) {
563
+ // const options = data.map(item => ({
564
+ // value: item.ID,
565
+ // label: item.System_Name
566
+ // }));
567
+ // if (options.length > 0) {
568
+ // field.pickerOptions = options;
569
+ // // TODO on degage les quotes simples temporairement, a corriger
570
+ // field.options = options.map(option => option.label.replace("'", ""));
571
+ // }
572
+ // } else {
573
+ // console.error("Unexpected API response format:", data);
574
+ // }
575
+ // } catch (error) {
576
+ // console.error("Error fetching classification data:", error);
577
+ // }
578
+ // }
579
+ console.log("filling with", field);
439
580
  return (h("div", { class: "form-group", key: fieldName }, h("label", { htmlFor: fieldName, class: "form-label" }, fieldLabel, isRequired && h("span", { class: "required" }, "*")), this.renderFormField(fieldName, field, ((_b = (_a = this.filledData) === null || _a === void 0 ? void 0 : _a[fieldName]) !== null && _b !== void 0 ? _b : fieldValue))));
440
581
  });
441
- case "ecoteka":
442
- // console.log("TODO renderFormFields", this.parsedSchema);
443
- break;
444
582
  case "track":
445
583
  default:
446
584
  return Object.entries(this.parsedSchema.fields).map(([fieldName, field]) => {
@@ -448,10 +586,9 @@ export class VoiceFormRecorder {
448
586
  return (h("div", { class: "form-group", key: fieldName }, h("label", { htmlFor: fieldName, class: "form-label" }, field.title || fieldName, field.required && h("span", { class: "required" }, "*")), this.renderFormField(fieldName, field, ((_b = (_a = this.filledData) === null || _a === void 0 ? void 0 : _a[fieldName]) !== null && _b !== void 0 ? _b : field.value))));
449
587
  });
450
588
  }
451
- return null;
452
589
  }
453
590
  renderFormField(fieldName, field, value) {
454
- var _a, _b;
591
+ var _a, _b, _c, _d;
455
592
  const isReadonly = this.isReadonlyMode && !this.filledData;
456
593
  const commonProps = {
457
594
  id: fieldName,
@@ -461,13 +598,22 @@ export class VoiceFormRecorder {
461
598
  disabled: isReadonly
462
599
  };
463
600
  switch (field.type) {
601
+ case 'multiselect':
602
+ if (isReadonly) {
603
+ return (h("div", { class: "readonly-select" }, h("div", { class: "select-placeholder" }, "Available options:"), h("ul", { class: "select-options-list" }, (_a = field.options) === null || _a === void 0 ? void 0 : _a.map(option => (h("li", { class: "select-option" }, option))))));
604
+ }
605
+ const selectedValues = Array.isArray(value) ? value : (value ? [value] : []);
606
+ return (h("div", { class: "multiselect-container" }, (_b = field.options) === null || _b === void 0 ? void 0 : _b.map(option => {
607
+ const isChecked = selectedValues.some(v => (v === null || v === void 0 ? void 0 : v.toString().toLowerCase()) === (option === null || option === void 0 ? void 0 : option.toString().toLowerCase()));
608
+ return (h("label", { class: "multiselect-option" }, h("input", { type: "checkbox", name: fieldName, value: option, checked: isChecked, disabled: isReadonly }), h("span", { class: "multiselect-label" }, option)));
609
+ })));
464
610
  case 'select':
465
611
  if (isReadonly) {
466
612
  // In readonly mode, show all options as a list instead of dropdown
467
- return (h("div", { class: "readonly-select" }, h("div", { class: "select-placeholder" }, "Available options:"), h("ul", { class: "select-options-list" }, (_a = field.options) === null || _a === void 0 ? void 0 : _a.map(option => (h("li", { class: "select-option" }, option))))));
613
+ return (h("div", { class: "readonly-select" }, h("div", { class: "select-placeholder" }, "Available options:"), h("ul", { class: "select-options-list" }, (_c = field.options) === null || _c === void 0 ? void 0 : _c.map(option => (h("li", { class: "select-option" }, option))))));
468
614
  }
469
- return (h("select", { id: fieldName, name: fieldName, class: "form-input", required: field.required }, h("option", { value: "" }, "-- Select --"), (_b = field.options) === null || _b === void 0 ? void 0 :
470
- _b.map(option => (h("option", { value: option, selected: value === option }, option)))));
615
+ return (h("select", { id: fieldName, name: fieldName, class: "form-input", required: field.required }, h("option", { value: "" }, "-- Select --"), (_d = field.options) === null || _d === void 0 ? void 0 :
616
+ _d.map(option => (h("option", { value: option, selected: value === option }, option)))));
471
617
  case 'boolean':
472
618
  return (h("input", Object.assign({}, commonProps, { type: "checkbox", class: "form-checkbox", checked: value === true || value === 'true' })));
473
619
  case 'number':
@@ -486,7 +632,7 @@ export class VoiceFormRecorder {
486
632
  return (h("div", { class: "debug-panel" }, h("div", { class: "debug-title" }, "Debug Information:"), h("div", { class: "debug-content" }, JSON.stringify(this.debugInfo, null, 2))));
487
633
  }
488
634
  render() {
489
- return (h("div", { key: '40d850c62945b71d22c1fcb6181c9e8aba0f2a05' }, h("div", { key: 'da8aa5b7f122471a8d4d49662d418bd925f1d84c', class: "voice-recorder-container" + (this.debug || this.renderForm ? "-debug" : "") }, this.renderRecordButton(), this.displayStatus ? this.renderStatusMessage() : "", this.renderUploadButton(), this.renderForm ? this.renderFormPreview() : "", this.debug ? this.renderDebugPanel() : "")));
635
+ return (h("div", { key: '2eddc02481849fda4e6d9e245d4c3c668938b84c' }, h("div", { key: 'eb1bc3cfcf0a19c54f5b2ab1ce488fa289a0dc68', class: "voice-recorder-container" + (this.debug || this.renderForm ? "-debug" : "") }, h("div", { key: 'b93900dce4b0de5d830f4f8517d4e56dc746efbb', class: "row-audio-area" }, this.renderRecordButton(), this.renderUploadRecordButton()), this.displayStatus ? this.renderStatusMessage() : "", this.renderUploadButton(), this.renderForm ? this.renderFormPreview() : "", this.debug ? this.renderDebugPanel() : "")));
490
636
  }
491
637
  static get is() { return "voice-input-module"; }
492
638
  static get encapsulation() { return "shadow"; }
@@ -621,13 +767,13 @@ export class VoiceFormRecorder {
621
767
  "reflect": false,
622
768
  "defaultValue": "'en'"
623
769
  },
624
- "voiceOrOcr": {
770
+ "inputTypes": {
625
771
  "type": "string",
626
- "attribute": "voice-or-ocr",
772
+ "attribute": "input-types",
627
773
  "mutable": false,
628
774
  "complexType": {
629
- "original": "'voice'|'ocr'|'both'",
630
- "resolved": "\"both\" | \"ocr\" | \"voice\"",
775
+ "original": "string",
776
+ "resolved": "string",
631
777
  "references": {}
632
778
  },
633
779
  "required": false,
@@ -639,7 +785,7 @@ export class VoiceFormRecorder {
639
785
  "getter": false,
640
786
  "setter": false,
641
787
  "reflect": false,
642
- "defaultValue": "undefined"
788
+ "defaultValue": "''"
643
789
  },
644
790
  "debug": {
645
791
  "type": "boolean",