@osimatic/helpers-js 1.3.0 → 1.3.2

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/CHANGELOG CHANGED
@@ -73,4 +73,6 @@ Toutes les fonctions des classes SqlTime, SqlDate et SqlDateTime prennent mainte
73
73
  1.1.66
74
74
  Duration.convertToDurationAsCentieme() -> Duration.convertToDurationAsHundredthOfAnHour()
75
75
 
76
+ 1.3.0
77
+ HTTPRequest -> HTTPClient
76
78
 
package/index.js CHANGED
@@ -8,7 +8,7 @@ require('./number');
8
8
 
9
9
  // exports d'ojets non natif
10
10
  const { HTTPClient } = require('./http_client');
11
- const { HTTPRequest, Cookie, UrlAndQueryString } = require('./network');
11
+ const { Cookie, UrlAndQueryString } = require('./network');
12
12
  const { IBAN, BankCard } = require('./bank');
13
13
  const { AudioMedia, VideoMedia, UserMedia } = require('./media');
14
14
  const { PersonName, Email, TelephoneNumber } = require('./contact_details');
@@ -22,6 +22,7 @@ const { SocialNetwork } = require('./social_network');
22
22
  const { sleep, refresh } = require('./util');
23
23
  const { chr, ord, trim, empty } = require('./php.min');
24
24
  const { NumberFormatter } = require('./number');
25
+ const { Password } = require('./user');
25
26
 
26
27
  // exports plugins "maison"
27
28
  const { Browser, UserAgent } = require('./visitor');
@@ -50,7 +51,7 @@ const { WebSocket } = require('./web_socket');
50
51
 
51
52
  module.exports = {
52
53
  Array, Object, Number, String,
53
- HTTPClient, HTTPRequest, Cookie, UrlAndQueryString, IBAN, BankCard, AudioMedia, VideoMedia, UserMedia, PersonName, Email, TelephoneNumber, DateTime, DatePeriod, TimestampUnix, SqlDate, SqlTime, SqlDateTime, Duration, File, CSV, Img, FormHelper, Country, PostalAddress, GeographicCoordinates, HexColor, RgbColor, SocialNetwork, NumberFormatter,
54
+ HTTPClient, Cookie, UrlAndQueryString, IBAN, BankCard, AudioMedia, VideoMedia, UserMedia, PersonName, Email, TelephoneNumber, DateTime, DatePeriod, TimestampUnix, SqlDate, SqlTime, SqlDateTime, Duration, File, CSV, Img, FormHelper, Country, PostalAddress, GeographicCoordinates, HexColor, RgbColor, SocialNetwork, NumberFormatter, Password,
54
55
  Browser, DataTable, Pagination, Navigation, DetailsSubArray, SelectAll, MultipleActionInTable, MultipleActionInDivList, EditValue, FormDate, InputPeriod, ShoppingCart, FlashMessage, CountDown, ImportFromCsv, JwtToken, JwtSession, ApiTokenSession, ListBox, WebRTC, WebSocket, EventBus,
55
56
  sleep, refresh, chr, ord, trim, empty,
56
57
  Chartjs, GoogleCharts, GoogleRecaptcha, GoogleMap, OpenStreetMap
package/network.js CHANGED
@@ -221,7 +221,7 @@ class UrlAndQueryString {
221
221
  if (typeof (object) == 'object') {
222
222
  for (var name in object) {
223
223
  value = object[name];
224
- // 06/06/2022 : ajout de ce if pour éviter bug sur fonction HTTPRequest.formatQueryString
224
+ // 06/06/2022 : ajout de ce if pour éviter bug sur fonction HTTPClient.formatQueryString
225
225
  if (typeof (value) == 'undefined') {
226
226
  continue;
227
227
  }
@@ -231,7 +231,7 @@ class UrlAndQueryString {
231
231
  if (typeof (value) == 'object') {
232
232
  buildStringFromParam(value, p + name);
233
233
  }
234
- // 06/06/2022 : ajout null !== value pour éviter bug sur fonction HTTPRequest.formatQueryString
234
+ // 06/06/2022 : ajout null !== value pour éviter bug sur fonction HTTPClient.formatQueryString
235
235
  else if (null !== value && typeof (value) != 'function' && name != '') {
236
236
  // 27/01/2020 : correction bug boolean affiché en string true/false
237
237
  if (typeof (value) == 'boolean') {
@@ -309,448 +309,4 @@ class UrlAndQueryString {
309
309
 
310
310
  }
311
311
 
312
- /** @deprecated */
313
- class HTTPRequest {
314
- static init() {
315
- require('whatwg-fetch'); //fetch polyfill loaded in window.fetch
316
- }
317
-
318
- static setRefreshTokenUrl(url) {
319
- this.refreshTokenUrl = url;
320
- }
321
-
322
- static setRefreshTokenCallback(callback) {
323
- this.refreshTokenCallback = callback;
324
- }
325
-
326
- static getHeaders(asObject) {
327
- if (typeof this.headers == 'undefined') {
328
- this.headers = {};
329
- }
330
-
331
- if (typeof asObject != 'undefined' && asObject) {
332
- return this.headers;
333
- }
334
-
335
- let httpHeaders = new Headers();
336
- Object.entries(this.headers).forEach(([key, value]) => {
337
- httpHeaders.append(key, value);
338
- });
339
-
340
- return httpHeaders;
341
- }
342
-
343
- static getHeader(key) {
344
- if (typeof this.headers == 'undefined') {
345
- this.headers = {};
346
- }
347
-
348
- return this.headers[key];
349
- }
350
-
351
- static setHeader(key, value) {
352
- if (typeof this.headers == 'undefined') {
353
- this.headers = {};
354
- }
355
-
356
- this.headers[key] = value;
357
- }
358
-
359
- static setAuthorizationHeader(accessToken) {
360
- if (typeof this.headers == 'undefined') {
361
- this.headers = {};
362
- }
363
-
364
- this.headers['Authorization'] = 'Bearer ' + accessToken;
365
- }
366
-
367
- static convertObjectToFormData(obj) {
368
- // 30/05/2022 : ancienne version, qui ne fonctionne pas avec des tableaux
369
- // let formData = new FormData();
370
- // Object.entries(data).forEach(([key, value]) => formData.append(key, value));
371
- // return formData;
372
-
373
- var formData = new FormData();
374
-
375
- function appendFormData(data, root) {
376
- //console.log('appendFormData', data, root);
377
- root = root || '';
378
- if (data instanceof File) {
379
- formData.append(root, data);
380
- } else if (Array.isArray(data)) {
381
- for (var i = 0; i < data.length; i++) {
382
- appendFormData(data[i], root + '[' + i + ']');
383
- }
384
- } else if (typeof data === 'object' && data) {
385
- for (var key in data) {
386
- if (data.hasOwnProperty(key)) {
387
- if (root === '') {
388
- appendFormData(data[key], key);
389
- } else {
390
- appendFormData(data[key], root + '.' + key);
391
- }
392
- }
393
- }
394
- } else {
395
- if (data !== null && typeof data !== 'undefined') {
396
- formData.append(root, data);
397
- }
398
- }
399
- }
400
-
401
- appendFormData(obj);
402
-
403
- return formData;
404
- }
405
-
406
- static formatQueryString(data) {
407
- if (data == null) {
408
- return '';
409
- }
410
- if (typeof data == 'object') {
411
- data = UrlAndQueryString.buildQuery(data);
412
- }
413
- if (data !== '' && data.substring(0, 1) !== '&') {
414
- data = '&' + data;
415
- }
416
- return data;
417
- }
418
-
419
- static formatFormData(data) {
420
- if (!(data instanceof FormData)) {
421
- return HTTPRequest.convertObjectToFormData(data);
422
- }
423
- return data;
424
- }
425
-
426
- static logRequestFailure(response, json) {
427
- console.error('Request failure. Status: ' + response.statusText + ' ; HTTP Code : ' + response.status, json);
428
- }
429
-
430
- static logJqueryRequestFailure(jqxhr, status, errorThrown) {
431
- console.error('Request failure. Status: ' + status + ' ; HTTP Code: ' + jqxhr.status + (null != errorThrown && '' !== errorThrown ? ' ; Error message: ' + errorThrown : ''), jqxhr.responseJSON);
432
- }
433
-
434
- static isExpiredToken(response, json) {
435
- if (response.status !== 401) {
436
- return false;
437
- }
438
-
439
- return (
440
- response.statusText === 'Expired JWT Token'
441
- || (typeof json['message'] != 'undefined' && json['message'] === 'Expired JWT Token')
442
- || (typeof json['error'] != 'undefined' && json['error'] === 'expired_token')
443
- || (typeof json['error'] != 'undefined' && json['error'] === 'authentification_failure')
444
- || (json === 'expired_token')
445
- || (json === 'authentification_failure')
446
- );
447
- }
448
-
449
- static async get(url, data, successCallback, errorCallback) {
450
- url += (!url.includes('?') ? '?' : '') + this.formatQueryString(data);
451
- data = null;
452
-
453
- if (window.fetch) {
454
- const response = await fetch(url, {
455
- method: 'GET',
456
- headers: HTTPRequest.getHeaders(),
457
- mode: 'cors',
458
- cache: 'no-cache'
459
- });
460
-
461
- let jsonData = {};
462
- try {
463
- jsonData = await response.json();
464
-
465
- if (HTTPRequest.isExpiredToken(response, jsonData)) {
466
- HTTPRequest.refreshToken(() => HTTPRequest.get(url, data, successCallback, errorCallback), errorCallback);
467
- return;
468
- }
469
-
470
- if (response.ok) {
471
- successCallback(jsonData, response);
472
- return;
473
- }
474
- } catch (e) {
475
- console.error(e);
476
- if (typeof errorCallback != 'undefined' && errorCallback != null) {
477
- errorCallback(response);
478
- }
479
- return;
480
- }
481
-
482
- HTTPRequest.logRequestFailure(response, jsonData);
483
- if (typeof errorCallback != 'undefined' && errorCallback != null) {
484
- errorCallback(response, jsonData);
485
- }
486
- return;
487
- }
488
-
489
- //l'api fetch n'est pas dispo pour ce navigateur => normalement ce cas ne devrait pas arriver car le polyfill est chargé dans la méthode init
490
- $.ajax({
491
- type: 'GET',
492
- url: url,
493
- headers: HTTPRequest.getHeaders(true),
494
- dataType: 'json',
495
- cache: false,
496
- success: (data, status, jqxhr) => {
497
- if (typeof successCallback != 'undefined' && successCallback != null) {
498
- successCallback(data, jqxhr);
499
- }
500
- },
501
- error: (jqxhr, status, errorThrown) => {
502
- if (HTTPRequest.isExpiredToken(jqxhr, jqxhr.responseJSON)) {
503
- HTTPRequest.refreshToken(() => HTTPRequest.get(url, data, successCallback, errorCallback), errorCallback);
504
- return;
505
- }
506
-
507
- HTTPRequest.logJqueryRequestFailure(jqxhr, status, errorThrown);
508
- if (typeof errorCallback != 'undefined' && errorCallback != null) {
509
- errorCallback(jqxhr, jqxhr.responseJSON);
510
- }
511
- }
512
- });
513
- }
514
-
515
- static async download(url, data, errorCallback, completeCallback, method) {
516
- method = typeof method == 'undefined' || null == method ? 'GET' : method;
517
-
518
- if ('POST' !== method) {
519
- url += (!url.includes('?') ? '?' : '') + this.formatQueryString(data);
520
- data = null;
521
- }
522
-
523
- if (window.fetch) {
524
- let requestInit = {
525
- method: 'GET',
526
- headers: HTTPRequest.getHeaders(),
527
- mode: 'cors',
528
- cache: 'no-cache'
529
- }
530
-
531
- if ('POST' === method) {
532
- requestInit['method'] = 'POST';
533
- requestInit['body'] = this.formatFormData(data);
534
- }
535
-
536
- const response = await fetch(url, requestInit);
537
- try {
538
- if (response.status === 401 && response.statusText === 'Expired JWT Token') {
539
- HTTPRequest.refreshToken(() => HTTPRequest.download(url, data, errorCallback, completeCallback, method), errorCallback);
540
- return;
541
- }
542
-
543
- if (response.ok) {
544
- const blobData = await response.blob();
545
- File.download(blobData, response.headers.get('content-type'), response.headers.get('content-disposition'));
546
- } else {
547
- HTTPRequest.logRequestFailure(response, null);
548
- if (typeof errorCallback != 'undefined' && errorCallback != null) {
549
- errorCallback(response);
550
- }
551
- }
552
- } catch (e) {
553
- console.error(e);
554
- if (typeof errorCallback != 'undefined' && errorCallback != null) {
555
- errorCallback(response);
556
- }
557
- }
558
- if (typeof completeCallback != 'undefined' && completeCallback != null) {
559
- completeCallback(response);
560
- }
561
- return;
562
- }
563
-
564
- //l'api fetch n'est pas dispo pour ce navigateur => normalement ce cas ne devrait pas arriver car le polyfill est chargé dans la méthode init
565
- let ajaxOptions = {
566
- type: 'GET',
567
- url: url,
568
- headers: HTTPRequest.getHeaders(true),
569
- cache: false,
570
- xhrFields: {
571
- responseType: 'blob'
572
- },
573
- };
574
- if ('POST' === method) {
575
- ajaxOptions['type'] = 'POST';
576
- ajaxOptions['data'] = this.formatFormData(data);
577
- ajaxOptions['contentType'] = false;
578
- ajaxOptions['processData'] = false;
579
- }
580
-
581
- $.ajax(Object.assign({...ajaxOptions}, {
582
- success: (data, status, jqxhr) => File.download(data, jqxhr.getResponseHeader('Content-Type'), jqxhr.getResponseHeader('Content-Disposition')),
583
- error: (jqxhr, status, errorThrown) => {
584
- if (HTTPRequest.isExpiredToken(jqxhr, jqxhr.responseJSON)) {
585
- HTTPRequest.refreshToken(() => HTTPRequest.download(url, data, errorCallback, completeCallback, method), errorCallback);
586
- return;
587
- }
588
-
589
- HTTPRequest.logJqueryRequestFailure(jqxhr, status, errorThrown);
590
- if (typeof errorCallback != 'undefined' && errorCallback != null) {
591
- errorCallback(jqxhr);
592
- }
593
- },
594
- complete: (jqxhr) => {
595
- if (typeof completeCallback != 'undefined' && completeCallback != null) {
596
- completeCallback(jqxhr);
597
- }
598
- }
599
- }));
600
- }
601
-
602
- static async post(url, formData, successCallback, errorCallback, formErrorCallback) {
603
- formData = this.formatFormData(formData);
604
-
605
- if (window.fetch) {
606
- const response = await fetch(url, {
607
- method: 'POST',
608
- body: formData,
609
- headers: HTTPRequest.getHeaders(),
610
- mode: 'cors',
611
- cache: 'no-cache'
612
- });
613
-
614
- let jsonData = {};
615
- try {
616
- if (response.status !== 204 && response.statusText !== 'No Content') {
617
- jsonData = await response.json();
618
- }
619
- //console.log(url, jsonData);
620
-
621
- if (url !== HTTPRequest.refreshTokenUrl && HTTPRequest.isExpiredToken(response, jsonData)) {
622
- HTTPRequest.refreshToken(() => HTTPRequest.post(url, formData, successCallback, errorCallback, formErrorCallback), errorCallback);
623
- return;
624
- }
625
-
626
- if (response.ok) {
627
- if (typeof successCallback != 'undefined' && successCallback != null) {
628
- successCallback(jsonData, response);
629
- }
630
- return;
631
- }
632
-
633
- if (response.status === 400 && typeof formErrorCallback != 'undefined' && formErrorCallback != null) {
634
- formErrorCallback(jsonData, response);
635
- return;
636
- }
637
- } catch (e) {
638
- console.error(e);
639
- if (typeof errorCallback != 'undefined' && errorCallback != null) {
640
- errorCallback(response);
641
- }
642
- return;
643
- }
644
-
645
- HTTPRequest.logRequestFailure(response, jsonData);
646
- if (typeof errorCallback != 'undefined' && errorCallback != null) {
647
- errorCallback(response, jsonData);
648
- }
649
- return;
650
- }
651
-
652
- //l'api fetch n'est pas dispo pour ce navigateur => normalement ce cas ne devrait pas arriver car le polyfill est chargé dans la méthode init
653
- $.ajax({
654
- type: 'POST',
655
- url: url,
656
- headers: HTTPRequest.getHeaders(true),
657
- dataType: 'json', // 22/09/2020 : à voir si cette ligne pose pb (utilisé pour requete import et peut être d'autres
658
- data: formData,
659
- cache: false,
660
- contentType: false,
661
- processData: false,
662
- success: (data, status, jqxhr) => {
663
- if (typeof successCallback != 'undefined' && successCallback != null) {
664
- successCallback(data, jqxhr);
665
- }
666
- },
667
- error: (jqxhr, status, errorThrown) => {
668
- if (url !== HTTPRequest.refreshTokenUrl && HTTPRequest.isExpiredToken(jqxhr, jqxhr.responseJSON)) {
669
- HTTPRequest.refreshToken(() => HTTPRequest.post(url, formData, successCallback, errorCallback, formErrorCallback), errorCallback);
670
- return;
671
- }
672
- if (jqxhr.status === 400 && typeof formErrorCallback != 'undefined' && formErrorCallback != null) {
673
- formErrorCallback(jqxhr.responseJSON, jqxhr);
674
- return;
675
- }
676
-
677
- HTTPRequest.logJqueryRequestFailure(jqxhr, status, errorThrown);
678
- if (typeof errorCallback != 'undefined' && errorCallback != null) {
679
- errorCallback(jqxhr, jqxhr.responseJSON);
680
- }
681
- }
682
- });
683
- }
684
-
685
- static refreshToken(onCompleteCallback, errorCallback) {
686
- if (typeof this.refreshTokenCallback == 'function') {
687
- this.refreshTokenCallback(onCompleteCallback);
688
- return;
689
- }
690
-
691
- if (typeof this.refreshTokenUrl == 'undefined') {
692
- console.error('URL refresh token non définie. Appeler HTTPRequest.setRefreshTokenUrl(url)');
693
- return;
694
- }
695
-
696
- let payload = new FormData();
697
- payload.append('refresh_token', JwtSession.getRefreshToken());
698
-
699
- HTTPRequest.post(this.refreshTokenUrl, payload,
700
- (data) => {
701
- JwtSession.setToken(data.token);
702
- JwtSession.setRefreshToken(data.refresh_token);
703
-
704
- HTTPRequest.setAuthorizationHeader(JwtSession.getToken());
705
-
706
- onCompleteCallback();
707
- },
708
- () => {
709
- JwtSession.logout();
710
- errorCallback();
711
- }
712
- );
713
- }
714
-
715
- static doRequest(url, strParam, methode, formatRetour, callback) {
716
- var xhr = null;
717
-
718
- if (window.XMLHttpRequest || window.ActiveXObject) {
719
- if (window.ActiveXObject) {
720
- try {
721
- xhr = new ActiveXObject('Msxml2.XMLHTTP');
722
- } catch (e) {
723
- xhr = new ActiveXObject('Microsoft.XMLHTTP');
724
- }
725
- } else {
726
- xhr = new XMLHttpRequest();
727
- }
728
- } else {
729
- // Votre navigateur ne supporte pas l'objet XMLHTTPRequest!
730
- return null;
731
- }
732
-
733
- xhr.onreadystatechange = function () {
734
- if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 0)) {
735
- let data;
736
- if (formatRetour == 'xml') {
737
- data = xhr.responseXML;
738
- } else {
739
- data = eval('(' + xhr.responseText + ')');
740
- }
741
- callback(data);
742
- }
743
- };
744
-
745
- if (methode === 'POST') {
746
- xhr.open('POST', url, true);
747
- xhr.send();
748
- } else {
749
- xhr.open('GET', url + '?' + strParam, true);
750
- xhr.send(null);
751
- }
752
- return false;
753
- }
754
- }
755
-
756
- module.exports = {HTTPRequest, Cookie, UrlAndQueryString};
312
+ module.exports = { Cookie, UrlAndQueryString };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osimatic/helpers-js",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "main": "main.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
package/user.js ADDED
@@ -0,0 +1,86 @@
1
+ class Password {
2
+ static getPasswordStrength(password) {
3
+ let score = 0;
4
+
5
+ if (password.length >= 8) score++;
6
+ if (/[A-Z]/.test(password)) score++;
7
+ if (/[a-z]/.test(password)) score++;
8
+ if (/[0-9]/.test(password)) score++;
9
+ if (/[^A-Za-z0-9]/.test(password)) score++;
10
+
11
+ if (password.length > 12 && score >= 4) score++; // Bonus pour long mot de passe
12
+
13
+ return score;
14
+ }
15
+
16
+ static displayPasswordStrength(input) {
17
+ function update(input) {
18
+ input = $(input);
19
+ const password = input.val();
20
+ const div = input.closest('.form-group').find('.password_strength_content');
21
+ const score = Password.getPasswordStrength(password);
22
+
23
+ const strengthBar = div.find('.password_strength_bar');
24
+ const strengthText = div.find('.password_strength_text');
25
+
26
+ const conditions = {
27
+ length: password.length >= 8,
28
+ uppercase: /[A-Z]/.test(password),
29
+ lowercase: /[a-z]/.test(password),
30
+ number: /[0-9]/.test(password),
31
+ special: /[^A-Za-z0-9]/.test(password),
32
+ };
33
+
34
+ // Mise à jour des conditions
35
+ div.find('.password_strength_conditions li').each(function () {
36
+ const cond = $(this).data('condition');
37
+ $(this).removeClass('text-success text-danger');
38
+ if (conditions[cond]) {
39
+ $(this).addClass('text-success');
40
+ } else {
41
+ $(this).addClass('text-danger');
42
+ }
43
+ });
44
+
45
+ let width = (score / 6) * 100;
46
+ let color = 'danger';
47
+ let text = 'Très faible';
48
+
49
+ if (score >= 2) { color = 'danger'; text = 'Faible'; }
50
+ if (score >= 4) { color = 'warning'; text = 'Moyen'; }
51
+ if (score >= 5) { color = 'success'; text = 'Fort'; }
52
+
53
+ strengthBar.removeClass('bg-danger bg-warning bg-success').addClass('bg-'+color);
54
+ strengthText.removeClass('text-bg-danger text-bg-warning text-bg-success').addClass('text-bg-'+color);
55
+ strengthBar.width(width+'%');
56
+ strengthText.text(text);
57
+ }
58
+
59
+ const formGroup = input.closest('.form-group');
60
+ formGroup.find('.password_strength_content').remove();
61
+ formGroup.append(''
62
+ +'<div class="password_strength_content mt-1">'
63
+ +' <div class="progress" style="height: 6px;">'
64
+ +' <div class="password_strength_bar progress-bar" role="progressbar"></div>'
65
+ +' </div>'
66
+ +' <div class="d-flex justify-content-between align-items-start mt-2">'
67
+ +' <ul class="password_strength_conditions mb-0 ps-0" style="list-style: none;">'
68
+ +' <li data-condition="length">✔ Au moins 8 caractères</li>'
69
+ +' <li data-condition="uppercase">✔ Une majuscule</li>'
70
+ +' <li data-condition="lowercase">✔ Une minuscule</li>'
71
+ +' <li data-condition="number">✔ Un chiffre</li>'
72
+ +' <li data-condition="special">✔ Un caractère spécial</li>'
73
+ +' </ul>'
74
+ +' <div class="ms-3 text-end">'
75
+ +' <span class="badge password_strength_text" style="font-size: 10pt; font-weight: normal">New</span>'
76
+ +' </div>'
77
+ +' </div>'
78
+ +'</div>'
79
+ );
80
+ input.change(() => update(input));
81
+ input.on('input', () => update(input));
82
+ update(input);
83
+ }
84
+ }
85
+
86
+ module.exports = { Password };