dolibarr 20.0.0
custom_prompt.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2022 Alice Adminson <aadminson@example.com>
4 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
26// Load Dolibarr environment
27require '../../main.inc.php';
28require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php";
29require_once '../lib/ai.lib.php';
30
31$langs->loadLangs(array("admin", "website", "other"));
32
33// Parameters
34$action = GETPOST('action', 'aZ09');
35$backtopage = GETPOST('backtopage', 'alpha');
36$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php
37
38if (empty($action)) {
39 $action = 'edit';
40}
41
42$error = 0;
43$setupnotempty = 0;
44
45// Access control
46if (!$user->admin) {
48}
49
50
51// Set this to 1 to use the factory to manage constants. Warning, the generated module will be compatible with version v15+ only
52$useFormSetup = 1;
53
54if (!class_exists('FormSetup')) {
55 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php';
56}
57
58$formSetup = new FormSetup($db);
59
60// Setup conf AI_PROMPT
61$item = $formSetup->newItem('AI_CONFIGURATIONS_PROMPT');
62$item->defaultFieldValue = '';
63
64$setupnotempty += count($formSetup->items);
65
66$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
67
68// List of AI features
69$arrayofaifeatures = array(
70 'textgenerationemail' => array('label' => $langs->trans('TextGeneration').' ('.$langs->trans("EmailContent").')', 'picto'=>'', 'status'=>'development'),
71 'textgenerationwebpage' => array('label' => $langs->trans('TextGeneration').' ('.$langs->trans("WebsitePage").')', 'picto'=>'', 'status'=>'development'),
72 'textgeneration' => array('label' => $langs->trans('TextGeneration').' ('.$langs->trans("Other").')', 'picto'=>'', 'status'=>'notused'),
73 'imagegeneration' => array('label' => 'ImageGeneration', 'picto'=>'', 'status'=>'notused'),
74 'videogeneration' => array('label' => 'VideoGeneration', 'picto'=>'', 'status'=>'notused'),
75 'transcription' => array('label' => 'Transcription', 'picto'=>'', 'status'=>'notused'),
76 'translation' => array('label' => 'Translation', 'picto'=>'', 'status'=>'notused'),
77 'audiotext' => array('label' => 'AudioText', 'picto'=>'', 'status'=>'notused')
78);
79
80
81/*
82 * Actions
83 */
84
85$functioncode = GETPOST('functioncode', 'alpha');
86$pre_prompt = GETPOST('prePrompt');
87$post_prompt = GETPOST('postPrompt');
88// get all configs in const AI
89
90$currentConfigurationsJson = getDolGlobalString('AI_CONFIGURATIONS_PROMPT');
91$currentConfigurations = json_decode($currentConfigurationsJson, true);
92
93if ($action == 'update' && GETPOST('cancel')) {
94 $action = 'edit';
95}
96if ($action == 'update' && !GETPOST('cancel')) {
97 $error = 0;
98 if (empty($functioncode)) {
99 $error++;
100 setEventMessages($langs->trans('ErrorInputRequired'), null, 'errors');
101 }
102 if (!is_array($currentConfigurations)) {
103 $currentConfigurations = [];
104 }
105
106 if (empty($functioncode) || (empty($pre_prompt) && empty($post_prompt))) {
107 if (isset($currentConfigurations[$functioncode])) {
108 unset($currentConfigurations[$functioncode]);
109 }
110 } else {
111 $currentConfigurations[$functioncode] = [
112 'prePrompt' => $pre_prompt,
113 'postPrompt' => $post_prompt,
114 ];
115 }
116
117 $newConfigurationsJson = json_encode($currentConfigurations, JSON_UNESCAPED_UNICODE);
118 $result = dolibarr_set_const($db, 'AI_CONFIGURATIONS_PROMPT', $newConfigurationsJson, 'chaine', 0, '', $conf->entity);
119 if (!$error) {
120 if ($result) {
121 header("Location: ".$_SERVER['PHP_SELF']);
122 setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
123 exit;
124 } else {
125 setEventMessages($langs->trans("ErrorUpdating"), null, 'errors');
126 }
127 }
128
129 $action = 'edit';
130}
131
132if ($action == 'updatePrompts') {
133 $key = GETPOST('key', 'alpha');
134
135 $currentConfigurations[$key] = [
136 'prePrompt' => $pre_prompt,
137 'postPrompt' => $post_prompt,
138 ];
139
140 $newConfigurationsJson = json_encode($currentConfigurations, JSON_UNESCAPED_UNICODE);
141 $result = dolibarr_set_const($db, 'AI_CONFIGURATIONS_PROMPT', $newConfigurationsJson, 'chaine', 0, '', $conf->entity);
142 if (!$error) {
143 $action = '';
144 if ($result) {
145 header("Location: ".$_SERVER['PHP_SELF']);
146 setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
147 exit;
148 } else {
149 setEventMessages($langs->trans("ErrorUpdating"), null, 'errors');
150 }
151 }
152}
153
154if ($action == 'confirm_deleteproperty' && GETPOST('confirm') == 'yes') {
155 $key = GETPOST('key', 'alpha');
156
157 if (isset($currentConfigurations[$key])) {
158 unset($currentConfigurations[$key]);
159
160 $newConfigurationsJson = json_encode($currentConfigurations, JSON_UNESCAPED_UNICODE);
161 $res = dolibarr_set_const($db, 'AI_CONFIGURATIONS_PROMPT', $newConfigurationsJson, 'chaine', 0, '', $conf->entity);
162 if ($res) {
163 header("Location: ".$_SERVER['PHP_SELF']);
164 setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs');
165 exit;
166 } else {
167 setEventMessages($langs->trans("NoRecordDeleted"), null, 'errors');
168 }
169 }
170}
171
172
173/*
174 * View
175 */
176
177$form = new Form($db);
178
179$help_url = '';
180$title = "AiSetup";
181
182llxHeader('', $langs->trans($title), $help_url);
183
184// Subheader
185$linkback = '<a href="'.($backtopage ? $backtopage : DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1').'">'.$langs->trans("BackToModuleList").'</a>';
186
187print load_fiche_titre($langs->trans($title), $linkback, 'title_setup');
188
189// Configuration header
190$head = aiAdminPrepareHead();
191print dol_get_fiche_head($head, 'custom', $langs->trans($title), -1, "fa-microchip");
192
193//$newbutton = '<a href="'.$_SERVER["PHP_SELF"].'?action=create">'.$langs->trans("New").'</a>';
194$newbutton = '';
195
196print load_fiche_titre($langs->trans("AIPromptForFeatures"), $newbutton, '');
197
198if ($action == 'deleteproperty') {
199 $formconfirm = $form->formconfirm(
200 $_SERVER["PHP_SELF"].'?key='.urlencode(GETPOST('key', 'alpha')),
201 $langs->trans('Delete'),
202 $langs->trans('ConfirmDeleteSetup', GETPOST('key', 'alpha')),
203 'confirm_deleteproperty',
204 '',
205 0,
206 1
207 );
208 print $formconfirm;
209}
210
211if ($action == 'edit' || $action == 'deleteproperty') {
212 $out = '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
213 $out .= '<input type="hidden" name="token" value="'.newToken().'">';
214 $out .= '<input type="hidden" name="action" value="update">';
215
216
217 $out .= '<table class="noborder centpercent">';
218 $out .= '<thead>';
219 $out .= '<tr class="liste_titre">';
220 $out .= '<td>'.$langs->trans('Add').'</td>';
221 $out .= '<td></td>';
222 $out .= '</tr>';
223 $out .= '</thead>';
224 $out .= '<tbody>';
225 $out .= '<tr class="oddeven">';
226 $out .= '<td class="col-setup-title">';
227 $out .= '<span id="module" class="spanforparamtooltip">'.$langs->trans("Feature").'</span>';
228 $out .= '</td>';
229 $out .= '<td>';
230 // Combo list of AI features
231 $out .= '<select name="functioncode" id="functioncode" class="flat minwidth500">';
232 $out .= '<option>&nbsp;</option>';
233 foreach ($arrayofaifeatures as $key => $val) {
234 $labelhtml = $langs->trans($arrayofaifeatures[$key]['label']).($arrayofaifeatures[$key]['status'] == 'notused' ? ' <span class="opacitymedium">('.$langs->trans("NotYetAvailable").')</span>' : "");
235 $labeltext = $langs->trans($arrayofaifeatures[$key]['label']);
236 $out .= '<option value="'.$key.'" data-html="'.dol_escape_htmltag($labelhtml).'">'.dol_escape_htmltag($labeltext).'</option>';
237 }
238 /*
239 $sql = "SELECT name FROM llx_const WHERE name LIKE 'MAIN_MODULE_%' AND value = '1'";
240 $resql = $db->query($sql);
241
242 if ($resql) {
243 while ($obj = $db->fetch_object($resql)) {
244 $moduleName = str_replace('MAIN_MODULE_', '', $obj->name);
245 $out .= '<option value="' . htmlspecialchars($moduleName) . '">' . htmlspecialchars($moduleName) . '</option>';
246 }
247 } else {
248 $out.= '<option disabled>Erreur :'. $db->lasterror().'</option>';
249 }
250 */
251 $out .= '</select>';
252 $out .= ajax_combobox("functioncode");
253
254 $out .= '</td>';
255 $out .= '</tr>';
256 $out .= '<tr class="oddeven">';
257 $out .= '<td class="col-setup-title">';
258 $out .= '<span id="prePrompt" class="spanforparamtooltip">'.$langs->trans("Pre-Prompt").'</span>';
259 $out .= '</td>';
260 $out .= '<td>';
261 $out .= '<textarea class="flat minwidth500 quatrevingtpercent" id="prePromptInput" name="prePrompt" rows="3"></textarea>';
262 $out .= '</td>';
263 $out .= '</tr>';
264 $out .= '<tr class="oddeven">';
265 $out .= '<td class="col-setup-title">';
266 $out .= '<span id="postPrompt" class="spanforparamtooltip">'.$langs->trans("Post-Prompt").'</span>';
267 $out .= '</td>';
268 $out .= '<td>';
269 $out .= '<textarea class="flat minwidth500 quatrevingtpercent" id="postPromptInput" name="postPrompt" rows="3"></textarea>';
270 $out .= '</td>';
271 $out .= '</tr>';
272 $out .= '</tbody>';
273 $out .= '</table>';
274
275 $out .= $form->buttonsSaveCancel("Add", "");
276 $out .= '</form>';
277 $out .= '<br><br><br>';
278
279 print $out;
280}
281
282
283if ($action == 'edit' || $action == 'create' || $action == 'deleteproperty') {
284 $out = '';
285
286 if (!empty($currentConfigurations)) {
287 $out = '<table class="noborder centpercent">';
288 foreach ($currentConfigurations as $key => $config) {
289 if (!empty($key) && !preg_match('/^[a-z]+$/i', $key)) { // Ignore empty saved setup
290 continue;
291 }
292
293 $out .= '<thead>';
294 $out .= '<tr class="liste_titre">';
295 $out .= '<td>'.$arrayofaifeatures[$key]['picto'].' '.$langs->trans($arrayofaifeatures[$key]['label']);
296 $out .= '<a class="viewfielda reposition marginleftonly marginrighttonly showInputBtn" href="#" data-index="'.$key.'" data-state="edit" data-icon-edit="'.dol_escape_htmltag(img_edit()).'" data-icon-cancel="'.dol_escape_htmltag(img_view()).'">'.img_edit().'</a>';
297 $out .= '<a class="deletefielda reposition marginleftonly right" href="'.$_SERVER["PHP_SELF"].'?action=deleteproperty&token='.newToken().'&key='.urlencode($key).'">'.img_delete().'</a>';
298 $out .= '</td>';
299 $out .= '<td></td>';
300 $out .= '</tr>';
301 $out .= '</thead>';
302 $out .= '<tbody>';
303
304 $out .= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
305 $out .= '<input type="hidden" name="token" value="'.newToken().'">';
306 $out .= '<input type="hidden" name="key" value="'.$key.'" />';
307 $out .= '<input type="hidden" name="action" value="updatePrompts">';
308 $out .= '<tr class="oddeven">';
309 $out .= '<td class="col-setup-title">';
310 $out .= '<span id="prePrompt" class="spanforparamtooltip">'.$langs->trans("Pre-Prompt").'</span>';
311 $out .= '</td>';
312 $out .= '<td>';
313 $out .= '<textarea class="flat minwidth500" id="prePromptInput_'.$key.'" name="prePrompt" rows="2" disabled>'.$config['prePrompt'].'</textarea>';
314 $out .= '</td>';
315 $out .= '</tr>';
316 $out .= '<tr class="oddeven">';
317 $out .= '<td class="col-setup-title">';
318 $out .= '<span id="postPrompt" class="spanforparamtooltip">'.$langs->trans("Post-Prompt").'</span>';
319 $out .= '</td>';
320 $out .= '<td>';
321 $out .= '<textarea class="flat minwidth500" id="postPromptInput_'.$key.'" name="postPrompt" rows="2" disabled>'.$config['postPrompt'].'</textarea>';
322 $out .= '<br><input type="submit" class="button small submitBtn" name="modify" data-index="'.$key.'" style="display: none;" value="'.dol_escape_htmltag($langs->trans("Modify")).'"/>';
323
324 $out .= '</td>';
325 $out .= '</tr>';
326 $out .= '</form>';
327 }
328 $out .= '</tbody>';
329 $out .= '</table>';
330 }
331
332
333 $out .= "<script>
334 var configurations = ".$currentConfigurationsJson.";
335 $(document).ready(function() {
336 $('#module_select').change(function() {
337 var selectedModule = $(this).val();
338 var moduleConfig = configurations[selectedModule];
339
340 if (moduleConfig) {
341 $('#prePromptInput').val(moduleConfig.prePrompt || '');
342 $('#postPromptInput').val(moduleConfig.postPrompt || '');
343 } else {
344 $('#prePromptInput').val('');
345 $('#postPromptInput').val('');
346 }
347 });
348
349 $('.showInputBtn').click(function() {
350 event.preventDefault();
351 var index = $(this).data('index');
352 var state = $(this).data('state');
353
354 if(state === 'edit') {
355 $('#prePromptInput_'+index).removeAttr('disabled').focus();
356 $('#postPromptInput_'+index).removeAttr('disabled');
357 $('.submitBtn[data-index=' + index + ']').show();
358 $(this).html($(this).data('icon-cancel'));
359 $(this).data('state', 'cancel');
360
361 } else {
362
363 $('#prePromptInput_'+index).attr('disabled', 'disabled');
364 $('#postPromptInput_'+index).attr('disabled', 'disabled');
365 $('.submitBtn[data-index=' + index + ']').hide();
366 $(this).html($(this).data('icon-edit'));
367 $(this).data('state', 'edit');
368 }
369 });
370 });
371
372
373 </script>";
374
375 print $out;
376
377 print '<br>';
378}
379
380if (empty($setupnotempty)) {
381 print '<br>'.$langs->trans("NothingToSetup");
382}
383
384
385// Page end
386print dol_get_fiche_end();
387
388llxFooter();
389$db->close();
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
aiAdminPrepareHead()
Prepare admin pages header.
Definition ai.lib.php:30
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:456
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:55
llxFooter()
Empty footer.
Definition wrapper.php:69
Class to manage generation of HTML components Only common components must be here.
This class help you create setup render.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
img_view($titlealt='default', $float=0, $other='class="valignmiddle"')
Show logo view card.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.