Browse Source

ajout des bases du projet

raphael 4 years ago
parent
commit
fe5a4de675
100 changed files with 17411 additions and 0 deletions
  1. 16
    0
      .gitignore
  2. 1563
    0
      assets/exclusive/js/component/Sortable.js
  3. 15
    0
      assets/exclusive/js/component/cpt-captcha.js
  4. 1581
    0
      assets/exclusive/js/component/croppie.js
  5. 12
    0
      assets/exclusive/js/list.js
  6. 8
    0
      assets/exclusive/js/rocket-chat.js
  7. 250
    0
      assets/exclusive/scss/component/croppie.css
  8. 1
    0
      assets/shared/build/global/build_global-images.js
  9. 42
    0
      assets/shared/build/global/build_global-js.js
  10. 3
    0
      assets/shared/build/global/build_global-scss.js
  11. 453
    0
      assets/shared/build/js/barchart.js
  12. 1108
    0
      assets/shared/build/js/cpt-plugins.js
  13. 471
    0
      assets/shared/build/js/dashboard.js
  14. 54
    0
      assets/shared/build/js/init.js
  15. 1168
    0
      assets/shared/build/js/jquery.autocomplete.js
  16. 187
    0
      assets/shared/build/js/menu-back-office.js
  17. 77
    0
      assets/shared/build/js/menu.js
  18. 30
    0
      assets/shared/build/js/ressources.js
  19. 161
    0
      assets/shared/build/js/select_autocomplete.js
  20. 99
    0
      assets/shared/build/js/utility.js
  21. 51
    0
      assets/shared/build/scss/bootstrap.scss
  22. 12
    0
      assets/shared/build/scss/bootstrap/extended.scss
  23. 28
    0
      assets/shared/build/scss/bootstrap/extended/badge.scss
  24. 27
    0
      assets/shared/build/scss/bootstrap/extended/button.scss
  25. 19
    0
      assets/shared/build/scss/bootstrap/extended/dropdown.scss
  26. 298
    0
      assets/shared/build/scss/bootstrap/extended/form.scss
  27. 53
    0
      assets/shared/build/scss/bootstrap/extended/global.scss
  28. 84
    0
      assets/shared/build/scss/bootstrap/extended/modal.scss
  29. 9
    0
      assets/shared/build/scss/bootstrap/extended/table.scss
  30. 36
    0
      assets/shared/build/scss/bootstrap/extended/tabs.scss
  31. 6
    0
      assets/shared/build/scss/bootstrap/overwrited.scss
  32. 37
    0
      assets/shared/build/scss/bootstrap/overwrited/breadcrumbs.scss
  33. 4
    0
      assets/shared/build/scss/bootstrap/overwrited/card.scss
  34. 5
    0
      assets/shared/build/scss/core.scss
  35. 6
    0
      assets/shared/build/scss/plugins.scss
  36. 203
    0
      assets/shared/build/scss/plugins/datepicker.scss
  37. 70
    0
      assets/shared/build/scss/plugins/jquery.autocomplete.scss
  38. 28
    0
      assets/shared/build/scss/plugins/owl-carousel2/_animate.scss
  39. 7
    0
      assets/shared/build/scss/plugins/owl-carousel2/_autoheight.scss
  40. 115
    0
      assets/shared/build/scss/plugins/owl-carousel2/_core.scss
  41. 17
    0
      assets/shared/build/scss/plugins/owl-carousel2/_lazyload.scss
  42. 30
    0
      assets/shared/build/scss/plugins/owl-carousel2/_theme.default.scss
  43. 30
    0
      assets/shared/build/scss/plugins/owl-carousel2/_theme.green.scss
  44. 64
    0
      assets/shared/build/scss/plugins/owl-carousel2/_theme.scss
  45. 52
    0
      assets/shared/build/scss/plugins/owl-carousel2/_video.scss
  46. 5
    0
      assets/shared/build/scss/plugins/owl-carousel2/owl.carousel.scss
  47. 1
    0
      assets/shared/build/scss/plugins/owl-carousel2/owl.theme.default.scss
  48. 1
    0
      assets/shared/build/scss/plugins/owl-carousel2/owl.theme.green.scss
  49. 33
    0
      assets/shared/build/scss/plugins/tablesorter.scss
  50. 42
    0
      assets/shared/build/scss/plugins/zoom.scss
  51. 82
    0
      assets/shared/build/scss/settings.scss
  52. 468
    0
      assets/shared/build/scss/temp.scss
  53. 41
    0
      assets/shared/build/scss/theme.scss
  54. 1
    0
      assets/shared/build/scss/theme/base/detail.scss
  55. 95
    0
      assets/shared/build/scss/theme/base/global.scss
  56. 62
    0
      assets/shared/build/scss/theme/base/hero.scss
  57. 46
    0
      assets/shared/build/scss/theme/base/log-in.scss
  58. 649
    0
      assets/shared/build/scss/theme/base/nav-space.scss
  59. 234
    0
      assets/shared/build/scss/theme/base/nav.scss
  60. 257
    0
      assets/shared/build/scss/theme/base/parcours.scss
  61. 81
    0
      assets/shared/build/scss/theme/components/arrow.scss
  62. 9
    0
      assets/shared/build/scss/theme/components/avatar.scss
  63. 45
    0
      assets/shared/build/scss/theme/components/carousel.scss
  64. 1
    0
      assets/shared/build/scss/theme/components/collapse.scss
  65. 122
    0
      assets/shared/build/scss/theme/components/custom-card.scss
  66. 25
    0
      assets/shared/build/scss/theme/components/dropdown.scss
  67. 3704
    0
      assets/shared/build/scss/theme/components/icons.scss
  68. 120
    0
      assets/shared/build/scss/theme/components/list.scss
  69. 8
    0
      assets/shared/build/scss/theme/components/logo.scss
  70. 21
    0
      assets/shared/build/scss/theme/components/rating.scss
  71. 28
    0
      assets/shared/build/scss/theme/components/sentence-finder.scss
  72. 15
    0
      assets/shared/build/scss/theme/components/sticky.scss
  73. 64
    0
      assets/shared/build/scss/theme/components/tags.scss
  74. 46
    0
      assets/shared/build/scss/theme/components/widget.scss
  75. 117
    0
      assets/shared/build/scss/theme/components/wizzard.scss
  76. 20
    0
      assets/shared/build/scss/theme/tools/dev.scss
  77. 5
    0
      assets/shared/build/scss/theme/tools/remove-outline.scss
  78. 26
    0
      assets/shared/build/scss/theme/utilities/background.scss
  79. 57
    0
      assets/shared/build/scss/theme/utilities/border.scss
  80. 18
    0
      assets/shared/build/scss/theme/utilities/cover.scss
  81. 34
    0
      assets/shared/build/scss/theme/utilities/shape.scss
  82. 5
    0
      assets/shared/build/scss/theme/utilities/visibility.scss
  83. 3
    0
      assets/shared/build/scss/theme/utilities/width.scss
  84. BIN
      assets/shared/fonts/ionicons.eot
  85. 2230
    0
      assets/shared/fonts/ionicons.svg
  86. BIN
      assets/shared/fonts/ionicons.ttf
  87. BIN
      assets/shared/fonts/ionicons.woff
  88. BIN
      assets/shared/images/apple-touch-icon.png
  89. BIN
      assets/shared/images/avatar/avatar.png
  90. BIN
      assets/shared/images/captain-sign-in-organisme-de-formation.jpg
  91. BIN
      assets/shared/images/categories/formations-achat-transport-logistique-internationale.jpg
  92. BIN
      assets/shared/images/categories/formations-commerce-vente.jpg
  93. BIN
      assets/shared/images/categories/formations-developpement-personnel.jpg
  94. BIN
      assets/shared/images/categories/formations-direction-entreprise.jpg
  95. BIN
      assets/shared/images/categories/formations-droit.jpg
  96. BIN
      assets/shared/images/categories/formations-general.jpg
  97. BIN
      assets/shared/images/categories/formations-gestion-finance-comptabilite.jpg
  98. BIN
      assets/shared/images/categories/formations-informatique.jpg
  99. BIN
      assets/shared/images/categories/formations-langues.jpg
  100. 0
    0
      assets/shared/images/categories/formations-loisir.jpg

+ 16
- 0
.gitignore View File

@@ -0,0 +1,16 @@
1
+
2
+###> symfony/framework-bundle ###
3
+/.env
4
+/public/bundles/
5
+/var/
6
+/vendor/
7
+/node_modules/
8
+/.vscode
9
+/composer.lock
10
+/yarn.lock
11
+/yarn-error.log
12
+/symfony.lock
13
+/.project
14
+/.history/
15
+/.svn/
16
+###< symfony/framework-bundle ###

+ 1563
- 0
assets/exclusive/js/component/Sortable.js
File diff suppressed because it is too large
View File


+ 15
- 0
assets/exclusive/js/component/cpt-captcha.js View File

@@ -0,0 +1,15 @@
1
+function onReCaptchaLoad() {
2
+    // magic happens here
3
+	let id = $(".captcha div.g-captcha").attr("id");
4
+	grecaptcha.render(
5
+		$("#" + id)[0],
6
+		{
7
+			sitekey:$.turbolead.get("recaptcha_api_key"),
8
+			callback:function()
9
+			{
10
+				$(".captcha").find(".invalid-feedback").hide();
11
+			}
12
+
13
+		}
14
+	);
15
+};

+ 1581
- 0
assets/exclusive/js/component/croppie.js
File diff suppressed because it is too large
View File


+ 12
- 0
assets/exclusive/js/list.js View File

@@ -0,0 +1,12 @@
1
+$(document).ready(function()
2
+{
3
+  // change page limit
4
+  $("select.page-limit").each(function()
5
+  {
6
+    $(this).on('change',function()
7
+    {
8
+      let option = $(this).find('option:selected');
9
+      window.location.href = option.attr('data-url');
10
+    })
11
+  });
12
+});

+ 8
- 0
assets/exclusive/js/rocket-chat.js View File

@@ -0,0 +1,8 @@
1
+// Start of Rocket.Chat Livechat Script
2
+(function(w, d, s, u) {
3
+	w.RocketChat = function(c) { w.RocketChat._.push(c) }; w.RocketChat._ = []; w.RocketChat.url = u;
4
+	var h = d.getElementsByTagName(s)[0], j = d.createElement(s);
5
+	j.async = true; j.src = 'https://chat.logipro.com/packages/rocketchat_livechat/assets/rocketchat-livechat.min.js?_=201702160944';
6
+	h.parentNode.insertBefore(j, h);
7
+})(window, document, 'script', 'https://chat.logipro.com/livechat');
8
+// End of Rocket.Chat Livechat Script

+ 250
- 0
assets/exclusive/scss/component/croppie.css View File

@@ -0,0 +1,250 @@
1
+.croppie-container {
2
+    width: 100%;
3
+    height: 100%;
4
+}
5
+
6
+.croppie-container .cr-image {
7
+    z-index: -1;
8
+    position: absolute;
9
+    top: 0;
10
+    left: 0;
11
+    transform-origin: 0 0;
12
+    max-height: none;
13
+    max-width: none;
14
+}
15
+
16
+.croppie-container .cr-boundary {
17
+    position: relative;
18
+    overflow: hidden;
19
+    margin: 0 auto;
20
+    z-index: 1;
21
+    width: 100%;
22
+    height: 100%;
23
+}
24
+
25
+.croppie-container .cr-viewport,
26
+.croppie-container .cr-resizer {
27
+    position: absolute;
28
+    border: 2px solid #fff;
29
+    margin: auto;
30
+    top: 0;
31
+    bottom: 0;
32
+    right: 0;
33
+    left: 0;
34
+    box-shadow: 0 0 2000px 2000px rgba(0, 0, 0, 0.5);
35
+    z-index: 0;
36
+}
37
+
38
+.croppie-container .cr-resizer {
39
+  z-index: 2;
40
+  box-shadow: none;
41
+  pointer-events: none;
42
+}
43
+
44
+.croppie-container .cr-resizer-vertical,
45
+.croppie-container .cr-resizer-horisontal {
46
+  position: absolute;
47
+  pointer-events: all;
48
+}
49
+
50
+.croppie-container .cr-resizer-vertical::after,
51
+.croppie-container .cr-resizer-horisontal::after {
52
+    display: block;
53
+    position: absolute;
54
+    box-sizing: border-box;
55
+    border: 1px solid black;
56
+    background: #fff;
57
+    width: 10px;
58
+    height: 10px;
59
+    content: '';
60
+}
61
+
62
+.croppie-container .cr-resizer-vertical {
63
+  bottom: -5px;
64
+  cursor: row-resize;
65
+  width: 100%;
66
+  height: 10px;
67
+}
68
+
69
+.croppie-container .cr-resizer-vertical::after {
70
+    left: 50%;
71
+    margin-left: -5px;
72
+}
73
+
74
+.croppie-container .cr-resizer-horisontal {
75
+  right: -5px;
76
+  cursor: col-resize;
77
+  width: 10px;
78
+  height: 100%;
79
+}
80
+
81
+.croppie-container .cr-resizer-horisontal::after {
82
+    top: 50%;
83
+    margin-top: -5px;
84
+}
85
+
86
+.croppie-container .cr-original-image {
87
+    display: none;
88
+}
89
+
90
+.croppie-container .cr-vp-circle {
91
+    border-radius: 50%;
92
+}
93
+
94
+.croppie-container .cr-overlay {
95
+    z-index: 1;
96
+    position: absolute;
97
+    cursor: move;
98
+    touch-action: none;
99
+}
100
+
101
+.croppie-container .cr-slider-wrap {
102
+    width: 75%;
103
+    margin: 15px auto;
104
+    text-align: center;
105
+}
106
+
107
+.croppie-result {
108
+    position: relative;
109
+    overflow: hidden;
110
+}
111
+
112
+.croppie-result img {
113
+    position: absolute;
114
+}
115
+
116
+.croppie-container .cr-image,
117
+.croppie-container .cr-overlay,
118
+.croppie-container .cr-viewport {
119
+    -webkit-transform: translateZ(0);
120
+    -moz-transform: translateZ(0);
121
+    -ms-transform: translateZ(0);
122
+    transform: translateZ(0);
123
+}
124
+
125
+/*************************************/
126
+/***** STYLING RANGE INPUT ***********/
127
+/*************************************/
128
+/*http://brennaobrien.com/blog/2014/05/style-input-type-range-in-every-browser.html */
129
+/*************************************/
130
+
131
+.cr-slider {
132
+    -webkit-appearance: none;
133
+/*removes default webkit styles*/
134
+	/*border: 1px solid white; *//*fix for FF unable to apply focus style bug */
135
+    width: 300px;
136
+/*required for proper track sizing in FF*/
137
+    max-width: 100%;
138
+    padding-top: 8px;
139
+    padding-bottom: 8px;
140
+    background-color: transparent;
141
+}
142
+
143
+.cr-slider::-webkit-slider-runnable-track {
144
+    width: 100%;
145
+    height: 3px;
146
+    background: rgba(0, 0, 0, 0.5);
147
+    border: 0;
148
+    border-radius: 3px;
149
+}
150
+
151
+.cr-slider::-webkit-slider-thumb {
152
+    -webkit-appearance: none;
153
+    border: none;
154
+    height: 16px;
155
+    width: 16px;
156
+    border-radius: 50%;
157
+    background: #ddd;
158
+    margin-top: -6px;
159
+}
160
+
161
+.cr-slider:focus {
162
+    outline: none;
163
+}
164
+/*
165
+.cr-slider:focus::-webkit-slider-runnable-track {
166
+background: #ccc;
167
+}
168
+*/
169
+
170
+.cr-slider::-moz-range-track {
171
+    width: 100%;
172
+    height: 3px;
173
+    background: rgba(0, 0, 0, 0.5);
174
+    border: 0;
175
+    border-radius: 3px;
176
+}
177
+
178
+.cr-slider::-moz-range-thumb {
179
+    border: none;
180
+    height: 16px;
181
+    width: 16px;
182
+    border-radius: 50%;
183
+    background: #ddd;
184
+    margin-top: -6px;
185
+}
186
+
187
+/*hide the outline behind the border*/
188
+.cr-slider:-moz-focusring {
189
+    outline: 1px solid white;
190
+    outline-offset: -1px;
191
+}
192
+
193
+.cr-slider::-ms-track {
194
+    width: 100%;
195
+    height: 5px;
196
+    background: transparent;
197
+/*remove bg colour from the track, we'll use ms-fill-lower and ms-fill-upper instead */
198
+	border-color: transparent;/*leave room for the larger thumb to overflow with a transparent border */
199
+	border-width: 6px 0;
200
+	color: transparent;/*remove default tick marks*/
201
+}
202
+.cr-slider::-ms-fill-lower {
203
+	background: rgba(0, 0, 0, 0.5);
204
+	border-radius: 10px;
205
+}
206
+.cr-slider::-ms-fill-upper {
207
+	background: rgba(0, 0, 0, 0.5);
208
+	border-radius: 10px;
209
+}
210
+.cr-slider::-ms-thumb {
211
+	border: none;
212
+	height: 16px;
213
+	width: 16px;
214
+	border-radius: 50%;
215
+	background: #ddd;
216
+	margin-top:1px;
217
+}
218
+.cr-slider:focus::-ms-fill-lower {
219
+	background: rgba(0, 0, 0, 0.5);
220
+}
221
+.cr-slider:focus::-ms-fill-upper {
222
+	background: rgba(0, 0, 0, 0.5);
223
+}
224
+/*******************************************/
225
+
226
+/***********************************/
227
+/* Rotation Tools */
228
+/***********************************/
229
+.cr-rotate-controls {
230
+	position: absolute;
231
+	bottom: 5px;
232
+	left: 5px;
233
+	z-index: 1;
234
+}
235
+.cr-rotate-controls button {
236
+	border: 0;
237
+	background: none;
238
+}
239
+.cr-rotate-controls i:before {
240
+	display: inline-block;
241
+	font-style: normal;
242
+	font-weight: 900;
243
+	font-size: 22px;
244
+}
245
+.cr-rotate-l i:before {
246
+	content: '↺';
247
+}
248
+.cr-rotate-r i:before {
249
+	content: '↻';
250
+}

+ 1
- 0
assets/shared/build/global/build_global-images.js View File

@@ -0,0 +1 @@
1
+require.context("../../images",true,  /\.(png|jpe?g|svg|gif)$/im);

+ 42
- 0
assets/shared/build/global/build_global-js.js View File

@@ -0,0 +1,42 @@
1
+// REQUIRE bootstrap
2
+require('bootstrap');
3
+//require('chart.js');
4
+
5
+//require('../js/init.js');
6
+
7
+// Jquery
8
+require('jquery-ui/core.js');
9
+require('jquery-ui/widget.js');
10
+require('jquery-ui/widgets/slider.js');
11
+require('jquery-ui/widgets/mouse.js');
12
+require('jquery-ui/widgets/draggable.js');
13
+require('jquery-ui/widgets/resizable.js');
14
+require('jquery-ui/widgets/datepicker.js');
15
+require('jquery-ui/widgets/autocomplete.js');
16
+require('jquery-ui/widgets/button.js');
17
+
18
+// Gridstack
19
+require('gridstack-module/gridstack.js');
20
+require('gridstack-module/gridstack.jQueryUI.js');
21
+require('jquery-ui/ui/i18n/datepicker-fr');
22
+
23
+// d3 (graphique)
24
+//require('d3');
25
+
26
+// chart.js (graphique)
27
+require('chart.js');
28
+
29
+require('../js/utility.js');
30
+require('../js/menu.js');
31
+require('../js/menu-back-office.js');
32
+require('../js/ressources.js');
33
+require('../js/barchart.js');
34
+require('../js/dashboard.js');
35
+require('../js/select_autocomplete.js');
36
+
37
+require('../js/cpt-plugins.js');
38
+// pour le header
39
+require('../js/jquery.autocomplete.js');
40
+
41
+// en dernier
42
+require('../js/init.js');

+ 3
- 0
assets/shared/build/global/build_global-scss.js View File

@@ -0,0 +1,3 @@
1
+// REQUIRE CSS
2
+require('../scss/core.scss');
3
+require('../scss/temp.scss');

+ 453
- 0
assets/shared/build/js/barchart.js View File

@@ -0,0 +1,453 @@
1
+$( document ).ready(function() {
2
+  //setTimeout(initBarChart,20);
3
+});
4
+
5
+
6
+window.initBarChart = function(widget)
7
+{
8
+  // Ajout d'une fonctionnalité pour dessiner des informations suplémentaires sur le graphique
9
+  var originalLineDraw = Chart.controllers.horizontalBar.prototype.draw;
10
+  Chart.helpers.extend(Chart.controllers.horizontalBar.prototype, {
11
+     draw: function () {
12
+         originalLineDraw.apply(this, arguments);
13
+
14
+         var chart = this.chart;
15
+         var ctx = chart.chart.ctx;
16
+
17
+         var parent = $(chart.canvas).parent(".contentChart");
18
+         var parentSup = parent.parent(".heightFreeSpace");
19
+         var scrollBot = parentSup.scrollTop() - parent.height() + parentSup.height();
20
+
21
+         // Afficher les lignes
22
+         var indexs = chart.config.options.linesAtIndex;
23
+         if (typeof indexs !== "undefined")
24
+         {
25
+           ctx.save();
26
+           $.each(indexs, function(id, index) {
27
+              if (index.display)
28
+              {
29
+               index.color = index.color||"red";
30
+               index.lineWidth = index.lineWidth||3;
31
+               index.label = index.label||"";
32
+
33
+               var xaxis = chart.scales['x-axis-0'];
34
+               var yaxis = chart.scales['y-axis-0'];
35
+
36
+               var x1 = xaxis.getPixelForValue(index.value);
37
+               var y1 = yaxis.top;
38
+
39
+               var x2 = xaxis.getPixelForValue(index.value);
40
+               var y2 = yaxis.bottom;
41
+
42
+               // Dessiner les lignes
43
+               ctx.beginPath();
44
+               ctx.moveTo(x1, y1);
45
+               ctx.strokeStyle = index.color;
46
+               ctx.lineWidth= index.lineWidth;
47
+               ctx.lineTo(x2, y2);
48
+               ctx.stroke();
49
+
50
+             }
51
+           });
52
+
53
+           // Dessiner dans un second temps les tooltips pour éviter qu'elle se
54
+           // trouve dessous certaine lignes
55
+           $.each(indexs, function(id, index) {
56
+              if (index.display && index.tooltipDisplay)
57
+              {
58
+               index.color = index.color||"red";
59
+               index.lineWidth = index.lineWidth||3;
60
+               index.label = index.label||"";
61
+
62
+               var xaxis = chart.scales['x-axis-0'];
63
+               var yaxis = chart.scales['y-axis-0'];
64
+
65
+               var x2 = xaxis.getPixelForValue(index.value);
66
+               var y2 = yaxis.bottom + scrollBot;
67
+
68
+               // Dessiner les tooltips des lignes
69
+              var width = ctx.measureText(index.value).width;
70
+              var width2 = ctx.measureText(index.label).width;
71
+              if (width < width2) { width = width2; }
72
+
73
+              ctx.strokeStyle = index.color;
74
+              ctx.lineWidth= index.lineWidth;
75
+              ctx.globalAlpha = 0.8;
76
+              ctx.fillStyle = "black";
77
+              // Rectangle centré + 5 de padding en x et 5 en y (10-5 = 5)
78
+              roundRect(ctx, x2-width*0.5-5, y2-20, width+10, 40, 8, true);
79
+
80
+              ctx.globalAlpha = 1.0;
81
+              ctx.fillStyle = "white";
82
+              ctx.textBaseline="middle";
83
+              ctx.textAlign = "center";
84
+              ctx.fillText(index.label,x2,y2-7);
85
+              ctx.fillText(index.value,x2,y2+10);
86
+             }
87
+           });
88
+           ctx.restore();
89
+         }
90
+     }
91
+  });
92
+
93
+  Chart.Controller.prototype.updateAtMouseEvent = function(e) {
94
+    var chart = this;
95
+    var helpers = Chart.helpers;
96
+    var eventPosition = helpers.getRelativePosition(e, chart);
97
+
98
+    var xaxis = chart.scales['x-axis-0'];
99
+
100
+    var indexs = chart.config.options.linesAtIndex;
101
+    var found = (function() {
102
+      $.each(indexs, function(id, index) {
103
+        if (index.display) {
104
+          var xPixel = xaxis.getPixelForValue(index.value);
105
+          var newValue = false;
106
+          // Limte est la motier de la larger plus un pixel de marge
107
+          var limite = index.lineWidth*0.5+1;
108
+          if (xPixel < eventPosition.x + limite && xPixel > eventPosition.x - limite) {
109
+            newValue = true;
110
+          }
111
+          // S'il y a un changement redessiner la vue
112
+          if (index.tooltipDisplay != newValue) {
113
+            index.tooltipDisplay = newValue;
114
+            chart.draw();
115
+          }
116
+        }
117
+      });
118
+    }).call(this);
119
+  };
120
+
121
+
122
+  let char = null;
123
+  let legendContent = $("<div>", {class:"legend-content"});
124
+
125
+  if (typeof widget != 'undefined') {
126
+    char = widget.find(".myChart")[0];
127
+  }
128
+  else {
129
+    char = document.getElementById("myChart");
130
+  }
131
+
132
+	if (char)
133
+	{
134
+    $(char).parent(".contentChart").parent(".heightFreeSpace").before(legendContent[0]);
135
+
136
+	  var ctx = char.getContext('2d');
137
+	  var myChart = new Chart(ctx, {
138
+	      type: 'horizontalBar',
139
+	      data: {
140
+	          labels: [],
141
+	          datasets: [{
142
+	              label: '',
143
+	              data: [],
144
+	              backgroundColor: 'rgba(255,114,10,0.5)',
145
+	              borderColor: 'rgba(255,114,10,1)',
146
+	              borderWidth: 2
147
+	          }]
148
+	      },
149
+	      options: {
150
+            linesAtIndex: {},
151
+	          scales: {
152
+	              xAxes: [{
153
+                  ticks: {
154
+                      beginAtZero: true
155
+                  },
156
+                  scaleLabel: {
157
+                    show: true,
158
+                    labelString: 'Value'
159
+                  }
160
+	              }],
161
+                yAxes: [{
162
+                }]
163
+	          },
164
+	          maintainAspectRatio: false,
165
+            legend: false,
166
+            layout: {
167
+                padding: {
168
+                    left: 0,
169
+                    right: 25,
170
+                    top: 0,
171
+                    bottom: 0
172
+                }
173
+            }
174
+	      }
175
+	  });
176
+
177
+    function drawLegend()
178
+    {
179
+      // Affichage des legendes en dehors du graphique
180
+      legendContent.html('');
181
+      var legends = $('<ul>', {class:myChart.id + '-legend'}).appendTo(legendContent);
182
+
183
+      for (var i = 0; i < myChart.data.datasets.length; i++)
184
+      {
185
+        var legend = $('<li>', {class:'solid'}).appendTo(legends);
186
+
187
+        $('<span>', {class:'reprensation'}).css({
188
+          "background-color": myChart.data.datasets[i].backgroundColor,
189
+          "border": myChart.data.datasets[i].borderWidth + 'px solid ' + myChart.data.datasets[i].borderColor
190
+        }).appendTo(legend);
191
+
192
+        if (myChart.data.datasets[i].label) {
193
+          $('<span>', {class:'label', text:myChart.data.datasets[i].label}).appendTo(legend);
194
+        }
195
+      }
196
+
197
+      // légende des lignes
198
+      $.each(myChart.options.linesAtIndex, function(id, line) {
199
+        if (line.display)
200
+        {
201
+          var legend = $('<li>', {class:'solid'}).appendTo(legends);
202
+
203
+          $('<span>').css({
204
+            "border-left": line.lineWidth + 'px solid ' + line.color
205
+          }).appendTo(legend);
206
+
207
+          if (line.label) {
208
+            $('<span>', {class:'label', text:line.label}).appendTo(legend);
209
+          }
210
+
211
+          legend.mouseenter(function(){
212
+            chartLabelLineHover(id);
213
+          }).mouseleave(function(){
214
+            chartLabelLineOut(id);
215
+          });
216
+        }
217
+      });
218
+
219
+      resizeHeightFreeSpace($(char).parent(".contentChart").parent(".heightFreeSpace"));
220
+      myChart.resize();
221
+    }
222
+
223
+    // Event pour connaitre la position du curseur sur le graphique
224
+    $(char).mousemove(function(e){
225
+      myChart.updateAtMouseEvent(e);
226
+    });
227
+
228
+    /**
229
+     * Fonction qui permet d'afficher la tooltip d'un ligne sur le graphique
230
+     * lorsque son label est survolé
231
+     */
232
+    function chartLabelLineHover(lineId) {
233
+      if (typeof myChart.options.linesAtIndex[lineId] != "undefined") {
234
+        myChart.options.linesAtIndex[lineId].tooltipDisplay = true;
235
+        myChart.draw();
236
+      }
237
+    }
238
+    /**
239
+     * Fonction qui permet de masquer la tooltip d'un ligne sur le graphique
240
+     * lorsque son label n'est plus survolé
241
+     */
242
+    function chartLabelLineOut(lineId) {
243
+     if (typeof myChart.options.linesAtIndex[lineId] != "undefined") {
244
+       myChart.options.linesAtIndex[lineId].tooltipDisplay = false;
245
+       myChart.draw();
246
+     }
247
+   }
248
+
249
+
250
+    // Variable pour savoir si la mise à jour automatique est active
251
+    var autoUpdate = false;
252
+    // Variable pour savoir si la requête de récupération de données est en cours
253
+    var updateRun = false;
254
+
255
+    var lastIndexColorUse = -1;
256
+
257
+    /**
258
+     * Fonction qui lance la récupération des données à afficher
259
+     */
260
+	  function updateData()
261
+    {
262
+      if (!updateRun)
263
+      {
264
+        // Passé la variable updateRun à true pour éviter de relancer
265
+        // une mise à jour pendant qu'il y en a une en cours
266
+        updateRun = true;
267
+        widget.getWidgetData(function(result){
268
+    	    myChart.data.labels = result["labels"];
269
+    	    myChart.data.datasets = result["datasets"];
270
+
271
+          // On ajoute tout les données à afficher en plus sous forme de ligne (exemple les seuils)
272
+          $.each(result["lines"], function(index, line) {
273
+            myChart.options.linesAtIndex[index] = {value: line.value, label: line.label, color: line.color, lineWidth:'3', display:true, tooltipDisplay:false};
274
+          });
275
+
276
+    	    //myChart.data.datasets[1].data = [result["median"],result["median"],result["median"],result["median"],result["median"]];
277
+          updateChart();
278
+
279
+          // Si on est en mode auto update, relancer la mise à jour dans 5sec
280
+          // Amélioration possible : ne pas lancer la mise à jour si la page
281
+          // n'est pas visible (peut etre déjà géré par certain navigateur de base)
282
+          if (autoUpdate) {
283
+            setTimeout(function(){ updateRun = false; updateData(); }, 5000);
284
+          }
285
+          else {
286
+            updateRun = false;
287
+          }
288
+        });
289
+      }
290
+	  }
291
+
292
+    /**
293
+     * Redessine le graphique en prennant en compte les options
294
+     */
295
+    function updateChart()
296
+    {
297
+      // Calcule du Max de l'axe X
298
+      var maxValue = 0;
299
+      if (typeof myChart.data.datasets !== "undefined")
300
+      {
301
+        maxValue = Math.max.apply(Math,myChart.data.datasets[0].data);
302
+
303
+        // Appliquer les options
304
+        $.each(optionsWidget, function(index, option) {
305
+          if (option.type == 'line') {
306
+            myChart.options.linesAtIndex[index].display = option.value;
307
+
308
+            // Calcule du Max de l'axe X
309
+            if (option.value && maxValue < parseFloat(myChart.options.linesAtIndex[index].value)) {
310
+              maxValue = myChart.options.linesAtIndex[index].value;
311
+            }
312
+          }
313
+        });
314
+
315
+        // Appliquer le max de l'axe X
316
+        myChart.options.scales.xAxes[0]["ticks"]["max"] = parseInt(maxValue)+1;
317
+
318
+        // Si les donnée sont trop compressé, faire uns scroll
319
+        // @todo a adapter lorsqu'il y aura plusieurs donnée par entrée
320
+        // @toto ce code est adapté à un horizontale bare, à adapter au autre type d'affichage.
321
+        var dataMinHeight = 20;
322
+        var nbLabel = myChart.data.labels.length;
323
+        var nbDataSet = myChart.data.datasets.length;
324
+        var minHeight = nbLabel*nbDataSet*dataMinHeight;
325
+        var parentHeight = $(char).parent(".contentChart").parent(".heightFreeSpace").height();
326
+        if (minHeight > parentHeight) {
327
+          widget.find(".contentChart").css('min-height', minHeight+'px')
328
+        }
329
+        else {
330
+          widget.find(".contentChart").css('min-height', '100%')
331
+        }
332
+      }
333
+
334
+      // Mettre à jour les données automatiquement si l'option est coché
335
+      if (optionsWidget["realtime"].value)
336
+      {
337
+        autoUpdate = true;
338
+  	    updateData();
339
+      }
340
+      else {
341
+        autoUpdate = false;
342
+      }
343
+
344
+      // Redessiner le graphique
345
+      myChart.update();
346
+      // Mettre à jour la légende
347
+      //legendContent.html(myChart.generateLegend());
348
+      drawLegend();
349
+
350
+      // Adapter la taille du conteneur du graphique conteneurs
351
+      resizeHeightFreeSpace($(char).parent(".contentChart").parent(".heightFreeSpace"));
352
+      myChart.resize();
353
+    }
354
+
355
+
356
+    // Les options du graphique
357
+    var optionsWidget = {};
358
+    var optionWidget = widget.find('.option-widget');
359
+    // Extraire les options du widget
360
+    optionWidget.each(function(index, option) {
361
+      var optionObject = $(option);
362
+      var optionName = optionObject.attr('data-option-name');
363
+
364
+      optionsWidget[optionName] = {};
365
+      optionsWidget[optionName].type = optionObject.attr('data-option-type');
366
+
367
+      // En fonciton du type de input récupérer leur valeur (peut changer dans le temps avec l'ajout d'autre input)
368
+      if (optionObject.is(':checkbox'))
369
+      {
370
+        optionsWidget[optionName].value = optionObject.is(':checked');
371
+        optionObject.click(function(){
372
+          optionsWidget[optionName].value = optionObject.is(':checked');
373
+          updateChart();
374
+          widget.saveWidget();
375
+        });
376
+      }
377
+      else
378
+      {
379
+        optionsWidget[optionName].value = optionObject.val();
380
+        optionObject.change(function(){
381
+          optionsWidget[optionName].value = optionObject.val();
382
+          updateChart();
383
+          widget.saveWidget();
384
+        });
385
+      }
386
+    });
387
+
388
+	  // Afficher les données directement sans annimation
389
+	  myChart.options.animation.duration = 0;
390
+	  updateData();
391
+	  myChart.options.animation.duration = 1000;
392
+
393
+	}
394
+}
395
+
396
+
397
+
398
+
399
+/**
400
+ * Fonctions de dessin utiles
401
+ */
402
+
403
+/**
404
+* Draws a rounded rectangle using the current state of the canvas.
405
+* If you omit the last three params, it will draw a rectangle
406
+* outline with a 5 pixel border radius
407
+* @param {CanvasRenderingContext2D} ctx
408
+* @param {Number} x The top left x coordinate
409
+* @param {Number} y The top left y coordinate
410
+* @param {Number} width The width of the rectangle
411
+* @param {Number} height The height of the rectangle
412
+* @param {Number} [radius = 5] The corner radius; It can also be an object
413
+*                 to specify different radii for corners
414
+* @param {Number} [radius.tl = 0] Top left
415
+* @param {Number} [radius.tr = 0] Top right
416
+* @param {Number} [radius.br = 0] Bottom right
417
+* @param {Number} [radius.bl = 0] Bottom left
418
+* @param {Boolean} [fill = false] Whether to fill the rectangle.
419
+* @param {Boolean} [stroke = true] Whether to stroke the rectangle.
420
+*/
421
+function roundRect(ctx, x, y, width, height, radius, fill, stroke) {
422
+  if (typeof stroke == 'undefined') {
423
+    stroke = true;
424
+  }
425
+  if (typeof radius === 'undefined') {
426
+    radius = 5;
427
+  }
428
+  if (typeof radius === 'number') {
429
+    radius = {tl: radius, tr: radius, br: radius, bl: radius};
430
+  } else {
431
+    var defaultRadius = {tl: 0, tr: 0, br: 0, bl: 0};
432
+    for (var side in defaultRadius) {
433
+      radius[side] = radius[side] || defaultRadius[side];
434
+    }
435
+  }
436
+  ctx.beginPath();
437
+  ctx.moveTo(x + radius.tl, y);
438
+  ctx.lineTo(x + width - radius.tr, y);
439
+  ctx.quadraticCurveTo(x + width, y, x + width, y + radius.tr);
440
+  ctx.lineTo(x + width, y + height - radius.br);
441
+  ctx.quadraticCurveTo(x + width, y + height, x + width - radius.br, y + height);
442
+  ctx.lineTo(x + radius.bl, y + height);
443
+  ctx.quadraticCurveTo(x, y + height, x, y + height - radius.bl);
444
+  ctx.lineTo(x, y + radius.tl);
445
+  ctx.quadraticCurveTo(x, y, x + radius.tl, y);
446
+  ctx.closePath();
447
+  if (fill) {
448
+    ctx.fill();
449
+  }
450
+  if (stroke) {
451
+    ctx.stroke();
452
+  }
453
+}

+ 1108
- 0
assets/shared/build/js/cpt-plugins.js
File diff suppressed because it is too large
View File


+ 471
- 0
assets/shared/build/js/dashboard.js View File

@@ -0,0 +1,471 @@
1
+$( document ).ready(function() {
2
+  initDashboard();
3
+
4
+  $('.searchdatepicker').datepicker({
5
+	  minDate:new Date($("input[name='start']").val()),
6
+	 maxDate:new Date($("input[name='end']").val()),
7
+  });
8
+});
9
+
10
+function initDashboard()
11
+{
12
+  var actionSaveWidget = $(".edit-widget").attr("data-action-save");
13
+  var actionGetListWidgetClass = $(".edit-widget").attr("data-action-widget-list");
14
+  var actionGetWidgetContent = $(".edit-widget").attr("data-action-widget-get");
15
+  var actionGetWidgetDatas = $(".edit-widget").attr("data-action-widget-get-datas");
16
+  var idFormation = $(".edit-widget").attr("data-formation-id");
17
+
18
+
19
+  var options = {
20
+      cellHeight: 50,
21
+      verticalMargin: 10,
22
+      disableDrag: true,
23
+      disableResize: true
24
+  };
25
+  $('.grid-stack').gridstack(options);
26
+  var grid = $('.grid-stack').data('gridstack');
27
+  initWidget($(".grid-stack-item"));
28
+
29
+  // Variable qui contiendra la liste des class de widget
30
+  var selectWidgetClass = [];
31
+
32
+  // Lancer la récupérationn des class de widget
33
+  getListWidgetClass(function(result)
34
+  {
35
+    // Création d'un select à partir des données remontées
36
+    selectWidgetClass = $('<select>', {class:"widgets_class form-control"});
37
+    // Ajouter une option pour chaque class de widget
38
+    $(result).each(function() {
39
+      selectWidgetClass.append($("<option>").attr('value',this.class).text(this.name));
40
+    });
41
+
42
+    // Ajouter le select au widget
43
+    initSelectWidget($(".grid-stack-item"), 'd-none');
44
+  });
45
+
46
+  // Click sur le bouton édition
47
+  $(".edit-widget").click(function(){
48
+    var icon = $(this).children(".ion");
49
+    // Si le bouton est celui d'édition passé en mode édition et changer le bouton en sauvegarde
50
+    if (icon.hasClass("ion-md-create"))
51
+    {
52
+      // Passer en mode édition
53
+      editMode();
54
+    }
55
+    else if (icon.hasClass("ion-md-save"))
56
+    {
57
+      // Bonton de sauvegarde passé en bouton d'édition
58
+      waitMode();
59
+
60
+      // Savegarde des données
61
+      saveDashboard(function(result){
62
+        if (result) {
63
+          // Si la sauvegarde c'est bien passé on sort de l'édition
64
+          viewMode();
65
+        }
66
+        else {
67
+          // Si ça c'est mal passé on retroune à l'édition
68
+          editMode();
69
+        }
70
+      });
71
+    }
72
+
73
+    // Modifier le titre du bouton d'édition
74
+    var savTitle = $(this).attr("data-original-title");
75
+    $(this).attr("data-original-title", $(this).attr("data-title-active"));
76
+    $(this).attr("data-title-active", savTitle);
77
+  });
78
+
79
+  /** Action d'ajout d'un widget **/
80
+  $(".add-widget").click(function(){
81
+    addWidget();
82
+  });
83
+
84
+  function addWidget()
85
+  {
86
+    // On récupère le template de widget et on le clone
87
+    var template = $("#widget-content-template");
88
+    var templateClone = template.clone(true);
89
+    var content = $(templateClone.html());
90
+    grid.addWidget(content, 0, 0, 6, 4, true, 3, 12, 2);
91
+    grid.movable(content, true);
92
+    grid.resizable(content, true);
93
+
94
+    // Initialisations
95
+    initWidget(content);
96
+    initSelectWidget(content);
97
+  }
98
+
99
+  /**
100
+   * Passe le tableau de bord en mode édition
101
+   */
102
+  function editMode()
103
+  {
104
+    var icon = $(".edit-widget .ion");
105
+    // Passé en mode édition et changer le bouton en sauvegarde
106
+    icon.removeClass("ion-md-create ion-md-hourglass").addClass("ion-md-save");
107
+    grid.movable('.grid-stack-item', true);
108
+    grid.resizable('.grid-stack-item', true);
109
+    // Masquer les éléments d'édition
110
+    $(".add-widget, .delete-widget, .widgets_class").removeClass("d-none");
111
+
112
+    // Titre éditable
113
+    var title = $("h2.title-widget");
114
+    title.each(function(){
115
+      var titleVal = $(this).text();
116
+      $(this).replaceWith($("<input>", {type:"text", class:"title-widget h3 w-100 p-1 px-2", value:titleVal}));
117
+    });
118
+  }
119
+
120
+  /**
121
+   * Passe le tableau de bord en mode lecture
122
+   */
123
+  function viewMode()
124
+  {
125
+    var icon = $(".edit-widget .ion");
126
+
127
+    // Bonton de sauvegarde passé en bouton d'édition
128
+    icon.removeClass("ion-md-hourglass ion-md-save").addClass("ion-md-create");
129
+    grid.movable('.grid-stack-item', false);
130
+    grid.resizable('.grid-stack-item', false);
131
+    // Afficher les éléments d'édition
132
+    $(".add-widget, .delete-widget, .widgets_class").addClass("d-none");
133
+
134
+    // Titre non éditable
135
+    var title = $("input.title-widget");
136
+    title.each(function(){
137
+      var titleVal = $(this).val();
138
+      $(this).replaceWith($("<h2>", {class:"title-widget", text:titleVal}));
139
+    });
140
+  }
141
+
142
+  /**
143
+   * Passe le tableau de bord en mode attente
144
+   */
145
+  function waitMode()
146
+  {
147
+    var icon = $(".edit-widget .ion");
148
+
149
+    // Bonton de sauvegarde passé en bouton d'édition
150
+    icon.removeClass("ion-md-save ion-md-create").addClass("ion-md-hourglass");
151
+    grid.movable('.grid-stack-item', false);
152
+    grid.resizable('.grid-stack-item', false);
153
+    // Masquer les éléments d'édition
154
+    $(".add-widget, .delete-widget, .widgets_class").addClass("d-none");
155
+
156
+    // Titre non éditable
157
+    var title = $("input.title-widget");
158
+    title.each(function(){
159
+      var titleVal = $(this).val();
160
+      $(this).replaceWith($("<h2>", {class:"title-widget", text:titleVal}));
161
+    });
162
+  }
163
+
164
+
165
+  /**
166
+   * Initialise les événements des widgets
167
+   * @param object[] widgets Le widget ou un enssemble de widgets
168
+   */
169
+  function initWidget(widgets)
170
+  {
171
+    widgets.each(function( index ) {
172
+      var widget = $(this);
173
+
174
+      widget.saveWidget = function(callback){
175
+        callback = callback || function(){};
176
+        saveDashboard(callback, false);
177
+      };
178
+
179
+      // Event
180
+      widget.find(".delete-widget").click(function(){
181
+        $(this).tooltip('hide')
182
+        grid.removeWidget(widget);
183
+      }).tooltip();
184
+
185
+      // Contenu
186
+      udpateWidgetContent(widget);
187
+    });
188
+  }
189
+
190
+  /**
191
+   * Initialise les selects pour chaque widget renseigné
192
+   * @param dom[] widgets Les widgets auquels ajouter le select
193
+   * @param string classSelect La ou les class css à ajouter au select
194
+   */
195
+  function initSelectWidget(widgets, classSelect)
196
+  {
197
+    classSelect = classSelect || "";
198
+
199
+    // Pour chaque widget renseigné en param
200
+    widgets.each(function( index )
201
+    {
202
+      var widget = $(this);
203
+      var selectClone = selectWidgetClass.clone().addClass(classSelect);
204
+      widget.find(".title-widget").after(selectClone);
205
+      var value = widget.attr("data-widget-class");
206
+      if (typeof value != "undefined") {
207
+        selectClone.val(value);
208
+      }
209
+
210
+      // Au changement du select, meetre à jour le contenu du widget
211
+      selectClone.change(function(){
212
+        widget.attr("data-widget-class", selectClone.val());
213
+        udpateWidgetContent(widget);
214
+      });
215
+    });
216
+  }
217
+
218
+
219
+  /**
220
+   * Met à jour le contenu d'un widget
221
+   * @param dom widget Le widget à mettre à jour
222
+   */
223
+  function udpateWidgetContent(widget)
224
+  {
225
+    // On récupère la class du widget
226
+    var newValue = widget.attr("data-widget-class");
227
+
228
+    widget.getWidgetData = function(callback) {
229
+      getWidgetDatas(newValue, callback);
230
+    };
231
+
232
+    // On récupère le contenu de la class
233
+    getWidgetContent(newValue, function(result)
234
+    {
235
+      // Zone du contenu du widget
236
+      var contentWidget = widget.find(".content-widget");
237
+      // Bouton du menu du widget
238
+      var menuButtonWidget = widget.find(".menu-button-widget");
239
+      // Zone du menu du widget
240
+      var menuContenWidget = widget.find(".menu-content-widget");
241
+
242
+      // On met le resultat dans une div pour selectionner les différent élément à l'aide de find
243
+      resultHtml = $("<div>"+result.html+"</div>");
244
+
245
+      // On récupère le contenu
246
+      var content = resultHtml.find("content");
247
+      // On récupère le menu
248
+      var menu = resultHtml.find("menu");
249
+
250
+      // Mise en place du contenu
251
+      if (content.length) {
252
+        contentWidget.html(content.html());
253
+      }
254
+      // Mise en place du menu
255
+      if (menu.length) {
256
+        menuContenWidget.html(menu.html());
257
+      }
258
+
259
+      // Si on n'a pas de menu, masquer le bouton du menu, sinon l'afficher
260
+      if (!menu.length || $.trim(menu.html()) == "") {
261
+        menuButtonWidget.hide();
262
+      }
263
+      else {
264
+        menuButtonWidget.show();
265
+      }
266
+
267
+      // Initialiser les options
268
+      if (widget.attr("data-widget-options"))
269
+      {
270
+        var optionsDecode = $.parseJSON(widget.attr("data-widget-options"));
271
+        $.each(optionsDecode, function(index, value){
272
+          var input = widget.find("[data-option-name='"+index+"']");
273
+          if (input.length) {
274
+            if (input.is(':checkbox')) {
275
+                input.prop( "checked", value );
276
+            }
277
+            else {
278
+                input.val( value );
279
+            }
280
+          }
281
+        });
282
+      }
283
+
284
+      // Initialise les éléments devant prendre la place libre du parent
285
+      widget.find(".heightFreeSpace").each(function(index){
286
+        // L'élément
287
+        var elem = $(this);
288
+        initHeightFreeSpace(elem);
289
+      });
290
+
291
+      // Si on a une fonction d'initialisation renseigner l'executer
292
+      if (result.initJs != "") {
293
+        eval(result.initJs+"(widget)");
294
+      }
295
+
296
+      widget.find(".delete-widget-show").click(function(){
297
+        grid.removeWidget(widget);
298
+        saveDashboard();
299
+      });
300
+    });
301
+  }
302
+
303
+  /**
304
+   * Récupère la liste des class de widget
305
+   * @param function callback Fonction appelé à la fin de la récupération avec le resultat en paramètre
306
+   */
307
+  function getListWidgetClass(callback)
308
+  {
309
+    callback = callback || function(){};
310
+    var result = [];
311
+    $.ajax({
312
+      type: "GET",
313
+      url: actionGetListWidgetClass,
314
+      success: function(data, dataType)
315
+      {
316
+        if (typeof data.widgets != "undefined") {
317
+          result = data.widgets;
318
+        }
319
+        callback(result);
320
+      },
321
+      error: function(XMLHttpRequest, textStatus, errorThrown)
322
+      {
323
+        callback(result);
324
+      }
325
+    });
326
+  }
327
+
328
+  /**
329
+   * Récupère le contenue du widget en fonction de sa class
330
+   * @param string widgetClass Class du widget à charger
331
+   * @param function callback Fonction appelé à la fin de la récupération avec le resultat en paramètre
332
+   */
333
+  function getWidgetContent(widgetClass, callback)
334
+  {
335
+    callback = callback || function(){};
336
+    var result = "";
337
+    $.ajax({
338
+      type: "GET",
339
+      url: actionGetWidgetContent+"/"+widgetClass,
340
+      success: function(data, dataType)
341
+      {
342
+        if (typeof data != "undefined") {
343
+          result = data;
344
+        }
345
+        callback(result);
346
+      },
347
+      error: function(XMLHttpRequest, textStatus, errorThrown)
348
+      {
349
+        callback(result);
350
+      }
351
+    });
352
+  }
353
+
354
+  /**
355
+   * Récupère les données du widget en fonction de sa class
356
+   * @param string widgetClass Class du widget à charger
357
+   * @param function callback Fonction appelé à la fin de la récupération avec le resultat en paramètre
358
+   */
359
+  function getWidgetDatas(widgetClass, callback)
360
+  {
361
+    callback = callback || function(){};
362
+
363
+    let start = $('input[name="start"].hasDatepicker').datepicker("getDate");
364
+    let end = $('input[name="end"].hasDatepicker').datepicker('getDate');
365
+    var datas = {
366
+      idFormation: idFormation,
367
+      object: $('select[name="object"]').val(),
368
+      actor: $('select[name="actor"]').val(),
369
+      start: $.datepicker.formatDate('yy-m-d',start),
370
+      end:$.datepicker.formatDate('yy-m-d',end)
371
+    };
372
+
373
+    var result = "";
374
+    $.ajax({
375
+      type: "GET",
376
+      data: datas,
377
+      url: actionGetWidgetDatas+"/"+widgetClass,
378
+      success: function(data, dataType)
379
+      {
380
+        result = data;
381
+        callback(result);
382
+      },
383
+      error: function(XMLHttpRequest, textStatus, errorThrown)
384
+      {
385
+        callback(result);
386
+      }
387
+    });
388
+  }
389
+
390
+  /**
391
+   * Retourne la structure des widgets au format json
392
+   * @return string
393
+   */
394
+  function getGridDataSerialized()
395
+  {
396
+    this.serializedData = _.map($('.grid-stack > .grid-stack-item:visible'), function (el) {
397
+        el = $(el);
398
+        var node = el.data('_gridstack_node');
399
+
400
+        // Récupérer les options du widget
401
+        var options = {};
402
+        var optionsObjects = node.el.find('.option-widget');
403
+        optionsObjects.each(function(index, optionDom)
404
+        {
405
+          var optionObject = $(optionDom);
406
+
407
+          if (optionObject.is(':checkbox')) {
408
+            options[optionObject.attr('data-option-name')] = optionObject.is(':checked');
409
+          }
410
+          else {
411
+            options[optionObject.attr('data-option-name')] = optionObject.val();
412
+          }
413
+        });
414
+
415
+        return {
416
+            title: node.el.find("h2").html(),
417
+            x: node.x,
418
+            y: node.y,
419
+            width: node.width,
420
+            height: node.height,
421
+            widgetClass: node.el.attr("data-widget-class"),
422
+            options: options
423
+        };
424
+    }, this);
425
+    return JSON.stringify(this.serializedData, null, '');
426
+  };
427
+
428
+  /**
429
+   * Sauvegarde les données du dashboardId et affiche le retour sous forme d'alerte
430
+   * @param string action Url de la requête
431
+   * @param function callback Fonction appelé lors d'un retour avec comme valeur un booléen pour informé si tout c'est bien passé ou non.
432
+   **/
433
+  function saveDashboard(callback, showAlert)
434
+  {
435
+    callback = callback || function(){};
436
+    if (typeof showAlert == 'undefined') {
437
+      showAlert = true;
438
+    }
439
+
440
+    // Savegarde des données
441
+    var datas = {
442
+      structure: getGridDataSerialized(),
443
+      title: $("#dashboard-title").text()
444
+    };
445
+
446
+    $.ajax({
447
+      type: "POST",
448
+      url: actionSaveWidget,
449
+      data: datas,
450
+      success: function(data, dataType)
451
+      {
452
+        if (typeof data.success != "undefined") {
453
+          if (showAlert) {
454
+            addAlert("alert-success", data.success, true, 5000);
455
+          }
456
+          callback(true);
457
+        }
458
+        else if (typeof data.error != "undefined") {
459
+          if (showAlert) {
460
+            addAlert("alert-danger", data.error, true);
461
+          }
462
+          callback(false);
463
+        }
464
+      },
465
+      error: function(XMLHttpRequest, textStatus, errorThrown)
466
+      {
467
+        addAlert("alert-danger", errorThrown);
468
+      }
469
+    });
470
+  }
471
+}

+ 54
- 0
assets/shared/build/js/init.js View File

@@ -0,0 +1,54 @@
1
+$( document ).ready(function()
2
+{
3
+	// surcharge le tooltip d'origine
4
+	setTimeout(function(){ $.captain.initTooltip(); }, 10);
5
+
6
+	// initialise le moteur de recherche de formation
7
+	let input = $('input[name="mots_cles"]');
8
+
9
+	// correction appui touche entré => lance la recherche
10
+	input.on('keydown.xdsoft input.xdsoft cut.xdsoft paste.xdsoft', function(event)
11
+	{
12
+		let key = event.keyCode;
13
+		if (key == 13)
14
+		{
15
+			// stop l'événement du plugin
16
+			event.stopImmediatePropagation();
17
+
18
+			return true;
19
+		}
20
+	});
21
+
22
+	// initialise l'autocompletion
23
+	input.autocomplete(
24
+	{
25
+		titleKey: "proposition",
26
+		valueKey: "proposition",
27
+		minLength:2,
28
+		appendMethod:'replace',
29
+		source:[
30
+			function(query,callback)
31
+			{
32
+				$.captain.get('../search/autocomplete',{name:query},function(resp)
33
+				{
34
+					let items = resp.value;
35
+					callback(items);
36
+				});
37
+			}
38
+		],
39
+		// propositions déroulées
40
+		valid: function( value,query ){
41
+			return true;
42
+		},
43
+		// propositions du placeholder
44
+		equal: function( value,query ){
45
+			return true;
46
+		}
47
+	});
48
+
49
+	// ajout de la recherche à chaque changement du champ, car sinon il utilise toujours le même source
50
+	input.on('change keyup',function()
51
+	{
52
+		$(this).autocomplete('update');
53
+	});
54
+});

+ 1168
- 0
assets/shared/build/js/jquery.autocomplete.js
File diff suppressed because it is too large
View File


+ 187
- 0
assets/shared/build/js/menu-back-office.js View File

@@ -0,0 +1,187 @@
1
+document.addEventListener("DOMContentLoaded", function(event) {
2
+	var lastCursorX = -1;
3
+	var lastWidthMenu = 0;
4
+	// Si la fennetre est en mode moyen
5
+	var windowMd = false;
6
+
7
+
8
+	// Events tactiles
9
+	/*$(".space").bind("touchstart", function(event){
10
+		lastCursorX = event.changedTouches[0].pageX;
11
+		lastWidthMenu = $(".nave-space").width();
12
+		$(".space .nave-space-background, .space .nave-space").addClass("notransition").width(lastWidthMenu);
13
+	})
14
+	.bind("touchend", function(event){
15
+		lastCursorX = -1;
16
+		lastWidthMenu = $(".nave-space").width();
17
+		$(".space:not(.expanded) .nave-space-background, .space:not(.expanded) .nave-space").removeClass("notransition").css("width", "");
18
+		// Définir si on expend le menu ou non en fonction de sa position au ralaché.
19
+		if (lastWidthMenu > parseInt($(".nave-space").css("max-width"))/2) {
20
+			$(this).addClass("expanded");
21
+		}
22
+		else {
23
+			$(this).removeClass("expanded");
24
+		}
25
+	})
26
+	.bind("touchmove", function(event){
27
+		$(this).removeClass("expanded");
28
+		if (lastCursorX == -1) {
29
+			return false;
30
+		}
31
+		var diff = event.changedTouches[0].pageX - lastCursorX;
32
+		// Si on a un déplacement de plus de 10 pixels on concidère que l'utilisateur désire déplacer le menu
33
+		if (Math.abs(diff) > 10)
34
+		{
35
+			var newWidth = lastWidthMenu+diff;
36
+			$(".space:not(.expanded) .nave-space-background, .space:not(.expanded) .nave-space").width(newWidth);
37
+		}
38
+	});*/
39
+
40
+
41
+
42
+	// Fleche pour réduire agrandire le menu
43
+	$(".bouton-expande").click(function(event){
44
+		$(".space .nave-space-background, .space .nave-space").removeClass("notransition").css("width", "");
45
+		if ($(".space").hasClass("expanded")) {
46
+			expendMenu(false);
47
+			setPreference('expanded', 'no');
48
+		}
49
+		else {
50
+			expendMenu(true);
51
+			setPreference('expanded', 'yes');
52
+		}
53
+	});
54
+
55
+
56
+	$(".nave-space li").click(function(event){
57
+		//event.preventDefault();
58
+
59
+		var parentParent = $(this).parent().parent();
60
+		// Cas sous-menu
61
+		if (parentParent.is("li")) {
62
+			parentParent.addClass("sub-actif");
63
+		}
64
+
65
+		if (!$(this).find('li').length) {
66
+			// Si mobile
67
+			//$(".nave-space li.expanded").removeClass("expanded");
68
+			$(this).addClass("actif");
69
+			$(".nave-space li.actif").removeClass("actif");
70
+		}
71
+
72
+		//return false;
73
+	});
74
+
75
+	// Gestion de l'affichage des sous-menus
76
+	$(".nave-space li").each(function(id, elem){
77
+		var curElem = $(elem);
78
+		if (curElem.find('li').length)
79
+		{
80
+			curElem.find("a").first().click(function(){
81
+				if (curElem.hasClass("expanded"))
82
+				{
83
+					// Si le menu est réduit est qu'on clique sur un menu
84
+					// contenant un sous menu, ne pas réduire le sous menu
85
+					if (!$(".space").hasClass("expanded")) {
86
+						expendMenu(true);
87
+					}
88
+					else {
89
+						curElem.removeClass("expanded");
90
+					}
91
+				}
92
+				else
93
+				{
94
+					$(".nave-space li.expanded").removeClass("expanded");
95
+					expendMenu(true);
96
+					curElem.addClass("expanded");
97
+				}
98
+			});
99
+		}
100
+		else {
101
+			curElem.find("a").first().click(function(){
102
+				// Si mobile
103
+				//expendMenu(false);
104
+			});
105
+		}
106
+	});
107
+
108
+	// Réduire le menu quand on est en mode mobile et qu'on clique à coté
109
+	$(".content-space").after().click(function(){
110
+		if (windowMd) {
111
+			expendMenu(false);
112
+		}
113
+	});
114
+
115
+	/**
116
+	 * Agrandire ou réduire le menu
117
+	 */
118
+	function expendMenu(expend) {
119
+		if (expend) {
120
+			$(".space").addClass("expanded");
121
+		}
122
+		else {
123
+			$(".space").removeClass("expanded");
124
+		}
125
+	}
126
+
127
+
128
+	// Si la fennetre n'est pas assez grande pour afficher le menu complet, le menu sort du mode sticky
129
+	function testStiky()
130
+	{
131
+		if ($(".nave-space").height() > $(window).height()) {
132
+			 $(".nave-space").removeClass("position-sticky sticky-top");
133
+		}
134
+		else {
135
+			 $(".nave-space").addClass("position-sticky sticky-top");
136
+		}
137
+	}
138
+
139
+	// Test la taille de la fennetre pour adapter le menu
140
+	function testWindowsSize(init)
141
+	{
142
+		// Empécher l'animation
143
+		if (typeof init == 'undefined') {
144
+			init = false;
145
+		}
146
+
147
+		if (init) {
148
+			$(".nave-space-background, .nave-space").addClass("notransition");
149
+		}
150
+
151
+		if ($(window).width() < 991.88) {
152
+			if (!windowMd) {
153
+				expendMenu(false);
154
+				windowMd = true;
155
+			}
156
+		}
157
+		else {
158
+			if (windowMd) {
159
+				expendMenu(true);
160
+				windowMd = false;
161
+			}
162
+		}
163
+
164
+		if (init) {
165
+			setTimeout(function(){$(".nave-space-background, .nave-space").removeClass("notransition")}, 500);
166
+		}
167
+	}
168
+
169
+	testWindowsSize(true);
170
+	testStiky();
171
+	$( window ).resize(function() {
172
+	  testStiky();
173
+		testWindowsSize();
174
+	});
175
+
176
+});
177
+
178
+function setPreference(propriete, value)
179
+{
180
+	// requète ajax
181
+	let settings = {
182
+		action:$.turbolead.get("do__cpt_bo_register_ajax_set_preference"),
183
+		propriete:propriete,
184
+		value:value
185
+	};
186
+	$.captain.post($.turbolead.get("CPT_MODULE_URL"),settings,function(result){});
187
+}

+ 77
- 0
assets/shared/build/js/menu.js View File

@@ -0,0 +1,77 @@
1
+$( document ).ready(function() {
2
+  /* Gestion de la rétractation du menu (responsive) */
3
+  var body = $("body");
4
+
5
+  // Losqu'on clique sur le bouton pour afficher/masquer le menu
6
+  $(".main-menu-button").click(function(event){
7
+    event.preventDefault();
8
+    // Si le menu est visible on le rend non visible (appliqué au body pour facilement appliquer le CSS dessus et faire des tests)
9
+    // Sinon l'afficher  (en ajoutant la class main-menu-active)
10
+    if (body.hasClass("main-menu-active")) {
11
+      body.removeClass("main-menu-active");
12
+    }
13
+    else {
14
+      body.addClass("main-menu-active");
15
+    }
16
+
17
+    // Switcher les titres du bouton pour afficher l'action entre afficher et masquer le menu
18
+    var title = $(this).attr("title");
19
+    var titleActive = $(this).attr("data-title-active");
20
+    $(this).attr("data-title-active", title);
21
+    $(this).attr("title", titleActive);
22
+
23
+    return false;
24
+  });
25
+
26
+  var linkClick = false;
27
+  // Si on clique sur le menu sans cliquer sur un lien, stopper l'évent (pour ne pas masquer le menu)
28
+  $(".main-menu").click(function(event){
29
+    if (!linkClick)
30
+    {
31
+      event.preventDefault();
32
+      return false;
33
+    }
34
+    linkClick = false;
35
+    return true;
36
+  });
37
+  // Test pour informer qu'on a cliqué sur un lien du menu
38
+  $(".main-menu a").click(function(event){
39
+    linkClick = true;
40
+    return true;
41
+  });
42
+
43
+  // Si on clique sur le body et que le menu est affiché, on le masque
44
+  // (d'où le fait de stopper l'event quand on clique sur le menu pour ne pas le masquer à ce moment)
45
+  body.click(function(event){
46
+    if (body.hasClass("main-menu-active")) {
47
+      body.removeClass("main-menu-active");
48
+    }
49
+  });
50
+
51
+
52
+  /* Gestion des sous-menu */
53
+  $(".main-menu li.expend ul").each(function(){
54
+    // Afficher les sous-menus devant être déroulés
55
+    $(this).show();
56
+  });
57
+
58
+  $(".main-menu li").click(function(event){
59
+    var _this = $(this);
60
+    var ulChildren = _this.find("ul");
61
+    // Si le menu contien une liste (= sous menu) alors dérouler le sous menu ou l'enrouler
62
+    if (ulChildren.length) {
63
+      if (_this.hasClass("expend") && !linkClick)
64
+      {
65
+        _this.removeClass("expend");
66
+        // On stop l'animation courrant (si il y en a une). Petite animation de 300ms pour maequé le menu.
67
+        ulChildren.stop().hide(300);
68
+      }
69
+      else
70
+      {
71
+        _this.addClass("expend");
72
+        // On stop l'animation courrant (si il y en a une). Petite animation de 300ms pour afficher le menu.
73
+        ulChildren.stop().show(300);
74
+      }
75
+    }
76
+  });
77
+});

+ 30
- 0
assets/shared/build/js/ressources.js View File

@@ -0,0 +1,30 @@
1
+$( document ).ready(function() {
2
+  initTooltip();
3
+  initSlider();
4
+  initDatepicker();
5
+});
6
+
7
+function initDatepicker()
8
+{
9
+  $( ".datepicker" ).datepicker();
10
+}
11
+
12
+function initTooltip()
13
+{
14
+  $('[data-toggle="tooltip"]').tooltip();
15
+}
16
+
17
+function initSlider()
18
+{
19
+  $( "#slider-range" ).slider();
20
+  $( ".slider-range-d" ).slider({
21
+    range: true,
22
+    min: 0,
23
+    max: 500,
24
+    values: [ 75, 300 ],
25
+    slide: function( event, ui ) {
26
+      $( "#amount" ).val( "$" + ui.values[ 0 ] + " - $" + ui.values[ 1 ] );
27
+    }
28
+  });
29
+  $( "#amount" ).val( "$" + $( "#slider-range" ).slider( "values", 0 ) + " - $" + $( "#slider-range" ).slider( "values", 1 ) );
30
+}

+ 161
- 0
assets/shared/build/js/select_autocomplete.js View File

@@ -0,0 +1,161 @@
1
+$( document ).ready(function() {
2
+  $( ".combobox" ).combobox();
3
+});
4
+
5
+$.widget( "custom.combobox", {
6
+  _create: function() {
7
+    this.wrapper = $( "<span>" )
8
+      .addClass( "custom-combobox" )
9
+      .insertAfter( this.element );
10
+
11
+    this.element.hide();
12
+    this._createAutocomplete();
13
+    this._createShowAllButton();
14
+  },
15
+
16
+  _createAutocomplete: function() {
17
+    var selected = this.element.children( ":selected" ),
18
+      value = selected.val() ? selected.text() : "";
19
+
20
+      let savedAttributs = [];
21
+
22
+      let jqElement = this.element;
23
+      let wrapper = this.wrapper;
24
+      jqElement.children().each(function()
25
+	  {
26
+    	 $.each(this.attributes, function() {
27
+    		 let name = this.name;
28
+    		    // this.attributes is not a plain object, but an array
29
+    		    // of attribute nodes, which contain both the name and value
30
+    		    if(this.specified && name.indexOf('data-save') !== -1 && savedAttributs.indexOf(name) === -1)
31
+    		    {
32
+    		    	savedAttributs.push(name);
33
+
34
+    		    	 let input = $( "<input>", {type: "hidden", 'name': jqElement.attr("name")+"-" + name, value:value})
35
+    		         .appendTo(wrapper);
36
+    		    	 console.log(wrapper);
37
+    		    }
38
+    		  });
39
+	  });
40
+
41
+
42
+
43
+    this.input = $( "<input>" )
44
+      .appendTo( this.wrapper )
45
+      .val( value )
46
+      .attr( "title", "" )
47
+      .addClass( "custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left" )
48
+      .autocomplete({
49
+        delay: 0,
50
+        minLength: 0,
51
+        source: $.proxy( this, "_source" )
52
+      })
53
+      .tooltip({
54
+        classes: {
55
+          "ui-tooltip": "ui-state-highlight"
56
+        }
57
+      }).on('autocompletechange change', function () {
58
+    	  let option = jqElement.find('option:selected');
59
+    	  console.log(option.text());
60
+
61
+        $.each(savedAttributs,function(key,value)
62
+        {
63
+        	$('input[type="hidden"][name="' + jqElement.attr("name")+"-" +value + '"]').val(option.attr(value));
64
+        })
65
+      }).change();
66
+
67
+    this._on( this.input, {
68
+      autocompleteselect: function( event, ui ) {
69
+        ui.item.option.selected = true;
70
+        this._trigger( "select", event, {
71
+          item: ui.item.option
72
+        });
73
+      },
74
+
75
+      autocompletechange: "_removeIfInvalid"
76
+    });
77
+  },
78
+
79
+  _createShowAllButton: function() {
80
+    var input = this.input,
81
+      wasOpen = false;
82
+
83
+    $( "<a>" )
84
+      .attr( "tabIndex", -1 )
85
+      .appendTo( this.wrapper )
86
+      .button({
87
+        icons: {
88
+          primary: "ui-icon-triangle-1-s"
89
+        },
90
+        text: false
91
+      })
92
+      .removeClass( "ui-corner-all" )
93
+      .addClass( "custom-combobox-toggle ui-corner-right" )
94
+      .on( "mousedown", function() {
95
+        wasOpen = input.autocomplete( "widget" ).is( ":visible" );
96
+      })
97
+      .on( "click", function() {
98
+        input.trigger( "focus" );
99
+
100
+        // Close if already visible
101
+        if ( wasOpen ) {
102
+          return;
103
+        }
104
+
105
+        // Pass empty string as value to search for, displaying all results
106
+        input.autocomplete( "search", "" );
107
+      });
108
+  },
109
+
110
+  _source: function( request, response ) {
111
+    var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
112
+
113
+    response( this.element.find("option").map(function() {
114
+      var text = $( this ).text();
115
+      if ( this.value && ( !request.term || matcher.test(text) ) )
116
+        return {
117
+          label: text,
118
+          value: text,
119
+          option: this
120
+        };
121
+    }));
122
+  },
123
+
124
+  _removeIfInvalid: function( event, ui ) {
125
+
126
+    // Selected an item, nothing to do
127
+    if ( ui.item ) {
128
+      return;
129
+    }
130
+
131
+    // Search for a match (case-insensitive)
132
+    var value = this.input.val(),
133
+      valueLowerCase = value.toLowerCase(),
134
+      valid = false;
135
+    this.element.children( "option" ).each(function() {
136
+      if ( $( this ).text().toLowerCase() === valueLowerCase ) {
137
+        this.selected = valid = true;
138
+        return false;
139
+      }
140
+    });
141
+
142
+    // Found a match, nothing to do
143
+    if ( valid ) {
144
+      return;
145
+    }
146
+
147
+    // Remove invalid value
148
+    this.input
149
+      .val( "" )
150
+    this.element.val( "" );
151
+    this._delay(function() {
152
+      this.input.tooltip( "close" ).attr( "title", "" );
153
+    }, 2500 );
154
+    this.input.autocomplete( "instance" ).term = "";
155
+  },
156
+
157
+  _destroy: function() {
158
+    this.wrapper.remove();
159
+    this.element.show();
160
+  }
161
+});

+ 99
- 0
assets/shared/build/js/utility.js View File

@@ -0,0 +1,99 @@
1
+$( document ).ready(function() {
2
+  /**
3
+   * Initialise les éléments devant prendre la place libre du parent
4
+   */
5
+  window.initHeightFreeSpace = function(elem)
6
+  {
7
+    // Son parent
8
+    var parent = elem.parent();
9
+    // On attent un peu que la page se mette correctement en place
10
+    setTimeout(function(){
11
+      resizeHeightFreeSpace(elem);
12
+    }, 10);
13
+
14
+    // Si on reçois l'évent que l'élément doit recalculer sa taille on le refait
15
+    parent.bind("resizeHeightFreeSpace", function(){
16
+      resizeHeightFreeSpace(elem);
17
+    });
18
+  }
19
+
20
+  /* Fonction pour redimentionner un élément afiin qu'il prenne toute la placce disponible, en hauteur, du parent */
21
+  window.resizeHeightFreeSpace = function(elem)
22
+  {
23
+    // Le parent de l'élément
24
+    var parent = elem.parent();
25
+    // les enfants du parent
26
+    var children = parent.children();
27
+    // La taille du parent
28
+    var heightParent = parseFloat(parent.height());
29
+    // Le cumule de la taille des enfants
30
+    var heightChildren = 0;
31
+    children.each(function(index){
32
+      // On ajoute le cumule de la taille en hauteur des enfants, mais on ne prend pas en compte celui de l'élément que l'on veut redimentionner
33
+      if (!$(this).is(elem)) {
34
+        heightChildren += parseFloat($(this).height());
35
+        heightChildren += parseFloat($(this).css("marginTop"));
36
+        heightChildren += parseFloat($(this).css("marginBottom"));
37
+      }
38
+    });
39
+    // La hauteur disponnible = celle du parent moins le total de ses enfants hors l'élement
40
+    var height = heightParent - heightChildren;
41
+    // On applique la nouvelle taille à l'élément
42
+    elem.height(height+"px");
43
+  }
44
+
45
+  /* lorsque la fennetre est redimentionné */
46
+  $( window ).resize(function() {
47
+    // Emetre le souhait de recalculer la taille des éléments
48
+    $(".heightFreeSpace").parent().trigger('resizeHeightFreeSpace');
49
+  });
50
+  /* Losqu'un widget est redimentionné */
51
+  $('.grid-stack').on('gsresizestop', function(event, elem) {
52
+    // Emetre le souhait de recalculer la taille des éléments
53
+    $(".heightFreeSpace").parent().trigger('resizeHeightFreeSpace');
54
+  });
55
+
56
+  /* Pour chaque éléments ayant cette class "heightFreeSpace" on caclule dynamiquement
57
+   l'espace disponnible du parent pour que l'élement puisse prendre tout ce qui reste */
58
+  $(".heightFreeSpace").each(function(index){
59
+    // L'élément
60
+    var elem = $(this);
61
+    initHeightFreeSpace(elem);
62
+  });
63
+});
64
+
65
+
66
+/**
67
+ *  Ajoute une alert
68
+ *  @param string alertClass La class de l'alerte
69
+ *  @param string alertText le texte de l'alerte
70
+ *  @param bool replaceAlert supprimer les autres alertes ? Default : false
71
+ *  @param int lifeTime durée de vie de l'alert en ms       Default : 0
72
+ */
73
+window.addAlert = function(alertClass, alertText, replaceAlert, lifeTime)
74
+{
75
+  replaceAlert = replaceAlert||false;
76
+  lifeTime = lifeTime||0;
77
+
78
+  // Supprimer les autres alertes ?
79
+  if (replaceAlert) {
80
+    removeAlerts();
81
+  }
82
+
83
+  var alert = $("<div>", {class: "alert "+alertClass, role: "alert", text: alertText}).css({"display": "none", "min-width": "100%"}).insertAfter(".breadcrumb");
84
+  var close = $("<button>", {class: "close", type: "button", "data-dismiss": "alert", "aria-label": "Close"}).appendTo(alert);
85
+  $("<span>", {"aria-hidden": "true", text: "×"}).appendTo(close);
86
+  alert.show(300);
87
+
88
+  // Durée de vie de l'alerte
89
+  if (lifeTime) {
90
+    setTimeout(function(){alert.hide(300, function(){alert.remove();});}, lifeTime);
91
+  }
92
+}
93
+
94
+/**
95
+ *  Supprime les alertes
96
+ */
97
+window.removeAlerts = function() {
98
+  $(".alert").remove();
99
+}

+ 51
- 0
assets/shared/build/scss/bootstrap.scss View File

@@ -0,0 +1,51 @@
1
+// Import Boostrap form NPM
2
+// --------------------------------------------
3
+
4
+/* Boostrap variables overwrite and added theme variables */
5
+@import "settings";
6
+
7
+/* Path declaration is in config.yml */
8
+
9
+@import "~bootstrap/scss/functions";
10
+@import "~bootstrap/scss/variables";
11
+@import "~bootstrap/scss/mixins";
12
+@import "~bootstrap/scss/root";
13
+@import "~bootstrap/scss/reboot";
14
+@import "~bootstrap/scss/type";
15
+@import "~bootstrap/scss/images";
16
+//@import "~bootstrap/scsscode";
17
+@import "~bootstrap/scss/grid";
18
+@import "~bootstrap/scss/tables";
19
+@import "~bootstrap/scss/forms";
20
+@import "~bootstrap/scss/buttons";
21
+@import "~bootstrap/scss/transitions";
22
+@import "~bootstrap/scss/dropdown";
23
+@import "~bootstrap/scss/button-group";
24
+@import "~bootstrap/scss/input-group";
25
+@import "~bootstrap/scss/custom-forms";
26
+@import "~bootstrap/scss/nav";
27
+@import "~bootstrap/scss/navbar";
28
+@import "~bootstrap/scss/card";
29
+@import "~bootstrap/scss/breadcrumb";
30
+@import "~bootstrap/scss/pagination";
31
+@import "~bootstrap/scss/badge";
32
+//@import "~bootstrap/scssjumbotron";
33
+@import "~bootstrap/scss/alert";
34
+@import "~bootstrap/scss/progress";
35
+@import "~bootstrap/scss/media";
36
+@import "~bootstrap/scss/list-group";
37
+@import "~bootstrap/scss/close";
38
+@import "~bootstrap/scss/modal";
39
+@import "~bootstrap/scss/tooltip";
40
+@import "~bootstrap/scss/popover";
41
+//@import "~bootstrap/scsscarousel";
42
+@import "~bootstrap/scss/utilities";
43
+@import "~bootstrap/scss/print";
44
+
45
+// Overwrited Bootstrap components
46
+// --------------------------------------------
47
+@import "bootstrap/overwrited.scss";
48
+
49
+//  Etended Bootstrap components
50
+// --------------------------------------------
51
+@import "bootstrap/extended.scss";

+ 12
- 0
assets/shared/build/scss/bootstrap/extended.scss View File

@@ -0,0 +1,12 @@
1
+// Extended Boostrap
2
+// --------------------------------------------
3
+
4
+/* Extended boostrap */
5
+@import "extended/tabs";
6
+@import "extended/badge";
7
+@import "extended/form";
8
+@import "extended/button";
9
+@import "extended/table";
10
+@import "extended/dropdown";
11
+@import "extended/modal";
12
+@import "extended/global";

+ 28
- 0
assets/shared/build/scss/bootstrap/extended/badge.scss View File

@@ -0,0 +1,28 @@
1
+.badge-secondary {
2
+	color: rgba($black, .55);
3
+	background-color: rgba($black, .05);
4
+	border: none;
5
+}
6
+.badge-outilne-light {
7
+	color: $black;
8
+	background-color: $white;
9
+	border: 1px solid rgba($black, .2);
10
+}
11
+.badge-light {
12
+	color: rgba($black,1);
13
+	background-color: rgba($white,1);
14
+	border: none;
15
+}
16
+.badge-info {
17
+	color: theme-color("primary");
18
+}
19
+.like-badge {
20
+	white-space: normal;
21
+	display: inline-block;
22
+	padding: $badge-padding-y $badge-padding-x;
23
+	font-size: $badge-font-size;
24
+	font-weight: $badge-font-weight;
25
+	line-height: 1;
26
+	vertical-align: baseline;
27
+	border-radius: $badge-border-radius;
28
+}

+ 27
- 0
assets/shared/build/scss/bootstrap/extended/button.scss View File

@@ -0,0 +1,27 @@
1
+.btn.btn-secondary {
2
+	color: lighten($black,10%);
3
+	&:hover {
4
+		color: $black;
5
+		background-color: $white !important;
6
+	}
7
+}
8
+.btn-filter {
9
+	border-radius: 0;
10
+}
11
+
12
+.btn-link {
13
+	color: theme-color("primary");
14
+	background-color: transparent;
15
+}
16
+.btn-link-light {
17
+	color: $white;
18
+	&:hover {
19
+		color: $white;
20
+		text-decoration: underline;
21
+	}
22
+}
23
+
24
+.btn
25
+{
26
+	border-radius: 0;
27
+}

+ 19
- 0
assets/shared/build/scss/bootstrap/extended/dropdown.scss View File

@@ -0,0 +1,19 @@
1
+.dropdown-item.hover-disabled {
2
+	&:hover,
3
+	&:focus {
4
+		color: inherit;
5
+		background-color: inherit;
6
+	}
7
+}
8
+.dropdown-item {
9
+	white-space: normal;
10
+}
11
+.dropdown-dark {
12
+	width: 300px;
13
+	margin: 0 auto;
14
+	button {
15
+		width: 100%;
16
+		overflow: hidden;
17
+		text-overflow: ellipsis;
18
+	}
19
+}

+ 298
- 0
assets/shared/build/scss/bootstrap/extended/form.scss View File

@@ -0,0 +1,298 @@
1
+$form-step-width: 30px;
2
+$form-step-height: 30px;
3
+$form-step-radius: 100%;
4
+
5
+
6
+/*
7
+[1] Creat a class .like-label to uniformize form
8
+*/
9
+// [1]
10
+.like-label,
11
+label {
12
+	margin-bottom: .25rem;
13
+}
14
+
15
+// bouton sur mobile ou avec une valeur longue
16
+input[type="button"],
17
+input[type="submit"],
18
+button
19
+{
20
+	white-space: pre-wrap;
21
+}
22
+
23
+// form-separator
24
+.form-separator {
25
+	.form-step {
26
+		display: block;
27
+		height: $form-step-height;
28
+		width: $form-step-width;
29
+		border-radius: $form-step-width;
30
+		text-align: center;
31
+		line-height: $form-step-width;
32
+		color: $white;
33
+		background-color: theme-color("primary");
34
+	}
35
+}
36
+
37
+// form validation
38
+.form-with-validation {
39
+	padding-bottom: calc(68px + 2rem);
40
+}
41
+// Multiple state
42
+.form-validation {
43
+	position: fixed;
44
+	z-index: $zindex-form-validation;
45
+	bottom: 0;
46
+	left: 0;
47
+	width: 100%;
48
+}
49
+
50
+// Hide and show
51
+.form-validation-actions,
52
+.form-validation-states {
53
+	&.hide {
54
+		display: none;
55
+	}
56
+	&.show {
57
+		display: block;
58
+	}
59
+}
60
+
61
+.form-validation-states {
62
+	span {
63
+		border: 1px solid transparent;
64
+		padding: .375rem .75rem;
65
+		font-size: .875rem;
66
+		line-height: 1.5;
67
+		display: block;
68
+		text-align: center;
69
+	}
70
+	// by defaut, display only state defaut
71
+	&.show-state-default {
72
+		span:not(.state-default) {
73
+			display: none;
74
+		}
75
+		.state-default {
76
+			display: block;
77
+		}
78
+	}
79
+	&.show-state-success {
80
+		span:not(.state-success) {
81
+			display: none;
82
+		}
83
+		.state-success {
84
+			display: block;
85
+		}
86
+	}
87
+	&.show-state-in-progress {
88
+		span:not(.state-in-progress) {
89
+			display: none;
90
+		}
91
+		.state-in-progress {
92
+			display: block;
93
+		}
94
+	}
95
+}
96
+
97
+// OTHERS STATES
98
+.form-control,
99
+.custom-select {
100
+	color: $black;
101
+	.was-validated &:invalid,
102
+	&.is-invalid,
103
+	.was-validated &:valid,
104
+	&.is-valid {
105
+		border-color: $input-border-color;
106
+		&:focus {
107
+			border-color: $input-border-color;
108
+		}
109
+	}
110
+	.was-validated &:invalid,
111
+	&.is-invalid {
112
+		border-color: $input-border-color-error;
113
+		&:focus {
114
+			border-color: rgba($input-border-color-error,.5);
115
+		}
116
+	}
117
+}
118
+
119
+.form-control:focus,
120
+.custom-select:focus {
121
+	color: $black;
122
+}
123
+
124
+
125
+.custom-file-input {
126
+	.was-validated &:valid,
127
+	&.is-valid,
128
+	.was-validated &:invalid,
129
+	&.is-invalid {
130
+		 ~ .custom-file-label {
131
+			border-color: $input-border-color;
132
+
133
+			&::before {
134
+				border-color: inherit;
135
+			}
136
+		}
137
+		&:focus {
138
+			 ~ .custom-file-label {
139
+				box-shadow: none;
140
+			}
141
+		}
142
+	}
143
+}
144
+
145
+.custom-control-input {
146
+	color: $black !important;
147
+	.was-validated &:invalid,
148
+	&.is-invald,
149
+	.was-validated &:valid,
150
+	&.is-valid {
151
+		 ~ .custom-control-label {
152
+			color: $black;
153
+			&::before {
154
+				background-color: $custom-control-indicator-bg;
155
+			}
156
+		}
157
+		&:checked {
158
+			 ~ .custom-control-label::before {
159
+				background-color: theme-color("primary");
160
+			}
161
+		}
162
+		&:focus {
163
+			 ~ .custom-control-label::before {
164
+				box-shadow: none;
165
+			}
166
+		}
167
+	}
168
+}
169
+
170
+form > small,
171
+form .form-text {
172
+	font-size: 100% !important;
173
+}
174
+
175
+.invalid-feedback
176
+{
177
+	font-size: 90%;
178
+}
179
+
180
+
181
+/* Ajout de radio sous forme de switch */
182
+.cpt-switch {
183
+	border: 1px solid theme-color("primary");
184
+	display: table;
185
+	border-radius: 0.25rem;
186
+	overflow: hidden;
187
+
188
+	input[type="radio"] + label {
189
+		padding: 7px 15px;
190
+		border-right: 1px solid theme-color("primary");
191
+		margin: 0px;
192
+		cursor: pointer;
193
+	}
194
+	input[type="radio"] + label {
195
+		background-color:#FFF;
196
+		color:theme-color("primary");
197
+	}
198
+	input[type="radio"]:checked + label {
199
+		background-color:theme-color("primary");
200
+		color:#FFF;
201
+	}
202
+
203
+	input[type="radio"] + label.last {
204
+		border-right: 0px;
205
+	}
206
+
207
+	input[type="radio"] {
208
+		display:none;
209
+	}
210
+}
211
+
212
+
213
+/* Style spécifique pour le formulaire du profil utilisateur */
214
+.profil-info #nom {
215
+	border-radius: 0px 0.25rem 0.25rem 0px;
216
+}
217
+
218
+.profil-info #prenom {
219
+	height: 40px;
220
+}
221
+
222
+@include media-breakpoint-up(md) {
223
+	.profil-info #prenom {
224
+		border-radius: 0px 0.25rem 0.25rem 0px;
225
+		border-left: none;
226
+	}
227
+}
228
+
229
+
230
+
231
+/* Style spécifique pour le formulaire des demandes pour rejoindre une entreprise */
232
+#demande_accepter .done .step-circle,
233
+#demande_refuser .done .step-circle
234
+{
235
+	cursor: pointer;
236
+}
237
+
238
+#demande-avatar
239
+{
240
+	font-size: 7em;
241
+	
242
+	padding: 0px;
243
+}
244
+
245
+.fiche-personne
246
+{
247
+	.roles
248
+	{
249
+		margin: 0.2rem;
250
+		display: flex;
251
+		flex-wrap: wrap;
252
+		justify-content: center;
253
+		div
254
+		{
255
+			margin: 0.2rem;
256
+		}
257
+		
258
+	}
259
+	background-color: #F5F5F5;
260
+	width: 100%;
261
+	
262
+	@include media-breakpoint-up(md) {
263
+		min-width: 300px;
264
+		max-width: 300px;
265
+	}
266
+	
267
+	img
268
+	{
269
+		margin-left: auto;
270
+		margin-right: auto;
271
+		
272
+		width: 50px;
273
+		@include media-breakpoint-up(md) {
274
+			width: 100px;
275
+		}
276
+	}
277
+}
278
+
279
+.fiche-demande
280
+{
281
+	background-color: #F5F5F5;
282
+	margin: 0 auto;
283
+	
284
+	div
285
+	{
286
+		text-overflow: ellipsis;
287
+	}
288
+	img
289
+	{
290
+		margin-left: auto;
291
+		margin-right: auto;
292
+		
293
+		width: 50px;
294
+		@include media-breakpoint-up(md) {
295
+			width: 100px;
296
+		}
297
+	}
298
+}

+ 53
- 0
assets/shared/build/scss/bootstrap/extended/global.scss View File

@@ -0,0 +1,53 @@
1
+
2
+/* Liste à colonne */
3
+@each $breakpoint in map-keys($grid-breakpoints) {
4
+	@include media-breakpoint-up($breakpoint) {
5
+		$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
6
+		@for $i from 1 through 4 {
7
+		  .w#{$infix}-#{$i*25} {
8
+				width: $i*25% !important;
9
+			}
10
+		}
11
+	}
12
+}
13
+
14
+/* hauteur */
15
+@each $breakpoint in map-keys($grid-breakpoints) {
16
+	@include media-breakpoint-up($breakpoint) {
17
+		$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
18
+		@for $i from 1 through 20 {
19
+		  .h-px#{$infix}-#{$i*50} {
20
+				height: $i*50px !important;
21
+			}
22
+		  .h-min-px#{$infix}-#{$i*50} {
23
+				min-height: $i*50px !important;
24
+			}
25
+		}
26
+	}
27
+}
28
+
29
+@each $breakpoint in map-keys($grid-breakpoints) {
30
+	@include media-breakpoint-up($breakpoint) {
31
+		$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
32
+		@for $i from 1 through 10 {
33
+		  .w-px#{$infix}-#{$i*50} {
34
+				width: $i*50px !important;
35
+			}
36
+		  .w-max-px#{$infix}-#{$i*50} {
37
+				max-width: $i*50px !important;
38
+				width: 100% !important;
39
+			}
40
+		}
41
+	}
42
+}
43
+
44
+
45
+.clear-both {
46
+  clear: both;
47
+}
48
+
49
+
50
+.text-overflow-ellipsis {
51
+	overflow: hidden;
52
+	text-overflow: ellipsis;
53
+}

+ 84
- 0
assets/shared/build/scss/bootstrap/extended/modal.scss View File

@@ -0,0 +1,84 @@
1
+.modal-head
2
+{
3
+	width: 100%;
4
+}
5
+.modal-head .close
6
+{
7
+	padding: 0px;
8
+
9
+	//-webkit-mask: url('../images/icones/close.svg') no-repeat 50% 50%;
10
+ 	// mask: url('../images/icones/close.svg') no-repeat 50% 50%;
11
+  	//-webkit-mask-size: cover;
12
+  	//mask-size: cover;
13
+ 	// background-color: red;
14
+  
15
+	//filter: hue-rotate(220deg) saturate(5);
16
+	//-webkit-mask-image:url('../images/icones/close.svg');
17
+	//mask-image: url('../images/icones/close.svg');
18
+	//background-color: rgba(255,255,255);
19
+	
20
+	//background-image: url('../images/icones/close.svg');
21
+	
22
+	opacity: 1;
23
+	
24
+	position: absolute;
25
+	
26
+	width: 50px;
27
+	height: 50px;
28
+	
29
+	top: -26px;
30
+	right: -26px;
31
+	
32
+	border-radius: 50%;
33
+	
34
+	vertical-align: top;
35
+	
36
+	opacity: 1;
37
+	z-index: 100;
38
+}
39
+
40
+.modal-head .close:hover
41
+{
42
+	//background: url('../images/icones/close_hover.svg');
43
+}
44
+
45
+.modal-content
46
+{
47
+	display: block;
48
+
49
+	border: solid 5px #FFF;
50
+	border-radius: 0px;
51
+}
52
+.modal-body
53
+{
54
+	border: none;
55
+	padding: 0.9rem;
56
+}
57
+
58
+.modal-dialog
59
+{
60
+	margin-left: 1em;
61
+	margin-top: 1em;
62
+	margin-right: 1.2em;
63
+	
64
+	@include media-breakpoint-up(sm) {
65
+		margin: 1em auto;
66
+		padding: 1.2em;
67
+	}
68
+	
69
+	@include media-breakpoint-up(lg) {
70
+		top: 0px;
71
+		min-height: 100vh;
72
+		margin-top: 0;
73
+		margin-bottom:0;
74
+	}
75
+}
76
+
77
+.modal-header
78
+{
79
+	width: calc(100%);
80
+	border: none;
81
+	height: auto;
82
+	padding: 0px;
83
+	margin: 0px;
84
+}

+ 9
- 0
assets/shared/build/scss/bootstrap/extended/table.scss View File

@@ -0,0 +1,9 @@
1
+.table thead th {
2
+	border-bottom: none;
3
+}
4
+.table .header {
5
+	background-color: rgba(theme-color("primary"),.05);
6
+}
7
+.table td {
8
+	vertical-align: middle;
9
+}

+ 36
- 0
assets/shared/build/scss/bootstrap/extended/tabs.scss View File

@@ -0,0 +1,36 @@
1
+// TABS
2
+.tab-content {
3
+	position: relative;
4
+	margin-top: 1rem;
5
+}
6
+
7
+// tabs animation
8
+.tab-content > .tab-pane.slide-left,
9
+.tab-content > .tab-pane.slide-right {
10
+	transition: all .3s ease !important;
11
+}
12
+.tab-content > .tab-pane.slide-left.sliding,
13
+.tab-content > .tab-pane.slide-right.sliding {
14
+	opacity: 0 !important;
15
+}
16
+.tab-content > .tab-pane.slide-left.active,
17
+.tab-content > .tab-pane.slide-right.active {
18
+	opacity: 1;
19
+	transform: translate3d(0, 0, 0);
20
+}
21
+.tab-content > .tab-pane.slide-left.sliding {
22
+	transform: translate3d(10%, 0, 0) !important;
23
+}
24
+.tab-content > .tab-pane.slide-right.sliding {
25
+	transform: translate3d(-10%, 0, 0) !important;
26
+}
27
+
28
+
29
+#tab-pane-drh,
30
+#tab-pane-of {
31
+	.row {
32
+		padding-top: 3rem;
33
+		padding-bottom: 3rem;
34
+		min-height: 25vh !important;
35
+	}
36 <