dolibarr 24.0.0-beta
setup.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
4 * Copyright (C) 2026 John BOTELLA
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
27// Load Dolibarr environment
28require '../../main.inc.php';
36require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php";
37require_once __DIR__ . '/../lib/quickmemo.lib.php';
38require_once __DIR__ . '/../class/memo.class.php';
39//require_once "../class/myclass.class.php";
40
41// Translations
42$langs->loadLangs(array("admin", "quickmemo"));
43
44// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
46$hookmanager->initHooks(array('quickmemosetup', 'globalsetup'));
47
48// Parameters
49$action = GETPOST('action', 'aZ09');
50$backtopage = GETPOST('backtopage', 'alpha');
51$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php
52
53$value = GETPOST('value', 'alpha');
54$label = GETPOST('label', 'alpha');
55$scandir = GETPOST('scan_dir', 'alpha');
56$type = 'myobject';
57
58$error = 0;
59$setupnotempty = 0;
60
61// Access control
62if (!$user->admin) {
64}
65
66
67// Set this to 1 to use the factory to manage constants. Warning, the generated module will be compatible with version v15+ only
68$useFormSetup = 1;
69
70if (!class_exists('FormSetup')) {
71 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php';
72}
73$formSetup = new FormSetup($db);
74
75$item = $formSetup->newItem('QUICKMEMO_COLORS_PRESET');
82$item->fieldInputCallBack = function ($item) {
83 global $langs;
84
85 $item->fieldInputOverride = '
86 <div class="color-manager">
87 <div class="controls">
88 <input type="color" id="colorPicker" list="predefinedColors">
89 <datalist id="predefinedColors">
90 <option value="#fff8a6">
91 <option value="#ffd6d6">
92 <option value="#d6ffd9">
93 <option value="#d6e6ff">
94 <option value="#f3d6ff">
95 <option value="#ffffff">
96 <option value="#f5f5f5">
97 </datalist>
98 <button title="'.$langs->trans('Add').'" class="btn-low-emphasis --btn-icon" type="button" id="addColor"><span class="fa fa-plus"></span></button>
99 </div>
100
101 <div class="palette" id="palette"></div>
102
103 <div class="colors-container" id="colorsContainer"></div>
104
105 <input type="hidden" name="QUICKMEMO_COLORS_PRESET" id="colorsInput">
106 </div>';
107 return $item->fieldInputOverride;
108};
109
110
111
112$formSetup->newItem('QUICKMEMO_AUTO_RESIZE_FONT_SIZE_SECTION')->setAsTitle();
113
114$formSetup->newItem('QUICKMEMO_DISABLE_AUTO_RESIZE_FONT_SIZE')->setAsYesNo();
115$item = $formSetup->newItem('QUICKMEMO_AUTO_RESIZE_MIN_FONT_SIZE');
116$item->defaultFieldValue = '1';
123$item->fieldInputCallBack = function ($item) {
124 $item->fieldInputOverride = '
125 <input
126 type="range"
127 class="quickmemo-fontsize-config"
128 id="autoResizeFontMin"
129 name="QUICKMEMO_AUTO_RESIZE_MIN_FONT_SIZE"
130 min="0.5" max="3" step="0.05"
131 value="' . getDolGlobalString('QUICKMEMO_AUTO_RESIZE_MIN_FONT_SIZE', 1) . '"
132 />
133 <div id="previewMinText" class="example-of-memo-text-size">Lorem ipsum dolor sit amet</div>
134 ';
135 return $item->fieldInputOverride;
136};
137
138$item = $formSetup->newItem('QUICKMEMO_AUTO_RESIZE_MAX_FONT_SIZE');
139$item->defaultFieldValue = '1.4';
146$item->fieldInputCallBack = function ($item) {
147 $item->fieldInputOverride = '
148 <input
149 type="range"
150 id="autoResizeFontMax"
151 name="QUICKMEMO_AUTO_RESIZE_MAX_FONT_SIZE"
152 class="quickmemo-fontsize-config"
153 min="0.5" max="3" step="0.05"
154 value="' . getDolGlobalString('QUICKMEMO_AUTO_RESIZE_MAX_FONT_SIZE', 1.4) . '"
155 />
156
157 <div id="previewMaxText" class="example-of-memo-text-size">Lorem ipsum dolor sit amet</div>
158
159 ';
160
161 return $item->fieldInputOverride;
162};
163
164
165$setupnotempty += count($formSetup->items);
166
167
168
169/*
170 * Actions
171 */
172
173// For retrocompatibility Dolibarr < 15.0
174if (versioncompare(explode('.', DOL_VERSION), array(15)) < 0 && $action == 'update' && !empty($user->admin)) {
175 $formSetup->saveConfFromPost();
176}
177
178include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
179
180
181if (empty($action)) {
182 $action = 'edit';
183}
184
185
186/*
187 * View
188 */
189
190$form = new Form($db);
191
192$help_url = '';
193$title = "QuickMemoSetup";
194
195llxHeader('', $langs->trans($title), $help_url, '', 0, 0, '', ['quickmemo/css/setup.css'], '', 'mod-quickmemo page-admin');
196
197
198
199?>
200<script nonce="<?php print getNonce(); ?>">
201document.addEventListener('DOMContentLoaded', function () {
202
206 const PRELOADED_COLORS = <?php print json_encode(Memo::getColorPreset()); ?>;
207
208 const colorPicker = document.getElementById('colorPicker');
209 const addColorBtn = document.getElementById('addColor');
210 const colorsContainer = document.getElementById('colorsContainer');
211 const colorsInput = document.getElementById('colorsInput');
212
213 if (!colorPicker || !addColorBtn || !colorsContainer || !colorsInput) {
214 return;
215 }
216
217
218 let colors = [];
219 let draggedElement = null;
220
221 const placeholder = document.createElement('div');
222 placeholder.className = 'color-placeholder';
223
224 function updateHiddenInput() {
225 colorsInput.value = colors.join(',');
226 }
227
228 function normalize(color) {
229 return color.toLowerCase();
230 }
231
232 function rebuildColorsFromDOM() {
233 colors = Array.from(colorsContainer.querySelectorAll('.color-badge'))
234 .map(el => el.dataset.color);
235 updateHiddenInput();
236 }
237
238 function addColor(color) {
239 color = normalize(color);
240 if (colors.includes(color)) return;
241
242 colors.push(color);
243
244 const badge = document.createElement('div');
245 badge.className = 'color-badge';
246 badge.style.backgroundColor = color;
247 badge.dataset.color = color;
248 badge.draggable = true;
249
250 const removeBtn = document.createElement('span');
251 removeBtn.textContent = '×';
252
253 removeBtn.addEventListener('click', function(e) {
254 e.stopPropagation();
255 badge.remove();
256 rebuildColorsFromDOM();
257 });
258
259 badge.addEventListener('dragstart', function () {
260 draggedElement = badge;
261 badge.classList.add('dragging');
262
263 placeholder.style.width = badge.offsetWidth + 'px';
264 placeholder.style.height = badge.offsetHeight + 'px';
265
266 setTimeout(() => {
267 badge.style.display = 'none';
268 });
269 });
270
271 badge.addEventListener('dragend', function () {
272 badge.classList.remove('dragging');
273 badge.style.display = '';
274 placeholder.remove();
275 draggedElement = null;
276 });
277
278 colorsContainer.addEventListener('dragover', function (e) {
279 e.preventDefault();
280
281 const afterElement = getDragAfterElement(colorsContainer, e.clientX);
282 if (afterElement == null) {
283 colorsContainer.appendChild(placeholder);
284 } else {
285 colorsContainer.insertBefore(placeholder, afterElement);
286 }
287 });
288
289 colorsContainer.addEventListener('drop', function (e) {
290 e.preventDefault();
291 if (!draggedElement) return;
292
293 colorsContainer.insertBefore(draggedElement, placeholder);
294 rebuildColorsFromDOM();
295 });
296
297 badge.appendChild(removeBtn);
298 colorsContainer.appendChild(badge);
299
300 updateHiddenInput();
301 }
302
303 function getDragAfterElement(container, x) {
304 const elements = [...container.querySelectorAll('.color-badge:not(.dragging)')];
305
306 return elements.reduce((closest, child) => {
307 const box = child.getBoundingClientRect();
308 const offset = x - box.left - box.width / 2;
309
310 if (offset < 0 && offset > closest.offset) {
311 return { offset: offset, element: child };
312 } else {
313 return closest;
314 }
315 }, { offset: Number.NEGATIVE_INFINITY }).element;
316 }
317
318 addColorBtn.addEventListener('click', function () {
319 addColor(colorPicker.value);
320 });
321
322 PRELOADED_COLORS.forEach(color => {
323 addColor(color);
324 });
325
326
331 const QUICKMEMO_DISABLE_AUTO_RESIZE_FONT_SIZE = <?php print json_encode(getDolGlobalInt('QUICKMEMO_DISABLE_AUTO_RESIZE_FONT_SIZE')); ?>;
332
333 (function() {
334 const minInput = document.getElementById('autoResizeFontMin');
335 const maxInput = document.getElementById('autoResizeFontMax');
336
337
338 const previewMinText = document.getElementById('previewMinText');
339 const previewMaxText = document.getElementById('previewMaxText');
340
341 function updatePreview(changed) {
342
343 let min = parseFloat(minInput.value);
344 let max = parseFloat(maxInput.value);
345
346 if (changed === 'min' && min > max) {
347 max = min;
348 maxInput.value = max.toFixed(1);
349 }
350
351 if (changed === 'max' && max < min) {
352 min = max;
353 minInput.value = min.toFixed(1);
354 }
355
356 previewMinText.style.fontSize = min + 'em';
357 previewMaxText.style.fontSize = max + 'em';
358 }
359
360 minInput.addEventListener('input', () => updatePreview('min'));
361 maxInput.addEventListener('input', () => updatePreview('max'));
362
363 updatePreview();
364
365 })();
366
367 const toggleDisplayLineSize = function (display = true) {
368 const ids = [
369 'setup-line-item_QUICKMEMO_AUTO_RESIZE_MIN_FONT_SIZE',
370 'setup-line-item_QUICKMEMO_AUTO_RESIZE_MAX_FONT_SIZE'
371 ];
372
373 ids.forEach(id => {
374 const el = document.getElementById(id);
375 if (el) el.style.display = display ? '' : 'none';
376 });
377 };
378
379 toggleDisplayLineSize(!QUICKMEMO_DISABLE_AUTO_RESIZE_FONT_SIZE);
380
381 Dolibarr.on('delConstant', (data) => {
382 if(data.code === 'QUICKMEMO_DISABLE_AUTO_RESIZE_FONT_SIZE'){
383 toggleDisplayLineSize(true);
384 }
385 });
386
387 Dolibarr.on('setConstant', (data) => {
388 if(data.code === 'QUICKMEMO_DISABLE_AUTO_RESIZE_FONT_SIZE'){
389 toggleDisplayLineSize(false);
390 }
391 });
392});
393</script>
394<?php
395
396// Subheader
397$linkback = '<a href="'.($backtopage ? $backtopage : DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1').'">'.img_picto($langs->trans("BackToModuleList"), 'back', 'class="pictofixedwidth"').'<span class="hideonsmartphone">'.$langs->trans("BackToModuleList").'</span></a>';
398
399print load_fiche_titre($langs->trans($title), $linkback, 'title_setup');
400
401// Configuration header
403print dol_get_fiche_head($head, 'settings', $langs->trans($title), -1, "fa-sticky-note_fa");
404
405// Setup page goes here
406echo '<span class="opacitymedium">'.$langs->trans("QuickMemoSetupPage").'</span><br><br>';
407
408
409if (!empty($formSetup->items)) {
410 print $formSetup->generateOutput(true);
411 print '<br>';
412}
413
414
415
416if (empty($setupnotempty)) {
417 print '<br>'.$langs->trans("NothingToSetup");
418}
419
420// Page end
421print dol_get_fiche_end();
422
423llxFooter();
424$db->close();
versioncompare($versionarray1, $versionarray2)
Compare 2 versions (stored into 2 arrays), to know if a version (a,b,c) is lower than (x,...
Definition admin.lib.php:72
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage generation of HTML components Only common components must be here.
This class help you create setup render.
static getColorPreset()
Get color preset.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
quickmemoAdminPrepareHead()
Prepare admin pages header.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.