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.
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/ocr-file-uploader.voice-input-module.entry.cjs.js.map +1 -0
- package/dist/cjs/ocr-file-uploader_2.cjs.entry.js +4486 -0
- package/dist/cjs/ocr-file-uploader_2.cjs.entry.js.map +1 -0
- package/dist/cjs/voice-input-module.cjs.js +1 -1
- package/dist/collection/collection-manifest.json +8 -2
- package/dist/collection/components/voice-input-module/voice-input-module.css +76 -0
- package/dist/collection/components/voice-input-module/voice-input-module.js +218 -72
- package/dist/collection/components/voice-input-module/voice-input-module.js.map +1 -1
- package/dist/collection/services/llm.service.js +2 -2
- package/dist/collection/services/llm.service.js.map +1 -1
- package/dist/collection/services/speech-to-text.service.js +2 -4
- package/dist/collection/services/speech-to-text.service.js.map +1 -1
- package/dist/collection/utils/schema-converter.js +1 -1
- package/dist/collection/utils/schema-converter.js.map +1 -1
- package/dist/components/ocr-file-uploader.js +9 -0
- package/dist/components/ocr-file-uploader.js.map +1 -0
- package/dist/components/{file-uploader2.js → ocr-file-uploader2.js} +16 -12
- package/dist/components/ocr-file-uploader2.js.map +1 -0
- package/dist/components/voice-input-module.js +3257 -93
- package/dist/components/voice-input-module.js.map +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/ocr-file-uploader.voice-input-module.entry.js.map +1 -0
- package/dist/esm/ocr-file-uploader_2.entry.js +4483 -0
- package/dist/esm/ocr-file-uploader_2.entry.js.map +1 -0
- package/dist/esm/voice-input-module.js +1 -1
- package/dist/types/components/voice-input-module/voice-input-module.d.ts +9 -1
- package/dist/types/components.d.ts +8 -31
- package/dist/types/services/speech-to-text.service.d.ts +1 -1
- package/dist/voice-input-module/ocr-file-uploader.voice-input-module.entry.esm.js.map +1 -0
- package/dist/voice-input-module/p-37de1da2.entry.js +3 -0
- package/dist/voice-input-module/p-37de1da2.entry.js.map +1 -0
- package/dist/voice-input-module/voice-input-module.esm.js +1 -1
- package/loader/cdn.js +1 -0
- package/loader/index.cjs.js +1 -0
- package/loader/index.d.ts +24 -0
- package/loader/index.es2017.js +1 -0
- package/loader/index.js +2 -0
- package/package.json +7 -3
- package/www/build/index.esm.js +2 -0
- package/www/build/index.esm.js.map +1 -0
- package/www/build/loader.esm.js.map +1 -0
- package/www/build/ocr-file-uploader.voice-input-module.entry.esm.js.map +1 -0
- package/www/build/p-37de1da2.entry.js +3 -0
- package/www/build/p-37de1da2.entry.js.map +1 -0
- package/www/build/p-6438474d.js +2 -0
- package/www/build/p-DQuL1Twl.js +2 -0
- package/www/build/p-DQuL1Twl.js.map +1 -0
- package/www/build/p-jmc2yzBp.js +3 -0
- package/www/build/p-jmc2yzBp.js.map +1 -0
- package/www/build/voice-input-module.esm.js +2 -0
- package/www/build/voice-input-module.esm.js.map +1 -0
- package/www/build/voice-input-module.js +33 -0
- package/www/host.config.json +15 -0
- package/www/index.html +1662 -0
- package/.editorconfig +0 -15
- package/.prettierrc.json +0 -13
- package/api-key-inject.js +0 -46
- package/dist/cjs/file-uploader.voice-input-module.entry.cjs.js.map +0 -1
- package/dist/cjs/file-uploader_2.cjs.entry.js +0 -1319
- package/dist/cjs/file-uploader_2.cjs.entry.js.map +0 -1
- package/dist/collection/components/file-uploader/file-uploader.css +0 -26
- package/dist/collection/components/file-uploader/file-uploader.js +0 -130
- package/dist/collection/components/file-uploader/file-uploader.js.map +0 -1
- package/dist/components/file-uploader.d.ts +0 -11
- package/dist/components/file-uploader.js +0 -9
- package/dist/components/file-uploader.js.map +0 -1
- package/dist/components/file-uploader2.js.map +0 -1
- package/dist/esm/file-uploader.voice-input-module.entry.js.map +0 -1
- package/dist/esm/file-uploader_2.entry.js +0 -1316
- package/dist/esm/file-uploader_2.entry.js.map +0 -1
- package/dist/types/components/file-uploader/file-uploader.d.ts +0 -8
- package/dist/voice-input-module/file-uploader.voice-input-module.entry.esm.js.map +0 -1
- package/dist/voice-input-module/p-7b4f33ba.entry.js +0 -2
- package/dist/voice-input-module/p-7b4f33ba.entry.js.map +0 -1
- package/env-config.js +0 -4
- package/inject-env.js +0 -20
- package/src/components/file-uploader/file-uploader.css +0 -26
- package/src/components/file-uploader/file-uploader.tsx +0 -100
- package/src/components/file-uploader/readme.md +0 -31
- package/src/components/voice-input-module/readme.md +0 -114
- package/src/components/voice-input-module/voice-input-module.css +0 -251
- package/src/components/voice-input-module/voice-input-module.tsx +0 -731
- package/src/components.d.ts +0 -158
- package/src/index.html +0 -663
- package/src/index.ts +0 -12
- package/src/services/audio-recorder.service.ts +0 -74
- package/src/services/llm.service.ts +0 -221
- package/src/services/speech-to-text.service.ts +0 -72
- package/src/types/form-schema.types.ts +0 -78
- package/src/types/service-providers.types.ts +0 -22
- package/src/utils/schema-converter.ts +0 -494
- package/stencil.config.ts +0 -24
- 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],"
|
|
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.
|
|
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' ? '
|
|
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(
|
|
106
|
-
|
|
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:
|
|
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
|
-
|
|
156
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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 "
|
|
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': '
|
|
409
|
+
'InputClassification': 'classification',
|
|
349
410
|
'InputCheckbox': 'boolean',
|
|
350
411
|
'InputTextTranslation': 'string',
|
|
351
|
-
'
|
|
352
|
-
'
|
|
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 (!
|
|
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("
|
|
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 (!
|
|
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" }, (
|
|
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 --"), (
|
|
470
|
-
|
|
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: '
|
|
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
|
-
"
|
|
770
|
+
"inputTypes": {
|
|
625
771
|
"type": "string",
|
|
626
|
-
"attribute": "
|
|
772
|
+
"attribute": "input-types",
|
|
627
773
|
"mutable": false,
|
|
628
774
|
"complexType": {
|
|
629
|
-
"original": "
|
|
630
|
-
"resolved": "
|
|
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": "
|
|
788
|
+
"defaultValue": "''"
|
|
643
789
|
},
|
|
644
790
|
"debug": {
|
|
645
791
|
"type": "boolean",
|