Browse Source

First commit

Victor Hernandez 4 years ago
commit
e24c9e7c11
100 changed files with 7049 additions and 0 deletions
  1. 29
    0
      card.html
  2. 764
    0
      css/style.css
  3. 2
    0
      css/style.min.css
  4. 39
    0
      error.php
  5. 10
    0
      footer.php
  6. 141
    0
      funciones.php
  7. 117
    0
      header.php
  8. 374
    0
      home.php
  9. BIN
      img/.DS_Store
  10. BIN
      img/CDCC.png
  11. BIN
      img/EMA-banner1.png
  12. BIN
      img/EMA-banner2.png
  13. BIN
      img/andrew-neel-cckf4TsHAuw-unsplash.jpeg
  14. BIN
      img/carlos.jpg
  15. BIN
      img/carlos_original.jpg
  16. BIN
      img/coralys.jpg
  17. BIN
      img/coralys_original.jpg
  18. BIN
      img/cytonn-photography-GJao3ZTX9gU-unsplash.jpeg
  19. 6
    0
      img/google.svg
  20. BIN
      img/hector.jpg
  21. BIN
      img/hector_original.jpg
  22. BIN
      img/ivonne.png
  23. BIN
      img/juan.png
  24. BIN
      img/juan_original.png
  25. BIN
      img/pen_1024x1024.png
  26. BIN
      img/pen_800x800.png
  27. BIN
      img/tatiana.jpg
  28. BIN
      img/tatiana_original.jpg
  29. BIN
      img/victor.jpg
  30. 105
    0
      index.php
  31. 51
    0
      js/editQuestion.js
  32. 172
    0
      js/handleSubmit.js
  33. 77
    0
      js/home.js
  34. 39
    0
      js/index.js
  35. 146
    0
      js/main.js
  36. BIN
      js/nameOfTheQuestionnair.xlsx
  37. 242
    0
      js/viewExperience.js
  38. 5
    0
      js/viewMoment.js
  39. 5
    0
      js/viewQuestionnaire.js
  40. BIN
      nameOfTheQuestionnair.xlsx
  41. 342
    0
      old_code/bankOfQuestions.php
  42. 240
    0
      old_code/categories.php
  43. 6
    0
      old_code/conection.php
  44. 37
    0
      old_code/deleteQuestion.php
  45. 30
    0
      old_code/deleteQuestionQuestionnaire.php
  46. 37
    0
      old_code/deleteQuestionnaire.php
  47. 30
    0
      old_code/deleteQuestionnaireExperience.php
  48. 98
    0
      old_code/editExperience.php
  49. 59
    0
      old_code/insertQuestionnaire.php
  50. 32
    0
      old_code/insertQuestionnaireExperience.php
  51. 116
    0
      old_code/newExperience.php
  52. 59
    0
      old_code/subquestionnaires.php
  53. 57
    0
      old_code/updateQuestionnaire.php
  54. 145
    0
      old_code/viewQuestionnaireExperience.php
  55. 67
    0
      processes/addExistingQuestionToMoment.php
  56. 122
    0
      processes/callback.php
  57. 13
    0
      processes/checkLogin.php
  58. 20
    0
      processes/config.php
  59. 25
    0
      processes/dbh.inc.php
  60. 102
    0
      processes/deleteExperience.php
  61. 68
    0
      processes/deleteMoment.php
  62. 77
    0
      processes/deleteQuestion.php
  63. 110
    0
      processes/deleteQuestionnaire.php
  64. 118
    0
      processes/duplicateQuestionnaire.php
  65. 77
    0
      processes/export.php
  66. 20
    0
      processes/fullcalendar/LICENSE.txt
  67. 10
    0
      processes/fullcalendar/README.md
  68. 109
    0
      processes/fullcalendar/examples/background-events.html
  69. 109
    0
      processes/fullcalendar/examples/daygrid-views.html
  70. 75
    0
      processes/fullcalendar/examples/external-dragging-2cals.html
  71. 149
    0
      processes/fullcalendar/examples/external-dragging-builtin.html
  72. 129
    0
      processes/fullcalendar/examples/full-height.html
  73. 86
    0
      processes/fullcalendar/examples/google-calendar.html
  74. 141
    0
      processes/fullcalendar/examples/js/theme-chooser.js
  75. 93
    0
      processes/fullcalendar/examples/json.html
  76. 56
    0
      processes/fullcalendar/examples/json/events.json
  77. 118
    0
      processes/fullcalendar/examples/list-views.html
  78. 152
    0
      processes/fullcalendar/examples/locales.html
  79. 103
    0
      processes/fullcalendar/examples/month-view.html
  80. 50
    0
      processes/fullcalendar/examples/php/get-events.php
  81. 9
    0
      processes/fullcalendar/examples/php/get-time-zones.php
  82. 130
    0
      processes/fullcalendar/examples/php/utils.php
  83. 73
    0
      processes/fullcalendar/examples/rrule.html
  84. 125
    0
      processes/fullcalendar/examples/selectable.html
  85. 215
    0
      processes/fullcalendar/examples/theming.html
  86. 145
    0
      processes/fullcalendar/examples/time-zones.html
  87. 113
    0
      processes/fullcalendar/examples/timegrid-views.html
  88. 118
    0
      processes/fullcalendar/examples/week-numbers.html
  89. BIN
      processes/fullcalendar/fullcalendar-4.3.1.zip
  90. 20
    0
      processes/fullcalendar/packages/bootstrap/LICENSE.txt
  91. 8
    0
      processes/fullcalendar/packages/bootstrap/README.md
  92. 36
    0
      processes/fullcalendar/packages/bootstrap/main.css
  93. 12
    0
      processes/fullcalendar/packages/bootstrap/main.d.ts
  94. 83
    0
      processes/fullcalendar/packages/bootstrap/main.esm.js
  95. 91
    0
      processes/fullcalendar/packages/bootstrap/main.js
  96. 1
    0
      processes/fullcalendar/packages/bootstrap/main.min.css
  97. 6
    0
      processes/fullcalendar/packages/bootstrap/main.min.js
  98. 33
    0
      processes/fullcalendar/packages/bootstrap/package.json
  99. 20
    0
      processes/fullcalendar/packages/core/LICENSE.txt
  100. 0
    0
      processes/fullcalendar/packages/core/README.md

+ 29
- 0
card.html View File

@@ -0,0 +1,29 @@
1
+
2
+    	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
3
+  					
4
+  			<br><br><br>		
5
+  			
6
+  			<div class="row">
7
+  				<div class="col-sm-offset-1 col-sm-3">
8
+  					
9
+					<div class="row">
10
+						<div class="col">
11
+							<div class="thumbnail">
12
+								<div class="caption">
13
+									<h4 class="pannel-heading text-center">Tips on Milestones</h4>
14
+									<hr>
15
+									<ul>
16
+										<li>These are the milestones of the students involved in this experience.</li>
17
+										<br>
18
+										<li>Once your moments have been answered you can track the impact these milestones had on the students' answers, if any.</li>
19
+										<br>
20
+										<li>You can create new milestones with the plus button.</li>
21
+									</ul>
22
+								</div>
23
+							</div>
24
+						</div>
25
+					</div>
26
+  						
27
+  				</div><!--col-sm-4-->
28
+  			</div><!--row-->
29
+			

+ 764
- 0
css/style.css View File

@@ -0,0 +1,764 @@
1
+@import url(https://fonts.googleapis.com/css?family=Roboto);
2
+/* GLOBALS */
3
+body {
4
+  margin: 0;
5
+  font-family: Avenir, Helvetica, sans-serif;
6
+  line-height: 1.5;
7
+}
8
+
9
+a, a:hover, a:focus, a:active {
10
+  text-decoration: none;
11
+  color: #fff;
12
+}
13
+
14
+.modal {
15
+  overflow-y: auto;
16
+}
17
+
18
+/* HEADER */
19
+#main-header {
20
+  min-height: 8rem;
21
+  display: -webkit-box;
22
+  display: -ms-flexbox;
23
+  display: flex;
24
+  -webkit-box-orient: horizontal;
25
+  -webkit-box-direction: normal;
26
+      -ms-flex-direction: row;
27
+          flex-direction: row;
28
+  -webkit-box-pack: justify;
29
+      -ms-flex-pack: justify;
30
+          justify-content: space-between;
31
+  -webkit-box-align: center;
32
+      -ms-flex-align: center;
33
+          align-items: center;
34
+  position: fixed;
35
+  top: 0;
36
+  left: 0;
37
+  right: 0;
38
+  z-index: 2;
39
+  background: rgba(255, 255, 255, 0.7);
40
+  -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.2);
41
+          box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.2);
42
+  -webkit-backdrop-filter: blur(10px);
43
+          backdrop-filter: blur(10px);
44
+}
45
+
46
+#logo {
47
+  font-size: 1.7em;
48
+  text-decoration: none;
49
+  color: #606060;
50
+  height: initial;
51
+  padding: 0.3em 1em;
52
+  text-align: center;
53
+  display: -webkit-box;
54
+  display: -ms-flexbox;
55
+  display: flex;
56
+  -webkit-box-orient: horizontal;
57
+  -webkit-box-direction: normal;
58
+      -ms-flex-direction: row;
59
+          flex-direction: row;
60
+  -webkit-box-pack: justify;
61
+      -ms-flex-pack: justify;
62
+          justify-content: space-between;
63
+  -webkit-box-align: center;
64
+      -ms-flex-align: center;
65
+          align-items: center;
66
+  width: 155px;
67
+}
68
+
69
+#logo:hover,
70
+#logo:active,
71
+#logo:focus {
72
+  color: #333;
73
+}
74
+
75
+#account {
76
+  padding: 0.3em 1em;
77
+}
78
+
79
+.nav-link {
80
+  font-size: 1.2em;
81
+  padding: calc(1em / 2) 1em;
82
+  text-decoration: none;
83
+  color: #333;
84
+  position: relative;
85
+  -webkit-transition: color 150ms ease-in-out;
86
+  transition: color 150ms ease-in-out;
87
+}
88
+
89
+.nav-link:after {
90
+  content: '';
91
+  position: absolute;
92
+  bottom: 0;
93
+  height: 2px;
94
+  left: 1em;
95
+  right: 1em;
96
+  background-color: #606060;
97
+  -webkit-transform: scaleX(0);
98
+          transform: scaleX(0);
99
+  -webkit-transition: -webkit-transform 150ms ease-in-out;
100
+  transition: -webkit-transform 150ms ease-in-out;
101
+  transition: transform 150ms ease-in-out;
102
+  transition: transform 150ms ease-in-out, -webkit-transform 150ms ease-in-out;
103
+}
104
+
105
+.nav-link:hover::after,
106
+.nav-link:focus::after,
107
+.nav-link:active::after {
108
+  -webkit-transform: scaleX(1);
109
+          transform: scaleX(1);
110
+}
111
+
112
+.nav-link:hover,
113
+.nav-link:focus,
114
+.nav-link:active {
115
+  color: #606060;
116
+}
117
+
118
+.sign-out {
119
+  padding: 0.5em 1em;
120
+  background-color: #217ce4;
121
+  color: #fff;
122
+  text-decoration: none;
123
+  -webkit-box-shadow: 1px 1px 2px 1px rgba(0, 0, 0, 0.05), -1px 1px 2px 1px rgba(0, 0, 0, 0.02);
124
+          box-shadow: 1px 1px 2px 1px rgba(0, 0, 0, 0.05), -1px 1px 2px 1px rgba(0, 0, 0, 0.02);
125
+  -webkit-transition-property: background-color, -webkit-box-shadow;
126
+  transition-property: background-color, -webkit-box-shadow;
127
+  transition-property: background-color, box-shadow;
128
+  transition-property: background-color, box-shadow, -webkit-box-shadow;
129
+  -webkit-transition-duration: 150ms;
130
+          transition-duration: 150ms;
131
+  -webkit-transition-timing-function: ease-in-out;
132
+          transition-timing-function: ease-in-out;
133
+}
134
+
135
+.sign-out:hover,
136
+.sign-out:focus,
137
+.sign-out:active {
138
+  background-color: #3d88df;
139
+  -webkit-box-shadow: 1px 4px 5px 1px rgba(0, 0, 0, 0.1);
140
+          box-shadow: 1px 4px 5px 1px rgba(0, 0, 0, 0.1);
141
+}
142
+
143
+/* GOOGLE BUTTON */
144
+.google-button {
145
+  height: 40px;
146
+  border-width: 0;
147
+  background: #fff;
148
+  color: #737373;
149
+  border-radius: none;
150
+  white-space: nowrap;
151
+  -webkit-box-shadow: 1px 1px 2px 1px rgba(0, 0, 0, 0.05), -1px 1px 2px 1px rgba(0, 0, 0, 0.02);
152
+          box-shadow: 1px 1px 2px 1px rgba(0, 0, 0, 0.05), -1px 1px 2px 1px rgba(0, 0, 0, 0.02);
153
+  -webkit-transition-property: background-color, -webkit-box-shadow;
154
+  transition-property: background-color, -webkit-box-shadow;
155
+  transition-property: background-color, box-shadow;
156
+  transition-property: background-color, box-shadow, -webkit-box-shadow;
157
+  -webkit-transition-duration: 150ms;
158
+          transition-duration: 150ms;
159
+  -webkit-transition-timing-function: ease-in-out;
160
+          transition-timing-function: ease-in-out;
161
+  display: -webkit-box;
162
+  display: -ms-flexbox;
163
+  display: flex;
164
+  -ms-flex-pack: distribute;
165
+      justify-content: space-around;
166
+  -webkit-box-align: center;
167
+      -ms-flex-align: center;
168
+          align-items: center;
169
+}
170
+
171
+.google-button:focus,
172
+.google-button:hover {
173
+  -webkit-box-shadow: 1px 4px 5px 1px rgba(0, 0, 0, 0.1);
174
+          box-shadow: 1px 4px 5px 1px rgba(0, 0, 0, 0.1);
175
+  cursor: pointer;
176
+}
177
+
178
+.google-button:active {
179
+  background-color: #e5e5e5;
180
+  -webkit-box-shadow: none;
181
+          box-shadow: none;
182
+  -webkit-transition-duration: 10ms;
183
+          transition-duration: 10ms;
184
+}
185
+
186
+.google-button__icon {
187
+  margin: 5px;
188
+  width: 18px;
189
+  height: 18px;
190
+}
191
+
192
+.google-button__text {
193
+  padding: 0 12px;
194
+  font-size: 14px;
195
+  font-family: 'Roboto', Arial, sans-serif;
196
+}
197
+
198
+/* (EXPERIENCES PAGE) MAIN SECTION */
199
+#experience-main {
200
+  background-color: #606060;
201
+  display: -webkit-box;
202
+  display: -ms-flexbox;
203
+  display: flex;
204
+  -webkit-box-orient: vertical;
205
+  -webkit-box-direction: normal;
206
+      -ms-flex-direction: column;
207
+          flex-direction: column;
208
+  min-height: calc(90vh - 8rem - 10vh);
209
+  padding: 3em 5em;
210
+}
211
+
212
+#experience-main h3 {
213
+  color: #606060;
214
+}
215
+
216
+.experience-lead {
217
+  color: #fff;
218
+  font-size: 2em;
219
+  margin: 0 0 2em 0;
220
+  border-bottom: #fff;
221
+  border-bottom-width: 3px;
222
+  border-bottom-style: solid;
223
+}
224
+
225
+#experience-content {
226
+  display: -ms-grid;
227
+  display: grid;
228
+  grid-gap: 2em;
229
+  -ms-grid-columns: 1fr 1fr 1fr;
230
+      grid-template-columns: 1fr 1fr 1fr;
231
+  margin-bottom: 1em;
232
+}
233
+
234
+.grid-box {
235
+  background-color: #fff;
236
+  height: 15em;
237
+  width: 15em;
238
+  border-radius: 15px;
239
+  -webkit-box-shadow: 1px 1px 3px 1px #333;
240
+          box-shadow: 1px 1px 3px 1px #333;
241
+  -ms-grid-column-align: center;
242
+      justify-self: center;
243
+  padding: 3em 2em;
244
+  position: relative;
245
+  -webkit-transition: -webkit-transform 150ms ease-in-out;
246
+  transition: -webkit-transform 150ms ease-in-out;
247
+  transition: transform 150ms ease-in-out;
248
+  transition: transform 150ms ease-in-out, -webkit-transform 150ms ease-in-out;
249
+  cursor: pointer;
250
+}
251
+
252
+.grid-box .box-title {
253
+  color: #333;
254
+  font-size: 1.5em;
255
+  margin-bottom: 2em;
256
+}
257
+
258
+.grid-box .box-dates {
259
+  display: -webkit-box;
260
+  display: -ms-flexbox;
261
+  display: flex;
262
+  -webkit-box-orient: vertical;
263
+  -webkit-box-direction: normal;
264
+      -ms-flex-direction: column;
265
+          flex-direction: column;
266
+  color: #606060;
267
+  -webkit-box-pack: justify;
268
+      -ms-flex-pack: justify;
269
+          justify-content: space-between;
270
+}
271
+
272
+.grid-box .box-weeks {
273
+  color: #606060;
274
+}
275
+
276
+.grid-box .box-edit {
277
+  position: absolute;
278
+  right: 0;
279
+  bottom: 0;
280
+  font-size: 1.5em;
281
+  background-image: -webkit-gradient(linear, left top, right bottom, from(#fff), to(#e4e1d7));
282
+  background-image: linear-gradient(to bottom right, #fff, #e4e1d7);
283
+  /*radial-gradient(circle 200px at bottom right, #fff, $background-color); */
284
+  height: 2em;
285
+  width: 2em;
286
+  display: -webkit-box;
287
+  display: -ms-flexbox;
288
+  display: flex;
289
+  -webkit-box-align: center;
290
+      -ms-flex-align: center;
291
+          align-items: center;
292
+  -webkit-box-pack: center;
293
+      -ms-flex-pack: center;
294
+          justify-content: center;
295
+  border-bottom-right-radius: 15px;
296
+}
297
+
298
+.grid-box .box-edit a {
299
+  color: #217ce4;
300
+}
301
+
302
+.grid-box .box-weeks.warning {
303
+  color: #c83631;
304
+  font-size: 1.1em;
305
+}
306
+
307
+.grid-box#new-experience {
308
+  display: -webkit-box;
309
+  display: -ms-flexbox;
310
+  display: flex;
311
+  -webkit-box-orient: vertical;
312
+  -webkit-box-direction: normal;
313
+      -ms-flex-direction: column;
314
+          flex-direction: column;
315
+  -ms-flex-pack: distribute;
316
+      justify-content: space-around;
317
+  -webkit-box-align: center;
318
+      -ms-flex-align: center;
319
+          align-items: center;
320
+}
321
+
322
+.grid-box#new-experience span {
323
+  color: #217ce4;
324
+  font-size: 5em;
325
+}
326
+
327
+.grid-box#new-experience h4 {
328
+  color: #606060;
329
+  margin: 0;
330
+}
331
+
332
+.grid-box:hover {
333
+  -webkit-transform: translateY(-5px);
334
+          transform: translateY(-5px);
335
+}
336
+
337
+/* WELCOME SECTION */
338
+#welcome {
339
+  margin-top: 8rem;
340
+  min-height: 25rem;
341
+  background: #333 url(../img/cytonn-photography-GJao3ZTX9gU-unsplash.jpeg) no-repeat top left;
342
+  background-size: cover;
343
+  position: relative;
344
+  background-blend-mode: screen;
345
+  border-bottom: 3px solid #f0c873;
346
+}
347
+
348
+#welcome-text {
349
+  position: absolute;
350
+  bottom: 2.6rem;
351
+  left: 5vw;
352
+  width: 30%;
353
+  display: -webkit-box;
354
+  display: -ms-flexbox;
355
+  display: flex;
356
+  -webkit-box-orient: vertical;
357
+  -webkit-box-direction: normal;
358
+      -ms-flex-direction: column;
359
+          flex-direction: column;
360
+}
361
+
362
+#welcome-image {
363
+  height: 75px;
364
+  width: 75px;
365
+  border-radius: 50%;
366
+  margin-bottom: 15px;
367
+  border: 2px solid #fff;
368
+  -webkit-box-shadow: 1px 1px 10px 0px #222;
369
+          box-shadow: 1px 1px 10px 0px #222;
370
+}
371
+
372
+#welcome-user {
373
+  color: #fff;
374
+  text-shadow: 1px 1px 5px #222;
375
+  font-size: 3rem;
376
+  margin: 0;
377
+}
378
+
379
+/* (LOGIN PAGE) MAIN SECTION */
380
+#home-main {
381
+  background-color: #606060;
382
+  display: -webkit-box;
383
+  display: -ms-flexbox;
384
+  display: flex;
385
+  -webkit-box-orient: horizontal;
386
+  -webkit-box-direction: normal;
387
+      -ms-flex-direction: row;
388
+          flex-direction: row;
389
+  min-height: calc(80vh - 8rem - 10vh);
390
+  padding: 2.5em 2em;
391
+  color: #fff;
392
+}
393
+
394
+#home-main h3 {
395
+  font-size: 1.7em;
396
+  font-weight: 900;
397
+}
398
+
399
+#home-main p {
400
+  font-size: 1.3em;
401
+}
402
+
403
+#main-sidebar {
404
+  -webkit-box-flex: 1;
405
+      -ms-flex: 1;
406
+          flex: 1;
407
+  padding-left: 2em;
408
+}
409
+
410
+#main-sidebar h3 {
411
+  font-weight: 700;
412
+}
413
+
414
+#main-sidebar ul {
415
+  margin: 0;
416
+  padding-left: 1em;
417
+}
418
+
419
+#main-sidebar li {
420
+  list-style: none;
421
+  font-size: 1.3em;
422
+}
423
+
424
+#main-sidebar a {
425
+  opacity: 0.7;
426
+  text-decoration: none;
427
+}
428
+
429
+#main-sidebar a.active,
430
+#main-sidebar a:hover,
431
+#main-sidebar a:focus,
432
+#main-sidebar a:active {
433
+  opacity: 1;
434
+}
435
+
436
+.main-content {
437
+  -webkit-box-flex: 3;
438
+      -ms-flex: 3;
439
+          flex: 3;
440
+  overflow: hidden;
441
+}
442
+
443
+.main-content-box {
444
+  display: none;
445
+}
446
+
447
+.main-content-box.show {
448
+  display: initial;
449
+}
450
+
451
+.main-content-box #team-images {
452
+  display: -ms-grid;
453
+  display: grid;
454
+  -ms-grid-columns: (1fr)[2];
455
+      grid-template-columns: repeat(2, 1fr);
456
+  gap: 1em;
457
+  justify-items: center;
458
+  margin: 2em 0;
459
+}
460
+
461
+.main-content-box #team-images img {
462
+  height: 100px;
463
+  width: 100px;
464
+  border-radius: 50%;
465
+  border: 2px #fff solid;
466
+  -webkit-box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 0.3);
467
+          box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 0.3);
468
+}
469
+
470
+#contact-info {
471
+  margin-left: 3.5rem;
472
+  opacity: 0.8;
473
+}
474
+
475
+.login-hr {
476
+  border-width: 4px;
477
+  border-radius: 3px;
478
+}
479
+
480
+/* SHOWCASE */
481
+#showcase {
482
+  margin-top: 8rem;
483
+  min-height: calc(100vh - 8rem);
484
+  background: #333 url(../img/andrew-neel-cckf4TsHAuw-unsplash.jpeg) no-repeat left top;
485
+  background-size: cover;
486
+  position: relative;
487
+  background-blend-mode: screen;
488
+  border-bottom: 3px #f0c873 solid;
489
+}
490
+
491
+#showcase-text {
492
+  position: absolute;
493
+  top: 10vh;
494
+  right: 5vw;
495
+  width: 40%;
496
+  display: -webkit-box;
497
+  display: -ms-flexbox;
498
+  display: flex;
499
+  -webkit-box-orient: vertical;
500
+  -webkit-box-direction: normal;
501
+      -ms-flex-direction: column;
502
+          flex-direction: column;
503
+  text-shadow: 1px 1px 5px #222;
504
+}
505
+
506
+#showcase-heading {
507
+  font-size: 3em;
508
+  color: #fff;
509
+  width: 100%;
510
+  margin-bottom: 0.25em;
511
+  text-align: right;
512
+}
513
+
514
+#showcase-link {
515
+  display: -webkit-box;
516
+  display: -ms-flexbox;
517
+  display: flex;
518
+  -webkit-box-pack: end;
519
+      -ms-flex-pack: end;
520
+          justify-content: flex-end;
521
+}
522
+
523
+#showcase-link a {
524
+  color: #fff;
525
+  font-size: 1.8em;
526
+  text-decoration: underline;
527
+  cursor: pointer;
528
+}
529
+
530
+#showcase-link a:hover {
531
+  text-decoration: none;
532
+}
533
+
534
+/* (EXPERIENCE PAGE) SHOWCASE SECTION */
535
+#view-experience-showcase {
536
+  background-color: #606060;
537
+  margin-top: 8rem;
538
+  color: #fff;
539
+  border-bottom: 3px solid #f0c873;
540
+}
541
+
542
+#view-experience-buttons {
543
+  display: -webkit-box;
544
+  display: -ms-flexbox;
545
+  display: flex;
546
+  -webkit-box-orient: horizontal;
547
+  -webkit-box-direction: normal;
548
+      -ms-flex-direction: row;
549
+          flex-direction: row;
550
+  -webkit-box-align: center;
551
+      -ms-flex-align: center;
552
+          align-items: center;
553
+  -webkit-box-pack: justify;
554
+      -ms-flex-pack: justify;
555
+          justify-content: space-between;
556
+  height: 100%;
557
+  max-width: 18em;
558
+  margin: 0 auto;
559
+}
560
+
561
+#experience-pen {
562
+  color: #fff;
563
+  background-color: #217ce4;
564
+  border-radius: 15px;
565
+  padding: 0.75em;
566
+  font-size: 2em;
567
+  display: -webkit-box;
568
+  display: -ms-flexbox;
569
+  display: flex;
570
+  -webkit-box-align: center;
571
+      -ms-flex-align: center;
572
+          align-items: center;
573
+  -webkit-box-pack: center;
574
+      -ms-flex-pack: center;
575
+          justify-content: center;
576
+  -webkit-box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.3);
577
+          box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.3);
578
+  cursor: pointer;
579
+  -webkit-transition: -webkit-transform 150ms ease-in-out;
580
+  transition: -webkit-transform 150ms ease-in-out;
581
+  transition: transform 150ms ease-in-out;
582
+  transition: transform 150ms ease-in-out, -webkit-transform 150ms ease-in-out;
583
+}
584
+
585
+#experience-pen:hover,
586
+#experience-pen:focus,
587
+#experience-pen:active {
588
+  -webkit-transform: translateY(-5px);
589
+          transform: translateY(-5px);
590
+}
591
+
592
+#view-experience-tabs {
593
+  font-size: 1.2em;
594
+  margin: 1em 0;
595
+  display: -webkit-box;
596
+  display: -ms-flexbox;
597
+  display: flex;
598
+  -ms-flex-pack: distribute;
599
+      justify-content: space-around;
600
+}
601
+
602
+#view-experience-tabs a {
603
+  font-size: 1.2em;
604
+  padding: 0 1em;
605
+  text-decoration: none;
606
+  position: relative;
607
+  -webkit-transition: opacity 150ms ease-in-out;
608
+  transition: opacity 150ms ease-in-out;
609
+  opacity: 0.6;
610
+  font-weight: bold;
611
+}
612
+
613
+#view-experience-tabs a:after {
614
+  content: '';
615
+  position: absolute;
616
+  bottom: 0;
617
+  height: 1px;
618
+  left: 1em;
619
+  right: 1em;
620
+  background-color: #fff;
621
+  -webkit-transform: scaleX(0);
622
+          transform: scaleX(0);
623
+  -webkit-transition: -webkit-transform 150ms ease-in-out;
624
+  transition: -webkit-transform 150ms ease-in-out;
625
+  transition: transform 150ms ease-in-out;
626
+  transition: transform 150ms ease-in-out, -webkit-transform 150ms ease-in-out;
627
+}
628
+
629
+#view-experience-tabs a:hover::after,
630
+#view-experience-tabs a:focus::after,
631
+#view-experience-tabs a:active::after,
632
+#view-experience-tabs a.active::after {
633
+  -webkit-transform: scaleX(1);
634
+          transform: scaleX(1);
635
+}
636
+
637
+#view-experience-tabs a.active,
638
+#view-experience-tabs a:hover,
639
+#view-experience-tabs a:focus,
640
+#view-experience-tabs a:active {
641
+  opacity: 1;
642
+}
643
+
644
+/* (EXPERIENCE PAGE) MAIN SECTION */
645
+.main-content-box#calendar,
646
+.main-content-box#questionnaires,
647
+.main-content-box#moments,
648
+.main-content-box#milestones {
649
+  min-height: calc(80vh - 8rem - 10vh);
650
+}
651
+
652
+#view-experience-content {
653
+  background-color: #fff;
654
+  min-height: calc(100vh - 8rem);
655
+  display: -webkit-box;
656
+  display: -ms-flexbox;
657
+  display: flex;
658
+  -webkit-box-pack: center;
659
+      -ms-flex-pack: center;
660
+          justify-content: center;
661
+  -webkit-box-align: center;
662
+      -ms-flex-align: center;
663
+          align-items: center;
664
+}
665
+
666
+/* FOOTER */
667
+#main-footer {
668
+  background: #2e2e2e;
669
+  color: #fff;
670
+  display: -webkit-box;
671
+  display: -ms-flexbox;
672
+  display: flex;
673
+  -webkit-box-orient: vertical;
674
+  -webkit-box-direction: normal;
675
+      -ms-flex-direction: column;
676
+          flex-direction: column;
677
+  -webkit-box-align: center;
678
+      -ms-flex-align: center;
679
+          align-items: center;
680
+  -webkit-box-pack: center;
681
+      -ms-flex-pack: center;
682
+          justify-content: center;
683
+  min-height: 10vh;
684
+  padding: 1.5em;
685
+  border-top: 3px solid #f0c873;
686
+}
687
+
688
+#main-footer p {
689
+  margin: 0;
690
+  font-size: 1.2em;
691
+}
692
+
693
+#main-footer a {
694
+  color: #aaa;
695
+  text-decoration: none;
696
+}
697
+
698
+#main-footer a:hover,
699
+#main-footer a:active,
700
+#main-footer a:focus {
701
+  color: #fff;
702
+  text-decoration: underline;
703
+}
704
+
705
+/* MEDIA QUERIES */
706
+@media (max-width: 768px) {
707
+  #showcase {
708
+    display: -webkit-box;
709
+    display: -ms-flexbox;
710
+    display: flex;
711
+    -webkit-box-pack: center;
712
+        -ms-flex-pack: center;
713
+            justify-content: center;
714
+    -webkit-box-align: center;
715
+        -ms-flex-align: center;
716
+            align-items: center;
717
+  }
718
+  #showcase-text {
719
+    position: initial;
720
+    min-width: 70%;
721
+  }
722
+  #showcase-heading {
723
+    text-align: center;
724
+  }
725
+  #showcase-link {
726
+    -webkit-box-pack: center;
727
+        -ms-flex-pack: center;
728
+            justify-content: center;
729
+  }
730
+  #main-sidebar {
731
+    display: none;
732
+  }
733
+  .main-content-box {
734
+    display: initial;
735
+  }
736
+  #view-experience-buttons {
737
+    margin: 1rem auto;
738
+  }
739
+  #experience-lead {
740
+    text-align: center;
741
+  }
742
+  #experience-content {
743
+    -ms-grid-columns: 1fr 1fr;
744
+        grid-template-columns: 1fr 1fr;
745
+  }
746
+}
747
+
748
+@media (max-width: 580px) {
749
+  #experience-lead h2 {
750
+    margin: 20px auto 10px auto;
751
+  }
752
+  #experience-content {
753
+    -ms-grid-columns: 1fr;
754
+        grid-template-columns: 1fr;
755
+  }
756
+}
757
+
758
+@media (min-width: 1080px) {
759
+  #experience-content {
760
+    -ms-grid-columns: (1fr)[4];
761
+        grid-template-columns: repeat(4, 1fr);
762
+  }
763
+}
764
+/*# sourceMappingURL=style.css.map */

+ 2
- 0
css/style.min.css
File diff suppressed because it is too large
View File


+ 39
- 0
error.php View File

@@ -0,0 +1,39 @@
1
+<?php		
2
+		
3
+	require_once 'processes/config.php';
4
+	require_once 'processes/dbh.inc.php';
5
+	include_once 'header.php';
6
+		
7
+?>
8
+	<!-- START OF home.php -->
9
+	<body style="min-height: 100vh; display: flex; align-items: center;">
10
+	
11
+		<div class='container text-center'>
12
+			<h1>Error</h1>
13
+			<h4>That's odd, something went wrong!</h4>
14
+			<p style='color: red;'>Redirecting you back to login page<span id="dots">...</span></p>
15
+		</div>
16
+		
17
+		<script>
18
+			var numDots = 3;
19
+			var dots = document.getElementById('dots');
20
+			setInterval(function() {
21
+				if(dots.innerText === "...") {
22
+					dots.innerText = ".";
23
+				} else if(dots.innerText === ".") {
24
+					dots.innerText = "..";
25
+				} else if(dots.innerText === "..") {
26
+					dots.innerText = "...";
27
+				}
28
+			}, 500);
29
+		</script>
30
+		
31
+	</body>
32
+	<!-- END OF home.php -->
33
+</html>
34
+<?php
35
+
36
+	header('Refresh: 3; https://tania.uprrp.edu/admin_nuevo/processes/logout.php');
37
+	ob_end_flush();
38
+	
39
+?>

+ 10
- 0
footer.php View File

@@ -0,0 +1,10 @@
1
+    	<footer id="main-footer">
2
+    	    <p>Copyright &copy; <a href="https://cdcc.uprrp.edu">CDCC</a> (<span id="copyrightDate"></span>)</p>
3
+    	    <p>Universidad de Puerto Rico</p>
4
+    	    <p>Recinto de Río Piedras</p>
5
+    	</footer>
6
+
7
+    	<script src="js/main.js" defer></script>
8
+    	
9
+	</body>
10
+</html>

+ 141
- 0
funciones.php View File

@@ -0,0 +1,141 @@
1
+<?php
2
+
3
+function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") {
4
+  $theValue = (!get_magic_quotes_gpc()) ? addslashes($theValue) : $theValue;
5
+  switch ($theType) {
6
+    case "text":
7
+      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
8
+      break;    
9
+    case "long":
10
+    case "int":
11
+      $theValue = ($theValue != "") ? intval($theValue) : "NULL";
12
+      break;
13
+    case "double":
14
+      $theValue = ($theValue != "") ? "'" . doubleval($theValue) . "'" : "NULL";
15
+      break;
16
+    case "date":
17
+      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
18
+      break;
19
+    case "defined":
20
+      $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue;
21
+      break;
22
+  }
23
+  return $theValue;
24
+}
25
+
26
+function presentaPregsRangoSelect($min_val,$min_text,$max_val,$max_text,$id_q)
27
+{
28
+	//print $id_q;
29
+	print('<select class="form-control" name="question'.$id_q.'" required>');
30
+	print('<option></option>');
31
+	print('<option value="'.$min_val.'">'.$min_val." - ".$min_text.'</option>');
32
+	print("\n");
33
+	for($i=$min_val+1;$i<($max_val);$i++)
34
+	{
35
+		print('<option value="'.$i.'">'.$i.'</option>');
36
+		print($i);
37
+		print("\n");
38
+	}
39
+	print('<option value="'.$max_val.'">'.$max_val." - ".$max_text.'</option>');
40
+	print("\n");
41
+	print("</select>");
42
+	print("\n");
43
+}
44
+
45
+function presentaPregsRangoSlider($min_val,$min_text,$max_val,$max_text,$id_q)
46
+{
47
+	//print('<div class="slidecontainer">');
48
+	print('<input type="range" class="form-control-range slider" value="0" min="'.$min_val.'" max="'.$max_val.'" name="question'.$id_q.'" id="question'.$id_q.'" required>');
49
+	print('<div class="row">');
50
+	
51
+    print('<div class="col-4">');
52
+	print("<small>$min_text</small>");
53
+	print('</div>');
54
+    print('<div class="col-4 text-center">');
55
+	print('<span id="val'.$id_q.'"></span>');
56
+	print('</div>');
57
+    print('<div class="col-4 text-right">');
58
+	print("<small>$max_text</small>");
59
+	print('</div>');
60
+	print('</div>');
61
+	
62
+	print('
63
+	<script>
64
+	var slider'.$id_q.' = document.getElementById("question'.$id_q.'");
65
+	var output'.$id_q.' = document.getElementById("val'.$id_q.'");
66
+	output'.$id_q.'.innerHTML = slider'.$id_q.'.value;
67
+
68
+	slider'.$id_q.'.onclick = function() {
69
+	  output'.$id_q.'.innerHTML = this.value;
70
+	}
71
+	</script>
72
+	');
73
+	//print('</div>');
74
+}
75
+
76
+function presentaPregsRangoRadio($min_val,$min_text,$max_val,$max_text,$id_q)
77
+{
78
+	print('<div class="row-sm">');
79
+	print('<div class="form-check">');
80
+	print('<input class="form-check-input" type="radio" name="question'.$id_q.'" id="radio'.$min_val.'" value="'.$min_val.'" required>');
81
+	print('<label class="form-check-label" for="radio'.$min_val.'">'.$min_val.' - '.$min_text.'</label>');
82
+	print('</div>');
83
+
84
+	for($i=$min_val+1;$i<($max_val);$i++)
85
+	{
86
+		print('<div class="form-check">');
87
+		print('<input class="form-check-input" type="radio" name="question'.$id_q.'" id="radio'.$i.'" value="'.$i.'">');
88
+		print('<label class="form-check-label" for="radio'.$i.'">'.$i.'</label>');
89
+		print('</div>');
90
+	}
91
+	print('<div class="form-check">');
92
+	print('<input class="form-check-input" type="radio" name="question'.$id_q.'" id="radio'.$max_val.'" value="'.$max_val.'">');
93
+	print('<label class="form-check-label" for="radio'.$max_val.'">'.$max_val.' - '.$max_text.'</label>');
94
+	print('</div>');
95
+	print('</div>');
96
+
97
+}
98
+
99
+function presentaPregsRangoRadio2($min_val,$min_text,$max_val,$max_text,$id_q)
100
+{
101
+	print('<div class="row-sm">');
102
+    print('<div class="col">');
103
+	print('<div class="form-check form-check-inline">');
104
+	print('<input class="form-check-input" type="radio" name="question'.$id_q.'" id="radio'.$min_val.'" value="'.$min_val.'">');
105
+	print('</div>');
106
+	print('</div>');
107
+
108
+	for($i=$min_val+1;$i<($max_val);$i++)
109
+	{
110
+    print('<div class="col">');
111
+		print('<div class="form-check form-check-inline">');
112
+		print('<input class="form-check-input" type="radio" name="question'.$id_q.'" id="radio'.$i.'" value="'.$i.'">');
113
+		print('</div>');
114
+	print('</div>');
115
+	}
116
+
117
+    print('<div class="col">');
118
+	print('<div class="form-check form-check-inline">');
119
+	print('<input class="form-check-input" type="radio" name="question'.$id_q.'" id="radio'.$max_val.'" value="'.$max_val.'">');
120
+	print('</div>');
121
+	print('</div>');
122
+
123
+	print('</div>');
124
+	print('<div class="row-sm">');
125
+    print('<div class="col">');
126
+	print('<label class="form-check-label" for="radio'.$min_val.'">'.$min_val.' - '.$min_text.'</label>');
127
+	print('</div>');
128
+	for($i=$min_val+1;$i<($max_val);$i++)
129
+	{
130
+    print('<div class="col">');
131
+		print('<label class="form-check-label" for="radio'.$i.'">'.$i.'</label>');
132
+	print('</div>');
133
+	}
134
+    print('<div class="col">');
135
+	print('<label class="form-check-label" for="radio'.$max_val.'">'.$max_val.' - '.$max_text.'</label>');
136
+	print('</div>');
137
+
138
+	print('</div>');
139
+
140
+}
141
+?>

+ 117
- 0
header.php View File

@@ -0,0 +1,117 @@
1
+<?php ob_start(); ?>
2
+<!DOCTYPE html>
3
+<html lang="en">
4
+	<head>
5
+		<meta charset="UTF-8">
6
+		<meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+		<meta http-equiv="X-UA-Compatible" content="ie=edge">
8
+		<title>TANIA</title>
9
+		
10
+    	<!-- BOOTSTRAP STYLE IMPORT -->
11
+    	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
12
+    	
13
+    	<!-- JQUERY IMPORT-->
14
+    	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
15
+    	
16
+		<!-- BOOTSTRAP JS IMPORT -->
17
+    	<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
18
+    	
19
+    	<!-- FONTAWESOME IMPORT -->
20
+    	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.10.2/css/all.css">
21
+    	
22
+		<!-- APP ICON IMPORT -->
23
+		<!-- <link rel="icon" type="image/png" href="img/pen_1024x1024.png" sizes="1024x1024"> -->
24
+    	<link rel="icon" type="image/png" href="img/pen_800x800.png" sizes="800x800">
25
+    	
26
+		<!-- FULLCALENDAR IMPORT -->
27
+    	<link rel="stylesheet" href="processes/fullcalendar/packages/core/main.css">
28
+    	<link rel="stylesheet" href="processes/fullcalendar/packages/daygrid/main.css">
29
+    	<link rel="stylesheet" href="processes/fullcalendar/packages/timegrid/main.css">
30
+<!-- <link href="https://unpkg.com/@fullcalendar/core/main.min.css"> -->
31
+<!-- <link href="https://unpkg.com/@fullcalendar/daygrid/main.min.css"> -->
32
+
33
+    	<!-- CUSTOM STYLES -->
34
+    	<link rel="stylesheet" href="css/style.css">
35
+    	
36
+    	<style>
37
+    	
38
+textarea {
39
+	resize: vertical;
40
+}
41
+
42
+:root {
43
+	--size: 12px;
44
+	/* 15px for btn-xl */
45
+	/* 15px for btn-lg */
46
+	/* 12px for btn-md */
47
+	/* 10px for btn-sm */
48
+	/* 5px for btn-xs */
49
+	--period: 750ms;
50
+	--color: #3498db;
51
+	--bg-color: white;
52
+	--thinness: 5;
53
+	/* 10 is okay */
54
+}
55
+
56
+.loader {
57
+	display: inline-block;
58
+	width: 12px;
59
+	height: 12px;
60
+	position: relative;
61
+	margin-right: calc(12px / 2);
62
+}
63
+
64
+.loader:before, .loader:after {
65
+	content: "";
66
+	position: absolute;
67
+	left: 0; /* make sure it's inside the box */
68
+	width: 100%;
69
+	height: 100%;
70
+	border-radius: 100%;
71
+	border: calc(12px / 5) solid transparent;
72
+	border-top-color: #3498db;
73
+}
74
+
75
+.loader:before {
76
+	z-index: 100;
77
+	animation: spin 750ms infinite;
78
+}
79
+
80
+.loader:after {
81
+	border: calc(12px / 5) solid white;
82
+}
83
+
84
+@keyframes spin {
85
+	0% {
86
+		-webkit-transform: rotate(0deg);
87
+		-ms-transform: rotate(0deg);
88
+		-o-transform: rotate(0deg);
89
+		transform: rotate(0deg);
90
+	}
91
+
92
+	100% {
93
+		-webkit-transform: rotate(360deg);
94
+		-ms-transform: rotate(360deg);
95
+		-o-transform: rotate(360deg);
96
+		transform: rotate(360deg);
97
+	}
98
+}
99
+    	
100
+    	</style>
101
+
102
+		<script>
103
+// Enable tooltips
104
+$(function () {
105
+  $('[data-toggle="tooltip"]').tooltip();
106
+});
107
+		</script>
108
+	</head>
109
+<?php
110
+
111
+	//if(!empty($_SESSION) && !isset($_SESSION['error'])): //IF USER IS LOGGED IN (WITHOUT ANY ERROR)
112
+	//endif;
113
+
114
+	ini_set('display_errors', 1);
115
+	ini_set('display_startup_errors', 1);
116
+	error_reporting(E_ALL);
117
+?>

+ 374
- 0
home.php View File

@@ -0,0 +1,374 @@
1
+<?php
2
+	
3
+	require_once 'processes/config.php';
4
+	require_once 'processes/dbh.inc.php';
5
+	require_once 'processes/checkLogin.php';
6
+	include_once 'header.php';
7
+	
8
+	// RETRIEVE USER'S NAME AND PICTURE
9
+	$query1 = "SELECT * FROM `researcher` WHERE `email` = '" . $_SESSION['email'] . "';";
10
+	$result1 = mysqli_query($connection, $query1);
11
+	$dbUserData = mysqli_fetch_assoc($result1);
12
+	
13
+	// IF USER NOT IN DATABASE, EXIT
14
+	if($result1->num_rows !== 1) {
15
+		exit();
16
+	}
17
+	
18
+?>
19
+	<!-- START OF home.php -->
20
+	<body>
21
+
22
+    	<header id="main-header">
23
+        	<a id="logo" href=".">
24
+				TANIA
25
+            	<img src="./img/pen_800x800.png" alt="tania logo pen" width="25" height="25">
26
+        	</a>
27
+        	<div id="account">
28
+        	    <a class="nav-link" href="./questionnaires.php">Questionnaire Collection</a>
29
+        	    <a class="sign-out" href="./processes/logout.php">Sign Out</a>
30
+        	</div>
31
+    	</header>
32
+
33
+
34
+    	<section id="welcome">
35
+        	<div id="welcome-text">
36
+        	    <img id="welcome-image" src="<?php echo $dbUserData["picture"]; ?>" alt="User">
37
+        	    <h2 id="welcome-user">Welcome <?php echo explode(" ", $dbUserData['name'])[0]; ?></h2>
38
+        	</div>
39
+    	</section>
40
+
41
+
42
+    	<main id="experience-main">
43
+    	
44
+        	<div class="experience-lead">
45
+        	    <h2>Manage Your Experiences</h2>
46
+        	</div>
47
+        	
48
+        	<div id="experience-content">
49
+
50
+				<!--change to #New when using experience as templates has been implemented-->
51
+            	<div class="grid-box" id="new-experience" onclick="nextModal('#New_2')">
52
+                	<span class="fas fa-plus"></span>
53
+                    <h4>New</h4>
54
+            	</div>
55
+
56
+<?php
57
+	// WARNING: CHANGE QUERY TO INCLUDE "`id_researcher`='".$dbUserData['id_researcher']."';"
58
+	$query2 = "SELECT * FROM `experience`;";
59
+	$result2 = mysqli_query($connection, $query2);
60
+	
61
+	// IF USER HAS EXPERIENCES, SHOW ALL OF THEM
62
+	// ELSE PROMPT USER TO CREATE A NEW EXPERIENCE
63
+	if($result2->num_rows > 0): // USER HAS EXPERIENCE (STANDARD PAGE)
64
+?>
65
+
66
+				<?php while($row = mysqli_fetch_array($result2)): ?>
67
+
68
+            	<div class="grid-box" onclick="location='viewExperience.php?view=<?php echo $row['id']; ?>'">
69
+            	
70
+            		<?php if(mb_strlen($row['title']) == 0): ?>
71
+                	<span class="box-title" onclick="location='viewExperience.php?view=<?php echo $row['id']; ?>'"><small>N/A</small></span>
72
+            		<?php elseif(mb_strlen($row['title']) < 21): ?>
73
+                	<span class="box-title" onclick="location='viewExperience.php?view=<?php echo $row['id']; ?>'"><?php echo $row['title']; ?></span>
74
+                	<?php else: ?>
75
+<!--style="white-space: nowrap;"--><span class="box-title" onclick="location='viewExperience.php?view=<?php echo $row['id']; ?>'"><?php echo substr($row['title'], 0, 30)."<small>...</small>"; ?></span>
76
+                	<?php endif; ?>
77
+                	
78
+                	<div class="box-dates" onclick="location='viewExperience.php?view=<?php echo $row['id']; ?>'">
79
+                	    <p style="margin-bottom: 0;">• Starts: <?php echo date("M j, Y", strtotime($row['start_date'])); ?></p>
80
+                	    <p>• Ends: <?php echo date("M j, Y", strtotime($row['end_date'])); ?></p>
81
+                	</div>
82
+                	
83
+                	<?php 
84
+                		$x = (strtotime($row['end_date']) - strtotime('now')) / 604800;
85
+                		if($x <= 0):
86
+                	?>
87
+                	<span class="box-weeks warning">Finished</span>
88
+                	<?php else: ?>
89
+                	<span class="box-weeks"><?php echo round($x); ?> week<?php if(round($x) > 1) echo 's'; ?> remaining</span>
90
+                	<?php endif; ?>
91
+                	<span class="box-edit" style="background: none;">
92
+                	    <a>
93
+                	        <i class="fas fa-pen"></i>
94
+                	    </a>
95
+                	</span>
96
+
97
+            	</div>
98
+	
99
+            	<?php endwhile; ?>
100
+
101
+<?php else: // USER DOESN'T HAVE EXPERIENCES YET (ALTERNATE PAGE) ?>
102
+
103
+				<script> setTimeout(() => $('#FirstTime').modal('show'), 1000); </script>
104
+		
105
+<?php endif; ?>
106
+
107
+			</div>
108
+			
109
+			<br><br>
110
+			
111
+		</main>
112
+
113
+
114
+
115
+		<!-- POPUP FOR FIRST TIME -->
116
+		<div class='modal fade' id='FirstTime' tabindex='-1' role='dialog' aria-labelledby='FirstTimeLabel' aria-hidden='true'>
117
+			<div class='modal-dialog modal-sm' role='document'>
118
+ 				<div class='modal-content'>
119
+ 					<div class='modal-body'>
120
+ 						
121
+ 						
122
+ 						<!-- CLOSE BUTTON -->
123
+ 						<button type='button' class='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button>
124
+						
125
+						<div class="row text-center">
126
+							<h3>You don't have any experiences yet!</h3>
127
+						
128
+							<h5>Press below to create a new one!</h5>
129
+						
130
+							<button type="button" class='btn btn-default' data-dismiss='modal' onclick="nextModal('#New_2')">New</button>
131
+						</div>
132
+ 								
133
+       		
134
+     		 		</div><!--modal-body-->
135
+    			</div><!--modal-content-->
136
+  			</div><!--modal-dialog-->
137
+		</div><!--modal-->
138
+
139
+
140
+<!--
141
+		<!~~ POPUP FOR NEW EXPERIENCE 1 ~~>
142
+		<div class='modal fade' id='New' tabindex='-1' role='dialog' aria-labelledby='NewLabel' aria-hidden='true'>
143
+			<div class='modal-dialog modal-sm' role='document'>
144
+ 				<div class='modal-content'>
145
+ 					<div class='modal-body'>
146
+ 						
147
+ 						
148
+ 						<!~~ CLOSE BUTTON ~~>
149
+ 						<button type='button' class='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button>
150
+						
151
+						<h4 class='text-center'>Want to add another experience?</h4>
152
+						
153
+						<!~~ CHOOSE: BRAND NEW EXPERIENCE OR USE A TEMPLATE~~>
154
+						<div class='row text-center'>
155
+							<div class='btn-group'>
156
+								<button type="button" class='btn btn-default' data-dismiss="modal" onclick="nextModal('#New_2')">Brand New</button>
157
+								<a href='#' class='btn btn-default'>Use Template</a>
158
+							</div>
159
+						</div>
160
+						<br>
161
+ 						
162
+ 						
163
+      				</div><!~~modal-body~~>
164
+    			</div><!~~modal-content~~>
165
+  			</div><!~~modal-dialog~~>
166
+		</div><!~~modal~~>
167
+-->
168
+
169
+		
170
+<form id="newExperience"><!--method='POST' action='processes/insertExperience.php'-->
171
+		<!-- POPUP FOR NEW EXPERIENCE 2 -->
172
+		<div class='modal fade' id='New_2' tabindex='-1' role='dialog' aria-labelledby='NewLabel_2' aria-hidden='true'>
173
+			<div class='modal-dialog modal-lg' role='document'>
174
+ 				<div class='modal-content'>
175
+ 				
176
+ 					<div class='modal-body'>
177
+ 						
178
+ 						
179
+ 						
180
+ 						<!-- CLOSE BUTTON -->
181
+ 						<button type='button' class='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button>
182
+						
183
+						<div class='row'>
184
+							<div class='col-sm-10'>
185
+								<h2>Brand New Experience <small>(Basic Info)</small></h2>
186
+<!-- 								<h3><small>Start creating a new experience by first adding its basic info.</small></h3> -->
187
+							</div>
188
+						</div><!--row--> 						
189
+
190
+						<hr><br>
191
+
192
+	
193
+						<div class="form-horizontal">
194
+	
195
+							<!-- TITLE -->
196
+							<div class='form-group'>
197
+								<label class='control-label col-sm-2' for='e_title'>Title:</label>
198
+								<div class='col-sm-9'>
199
+									<input type='text' class='form-control text-center' id='e_title' name='title' placeholder='Title' maxlength="60" required>
200
+								</div>
201
+							</div>
202
+				
203
+							<!-- DESCRIPTION -->
204
+							<div class='form-group'>
205
+								<label class='control-label col-sm-2' for='e_description'>Description:</label>
206
+								<div class='col-sm-9'>
207
+									<textarea class='form-control text-center' id='e_description' name='description' rows='1' style='resize:vertical;' placeholder='Description' maxlength="100" required></textarea>
208
+								</div>
209
+							</div>
210
+				
211
+							<!-- TYPE -->
212
+							<div class='form-group'>
213
+								<label class='control-label col-sm-2' for='e_description'>Type:</label>
214
+								<div class='col-sm-9'>
215
+									<select class="form-control text-center" style="text-align-last: center;" id='e_type' name='type' required>
216
+										<option selected value="Course-Based Research">Course-Based Research</option>
217
+										<option value="Independent Research">Independent Research</option>
218
+									</select>
219
+								</div>
220
+							</div>
221
+				
222
+							<!-- DURATION -->
223
+							<div class='form-group'>
224
+								<label class='control-label col-sm-2' for='e_description'>Duration:</label>
225
+								<div class='col-sm-9'>
226
+									<input type='number' class='form-control text-center' id='e_duration' name='duration' placeholder='Duration' min="0" required readonly>
227
+								</div>
228
+							</div>
229
+				
230
+							<!-- START DATE -->
231
+							<div class='form-group'>
232
+								<label class='control-label col-sm-2' for='e_start'>Start Date:</label>
233
+								<div class='col-sm-9'>
234
+									<input type='date' class='form-control text-center' id='e_start' name='start' placeholder="YYYY-MM-DD" required>
235
+								</div>
236
+							</div>
237
+				
238
+							<!-- END DATE -->
239
+							<div class='form-group'>
240
+								<label class='control-label col-sm-2' for='e_end'>End Date:</label>
241
+								<div class='col-sm-9'>
242
+									<input type='date' class='form-control text-center' id='e_end' name='end' placeholder="YYYY-MM-DD" required>
243
+								</div>
244
+							</div>
245
+				
246
+							<!-- INSTITUTION -->
247
+							<div class='form-group'>
248
+								<label class='control-label col-sm-2' for='e_institution'>Institution:</label>
249
+								<div class='col-sm-9'>
250
+									<select class="form-control" id='e_institution' name='institution' style='width:100%; text-align-last: center;' required>
251
+										<option disabled selected value>Institution</option>
252
+										<?php
253
+											$query = "SELECT * FROM `institution`;";
254
+											$result = mysqli_query($connection, $query);
255
+											while($row = mysqli_fetch_assoc($result)):
256
+										?>
257
+										<option value='<?php echo $row['id']; ?>'><?php echo $row['name']; ?></option>
258
+										<?php endwhile; ?>
259
+									</select>
260
+								</div>
261
+							</div>
262
+
263
+
264
+							<br><hr style="width: 80%"><br><br>
265
+
266
+							
267
+							<!-- EXPIRY TIME -->
268
+							<div class='form-group'>
269
+								<label class='control-label col-sm-3' for='e_description'>Expiry Time:</label>
270
+								<div class='col-sm-7 input-groupd'>
271
+									<select class="form-control" style="text-align-last: center;" id="expiry_time" name="expiry_time" required>
272
+										<option selected value="30">30 min</option>
273
+										<option value="60">1 hour</option>
274
+										<option value="120">2 hours</option>
275
+										<option value="180">3 hours</option>
276
+<!-- 										<option value="240">4 hours</option> -->
277
+<!-- 										<option value="300">5 hours</option> -->
278
+										<option value="360">6 hours</option>
279
+										<option value="720">12 hours</option>
280
+										<option value="1080">18 hours</option>
281
+										<option value="1440">1 day</option>
282
+										
283
+									</select>
284
+								</div>
285
+							</div>
286
+							
287
+						</div>
288
+						
289
+						<br>
290
+						
291
+						<!--. Each Moment will need to have a <strong>predetermined expiry time</strong>; -->
292
+						<p class='alert alert-warning text-justify' style="width: 80%; margin: 0 auto;">We require that you specify a <strong>Moment Expiry Time</strong>. That is, the amount of time you, the researcher, will allot your subjects to answer a given Moment. The <strong>minimum</strong> we allow is 30 min, while the <strong>maximum</strong> is a whole day. Please keep in mind you should provide your subjects </strong>enough time</strong> so that they are allowed to answer properly, but do not allocate <strong>excessive time</strong>, as your subjects' answers may vary greatly with time.</p>
293
+
294
+						<br>
295
+			
296
+			
297
+
298
+		<!-- ERROR ALERT FOR USER -->			
299
+	<div id="error-newExperience" class="row" style="display: none;">
300
+		<div class="col-sm-12">
301
+			<div class="alert alert-danger mb-1" role="alert">
302
+				<h4 class="error-lead">Error!</h4>
303
+				<p class="error-description"></p>
304
+			</div>
305
+		</div>
306
+	</div>
307
+			
308
+			
309
+      				</div><!--modal-body-->
310
+      				
311
+      				<!-- SUBMIT OR CANCEL -->
312
+     				<div class='modal-footer'>
313
+       					<button type='button' class='btn btn-default' data-dismiss='modal'>Cancel</button>
314
+        				<button type='submit' class='btn btn-primary' name='newExperience'>Create</button>
315
+<!--         				<button type='button' class='btn btn-primary' data-dismiss='modal' onclick="nextModal('#New_3')">Next</button> -->
316
+      				</div>
317
+      				
318
+    			</div><!--modal-content-->
319
+  			</div><!--modal-dialog-->
320
+		</div><!--modal-->
321
+</form><!--form-->
322
+
323
+
324
+
325
+
326
+
327
+
328
+
329
+
330
+
331
+
332
+
333
+
334
+
335
+		<script src="js/home.js"></script>
336
+		<script src="js/handleSubmit.js"></script>
337
+
338
+
339
+<script>
340
+
341
+		
342
+		["newExperience"].forEach(function(formName) {
343
+			
344
+			var form = document.getElementById(formName);
345
+			
346
+			if(form) {
347
+				form.addEventListener('submit', function(e) {
348
+					handleSubmit(e, formName);
349
+				});
350
+			}
351
+			
352
+		});
353
+
354
+
355
+		window.onload = function() {
356
+
357
+			// Start Date
358
+			setStartDateRange();
359
+	
360
+			// End Date
361
+			startDate.addEventListener('change', setEndDateRange);
362
+	
363
+			// Duration
364
+			startDate.addEventListener('change', setDuration);
365
+			endDate.addEventListener('change', setDuration);
366
+			
367
+		}		
368
+
369
+		</script>
370
+
371
+		<!-- END OF home.php -->
372
+
373
+
374
+<?php include_once 'footer.php'; ?>

BIN
img/.DS_Store View File


BIN
img/CDCC.png View File


BIN
img/EMA-banner1.png View File


BIN
img/EMA-banner2.png View File


BIN
img/andrew-neel-cckf4TsHAuw-unsplash.jpeg View File


BIN
img/carlos.jpg View File


BIN
img/carlos_original.jpg View File


BIN
img/coralys.jpg View File


BIN
img/coralys_original.jpg View File


BIN
img/cytonn-photography-GJao3ZTX9gU-unsplash.jpeg View File


+ 6
- 0
img/google.svg View File

@@ -0,0 +1,6 @@
1
+<svg viewBox="0 0 366 372" xmlns="http://www.w3.org/2000/svg">
2
+    <path d="M125.9 10.2c40.2-13.9 85.3-13.6 125.3 1.1 22.2 8.2 42.5 21 59.9 37.1-5.8 6.3-12.1 12.2-18.1 18.3l-34.2 34.2c-11.3-10.8-25.1-19-40.1-23.6-17.6-5.3-36.6-6.1-54.6-2.2-21 4.5-40.5 15.5-55.6 30.9-12.2 12.3-21.4 27.5-27 43.9-20.3-15.8-40.6-31.5-61-47.3 21.5-43 60.1-76.9 105.4-92.4z" fill="#EA4335"/>
3
+    <path d="M20.6 102.4c20.3 15.8 40.6 31.5 61 47.3-8 23.3-8 49.2 0 72.4-20.3 15.8-40.6 31.6-60.9 47.3C1.9 232.7-3.8 189.6 4.4 149.2c3.3-16.2 8.7-32 16.2-46.8z" fill="#FBBC05"/>
4
+    <path d="M361.7 151.1c5.8 32.7 4.5 66.8-4.7 98.8-8.5 29.3-24.6 56.5-47.1 77.2l-59.1-45.9c19.5-13.1 33.3-34.3 37.2-57.5H186.6c.1-24.2.1-48.4.1-72.6h175z" fill="#4285F4"/>
5
+    <path d="M81.4 222.2c7.8 22.9 22.8 43.2 42.6 57.1 12.4 8.7 26.6 14.9 41.4 17.9 14.6 3 29.7 2.6 44.4.1 14.6-2.6 28.7-7.9 41-16.2l59.1 45.9c-21.3 19.7-48 33.1-76.2 39.6-31.2 7.1-64.2 7.3-95.2-1-24.6-6.5-47.7-18.2-67.6-34.1-20.9-16.6-38.3-38-50.4-62 20.3-15.7 40.6-31.5 60.9-47.3z" fill="#34A853"/>
6
+</svg>

BIN
img/hector.jpg View File


BIN
img/hector_original.jpg View File


BIN
img/ivonne.png View File


BIN
img/juan.png View File


BIN
img/juan_original.png View File


BIN
img/pen_1024x1024.png View File


BIN
img/pen_800x800.png View File


BIN
img/tatiana.jpg View File


BIN
img/tatiana_original.jpg View File


BIN
img/victor.jpg View File


+ 105
- 0
index.php View File

@@ -0,0 +1,105 @@
1
+<?php
2
+	
3
+	require_once 'processes/config.php';
4
+	
5
+	// IF USER IS ALREADY LOGGED IN, REDIRECT TO home.php
6
+	// ELSE PROMPT USER TO LOG IN
7
+	if(!empty($_SESSION)) {
8
+		header('Location: home.php');
9
+		exit();
10
+	}
11
+	
12
+	include_once 'header.php';
13
+	
14
+?>
15
+	<!-- START OF index.php -->
16
+	<body>
17
+		<header id="main-header">
18
+        	<a id="logo" href=".">
19
+				TANIA
20
+            	<img src="img/pen_800x800.png" alt="tania logo pen" width="25" height="25">
21
+        	</a>
22
+	        <div id="account">
23
+    	        <button class="google-button" onclick="window.location='<?php echo $loginURL; ?>'">
24
+    	            <img class="google-button__icon" src="img/google.svg" alt="Google">
25
+    	            <span class="google-button__text">Sign in with Google</span>
26
+    	        </button>
27
+    	    </div>
28
+    	</header>
29
+	
30
+  	  	<section id="showcase">
31
+   	     	<div id="showcase-text">
32
+    	        <div id="showcase-heading">
33
+                	Momentary Assesment Research Made Simple
34
+   	         	</div>
35
+    	        <div id="showcase-link">
36
+     	           <a onclick="window.location='<?php echo $loginURL; ?>'">Get Started</a>
37
+     	       </div>
38
+    	    </div>
39
+   	 	</section>	
40
+   	 	
41
+		<main id="home-main">
42
+        	<div id="main-sidebar">
43
+            	<h3>About</h3>
44
+        	    <ul>
45
+            	    <li><a href="#what-we-do" class="active">What We Do</a></li>
46
+                	<li><a href="#team">Team</a></li>
47
+	                <li><a href="#contact">Contact</a></li>
48
+    	        </ul>
49
+    	    </div>
50
+
51
+    	    <div class="main-content">
52
+    	    
53
+        	    <div id="what-we-do" class="main-content-box show">
54
+	                <h3>The problem</h3>
55
+    	            <p>Most research on REUs rely on retrospective recollection of experiences often limited by memory and conditioned to recall bias, where information is selectively withheld or revealed.</p>
56
+        	        <h3>Our proposal</h3>
57
+                	<p>To improve the evaluation strategies of REUs, we propose using Momentary Assessments Research Learning Environments (MARLE), a method used in clinical psychology to repeatedly sample momentary behaviors in real time within the natural environment of an experience or intervention.</p>
58
+                	<br>
59
+                	<hr class="login-hr">
60
+                	<br>
61
+            	</div>
62
+
63
+            	<div id="team" class="main-content-box">
64
+                	<h3>We are a team of professors and students</h3>
65
+                	<div id="team-images">
66
+                	    <img src="img/juan.png" alt="Juan">
67
+						<!-- <img src="img/ivonne.png" alt="Ivonne"> -->
68
+                	    <img src="img/CDCC.png" alt="CDCC" style="background-color: #eee; padding: 5px;">
69
+                	    <!-- <img src="./img/victor.jpg" alt="Víctor" style="height: 100px; width: 100px; border-radius: 50%;"> -->
70
+                		<!-- <img src="./img/hector.jpg" alt="Héctor" style="height: 100px; width: 100px; border-radius: 50%;"> -->
71
+                    	<!-- <img src="./img/tatiana.jpg" alt="Tatiana" style="height: 100px; width: 100px; border-radius: 50%;"> -->
72
+                    	<!-- <img src="./img/coralys.jpg" alt="Coralys" style="height: 100px; width: 100px; border-radius: 50%;"> -->
73
+                    	<!-- <img src="./img/carlos.jpg" alt="Carlos" style="height: 100px; width: 100px; border-radius: 50%;"> -->
74
+                	</div>
75
+					<!-- Dr. Ivonne Vele (Department of Education) -->
76
+                	<p>This is the result of a collaboration between Dr. Juan Ramírez (Department of Biology), and the CDCC at the University of Puerto Rico, Río Piedras Campus.</p>
77
+                	<br>
78
+                	<hr class="login-hr">
79
+                	<br>
80
+            	</div>
81
+
82
+            	<div id="contact" class="main-content-box">
83
+            	    <h3>Contact Us</h3>
84
+            	    <p>Care to use TANIA? Or just curious about the project? Whichever may be the case, don't hesitate to contact Dr. Juan Ramírez!</p>
85
+            	    <br>
86
+            	    <div id="contact-info">
87
+            	    <p>17 Ave. Universidad STE 1701 San Juan, PR 00925-2537</p>
88
+            	    <p>787.764.0000 Ext. 88341, 88349 Fax:787.773.1717</p>
89
+            	    <p>juan.ramirez3@upr.edu</p>
90
+            	    </div>
91
+            	    <br>
92
+            	    <hr class="login-hr hidden-xs">
93
+            	    <br>
94
+            	</div>
95
+            	
96
+            	<br><br><br>
97
+            	
98
+        	</div>
99
+    	</main>
100
+    	
101
+    	<script src="js/index.js"></script>
102
+    	
103
+		<!-- END OF index.php -->
104
+		
105
+<?php include_once 'footer.php'; ?>

+ 51
- 0
js/editQuestion.js View File

@@ -0,0 +1,51 @@
1
+$('#EditQuestion').on('show.bs.modal', function(event) {
2
+  var tableRow = $(event.relatedTarget);
3
+  var questionNumber = $(tableRow).data('question-number');
4
+//   var questionnaireID = $(tableRow).data('questionnaire-id');
5
+  var questionID = $(tableRow).data('question-id');
6
+  var premise = $(tableRow).data('premise');
7
+  var type = $(tableRow).data('type');
8
+  var min_text = $(tableRow).data('min_text');
9
+  var max_val = $(tableRow).data('max_val');
10
+  var max_text = $(tableRow).data('max_text');
11
+  var categoryID = $(tableRow).data('categoryid');
12
+  var subcategoryID = $(tableRow).data('subcategoryid');
13
+  var modal = $(this);
14
+  
15
+//   console.log('questionNumber' + questionNumber);
16
+//   console.log('questionnaireID' + questionnaireID);
17
+//   console.log('questionID' + questionID);
18
+//   console.log('premise' + premise);
19
+//   console.log('type' + type);
20
+//   console.log('min_text' + min_text);
21
+//   console.log('max_val' + max_val);
22
+//   console.log('max_text' + max_text);
23
+//   console.log('categoryID' + categoryID);
24
+//   console.log('subcategoryID' + subcategoryID);
25
+//   console.log(modal);
26
+  
27
+  deleteModal = $('#Delete');
28
+  deleteModal.find('.modal-body [name=questionID]').val(questionID);
29
+  deleteModal.find('.modal-body .question-number').text(questionNumber);
30
+
31
+  modal.find('.modal-body .question-number').text(questionNumber);  
32
+//   modal.find('.modal-body input[name="questionnaireID"]').val(questionnaireID);
33
+  modal.find('.modal-body input[name="questionID"]').val(questionID);
34
+  modal.find('.modal-body input[name="update_q_premise"]').val(premise);
35
+  modal.find('.modal-body select[name="update_q_type"]').val(type);
36
+  // min_val not necessary (always 1)
37
+  modal.find('.modal-body input[name="update_min_text"]').val(min_text);
38
+  modal.find('.modal-body input[name="update_max_val"]').val(max_val);
39
+  modal.find('.modal-body input[name="update_max_text"]').val(max_text);
40
+  modal.find('.modal-body select[name="update_q_category"]').val(categoryID);
41
+  modal.find('.modal-body select[name="update_q_subcategory"]').val(subcategoryID);
42
+
43
+
44
+  if(type === 2) {
45
+    modal.find('.modal-body .range').css('display', 'none');
46
+  } else if(type === 1) {
47
+  	modal.find('.modal-body .range').css('display', 'block');
48
+  }
49
+
50
+  
51
+});

+ 172
- 0
js/handleSubmit.js View File

@@ -0,0 +1,172 @@
1
+function handleSubmit(event, formName) {
2
+
3
+	// Prevent naive submit
4
+	event.preventDefault();
5
+
6
+
7
+	// Fetch error description element
8
+	var errorDescription = document.querySelector('#error-'+formName+' .error-description');
9
+	var submitButton = document.querySelector('#'+formName+' button[type="submit"]');
10
+
11
+
12
+	// Disable button and start "Loading" state
13
+	submitButton.disabled = true;
14
+	submitButton.classList.remove('btn-danger');
15
+	submitButton.classList.add('btn-primary');
16
+	submitButton.innerHTML = '<div class="loader"></div>Loading...';
17
+
18
+
19
+	// Fetch all input from form
20
+	var fields = {};
21
+	$("form#" + formName).find("input, textarea, select, button[type='submit']").each(function() {
22
+		var input = $(this);
23
+		fields[input.attr('name')] = input.val();
24
+	});
25
+
26
+
27
+	// Construct request URL (make sure to use http or https accordingly)
28
+	var baseURI = document.location.protocol + "//tania.uprrp.edu/admin_nuevo/processes/";
29
+	var fullURI = baseURI;
30
+
31
+	switch(formName) {
32
+	
33
+		// home.php
34
+		case "newExperience":
35
+			fullURI += "insertExperience.php";
36
+			break;
37
+		
38
+		// viewExperience.php
39
+		case "editForm":
40
+			fullURI += "updateExperience.php";
41
+			break;
42
+		case "newQuestionnaire":
43
+			fullURI += "insertQuestionnaire.php";
44
+			break;
45
+		case "newMoment":
46
+		 	fullURI += "insertMoment.php";
47
+		 	break;
48
+		case "newMilestone":
49
+			fullURI += "insertMilestone.php";
50
+			break;
51
+		
52
+		// viewQuestionnaire.php
53
+		case "updateQuestionnaire":
54
+			fullURI += "updateQuestionnaire.php";
55
+			break;
56
+		case "deleteQuestionnaire":
57
+			fullURI += "deleteQuestionnaire.php";
58
+			break;
59
+		case "newQuestion":
60
+			fullURI += "insertQuestionToQuestionnaire.php";
61
+			break;
62
+		case "deleteQuestion":
63
+			fullURI += "deleteQuestion.php";
64
+			break;
65
+		
66
+		// viewMoment.php
67
+		case "updateMoment":
68
+			fullURI += "updateMoment.php";
69
+			break;
70
+		case "deleteMoment":
71
+			fullURI += "deleteMoment.php";
72
+			break;
73
+		case "removeQuestionFromMoment":
74
+			fullURI += "removeQuestionFromMoment.php";
75
+			break;
76
+		case "addExistingQuestionToMoment":
77
+			fullURI += "addExistingQuestionToMoment.php";
78
+			break;
79
+		
80
+		// Both viewMoment.php and viewQuestionnaire.php
81
+		case "updateQuestion":
82
+			fullURI += "updateQuestion.php";
83
+			break;
84
+			
85
+
86
+		
87
+		default:
88
+			fullURI = document.location.protocol + '//tania.uprrp.edu/admin_nuevo/test.php';
89
+			
90
+	}
91
+
92
+// 	console.log(JSON.stringify(fields) + "\n" + fullURI);
93
+
94
+
95
+	// Use fullURI to make POST request w/ jQuery,
96
+	// Wait for response (start "Loading" state),
97
+	// Act according to error or success
98
+			
99
+//	!!!!!! SHOULD ADD TIMEOUT TO REQUESTS TO !!!!!!!
100
+	$.post(fullURI, fields)
101
+		.done(function(data, text) {
102
+				
103
+			console.log(data + "and" + text);
104
+
105
+			// Fetch needed elements
106
+			let alert = document.querySelector('#error-'+formName+' .alert');
107
+			let errorLead = document.querySelector('#error-'+formName+' .error-lead');
108
+
109
+
110
+			// Clear errors and change message to "Success"
111
+			errorDescription.remove();
112
+			errorLead.innerText = "Success!";
113
+			errorLead.style.marginBottom = "0";
114
+
115
+
116
+			// Change alert style to "Success"
117
+			alert.classList.remove('alert-danger');
118
+			alert.classList.add('alert-success');
119
+
120
+
121
+			// Change button style to "Success"
122
+			submitButton.classList.remove('btn-primary');
123
+			submitButton.classList.add('btn-success');
124
+			submitButton.innerHTML = '<span class="glyphicon glyphicon-ok"></span> Success!';// could use &#10004;
125
+
126
+
127
+			// Reload page
128
+			setTimeout(function() {
129
+			
130
+				let deleteForms = ["deleteQuestionnaire", "deleteMoment", "deleteExperience"];
131
+			
132
+				if(deleteForms.includes(formName)) {
133
+					history.back(); // go back to viewExperience page (remember we don't know the ID of the experience it came from)
134
+				} else {
135
+					location.reload();
136
+				}
137
+				
138
+			}, 250);
139
+
140
+		})
141
+		.fail(function(request, status, error) {
142
+				
143
+			console.log(request.responseText);
144
+			console.log(status);
145
+			console.log(error);
146
+	
147
+			// Fetch needed elements
148
+			let alertContainer = document.getElementById('error-'+formName);
149
+					
150
+			// If response is not a JSON, or if JSON doesn't have "error" field, say so
151
+			// else, dynamically update error message according to server
152
+			if(!isJSON(request.responseText) || JSON.parse(request.responseText).error === undefined) {
153
+				errorDescription.innerText = "Something went wrong on our side! Please try again later.";
154
+			} else {
155
+				errorDescription.innerText = JSON.parse(request.responseText).error;
156
+			}
157
+
158
+			// Change button style to "Retry"
159
+			submitButton.innerHTML = "Retry";
160
+			submitButton.disabled = false;
161
+					
162
+			// Display alert
163
+			alertContainer.style.display = "initial";
164
+
165
+		});
166
+// 		.always(function(data, textStatus, errorThrown) {
167
+// 			console.log(data);
168
+// 			console.log(textStatus);
169
+// 			console.log(errorThrown);
170
+// 		});
171
+
172
+}

+ 77
- 0
js/home.js View File

@@ -0,0 +1,77 @@
1
+///// !!! home.php !!! /////
2
+
3
+
4
+
5
+// Target the input fields to be updated
6
+let startDate = document.querySelector('input[name=start]');
7
+let endDate = document.querySelector('input[name=end]');
8
+let duration = document.querySelector('input[name=duration]');
9
+
10
+
11
+
12
+// For new experiences, the minimum start date is tomorrow and the maximum is a year from tomorrow
13
+function setStartDateRange() {
14
+
15
+	/* Compute the today, tomorrow and the year after tomorrow */
16
+// 	let today = new Date();
17
+// 	today.setHours(0, 0, 0, 0); // (default to 00:00:00)
18
+// 	let tomorrow = new Date(today);
19
+// 	tomorrow.setDate(tomorrow.getDate() + 1);
20
+// 	let aYearFromTomorrow = new Date(tomorrow);
21
+// 	aYearFromTomorrow.setDate(aYearFromTomorrow.getDate() + 365);
22
+
23
+	// Set minimum start date to tomorrow
24
+// 	startDate.min = tomorrow.toLocaleDateString();
25
+	
26
+	// Set maximum start date to a year from tomorrow
27
+// 	startDate.max = aYearFromTomorrow.toLocaleDateString();
28
+
29
+	if(!isNaN(Date.parse(startDate.value)) && !isNaN(Date.parse(endDate.value))) {
30
+		if(Date.parse(startDate.value) > Date.parse(endDate.value)) {
31
+			endDate.value = startDate.value;
32
+		}
33
+	}
34
+	
35
+}
36
+
37
+
38
+
39
+// For new experiences, the minimum end date is the day after the start date and the maximum is a year from the minimum end date
40
+function setEndDateRange() {
41
+	
42
+	/* Compute the day after the start date value, and the year after that */
43
+// 	let dayAfterStart = new Date(startDate.value);
44
+// 	dayAfterStart.setDate(dayAfterStart.getDate() + 1 + 1); // (additional 1 necessary because of line above, apparent 0-indexing)
45
+// 	let aYearFromMinimumEnd = new Date(dayAfterStart);
46
+// 	aYearFromMinimumEnd.setDate(aYearFromMinimumEnd.getDate() + 365);
47
+	
48
+	// Set minimum end date to the day after the start date
49
+// 	endDate.min = dayAfterStart.toLocaleDateString();
50
+	
51
+	// Set maximum end date to a year from the minimum end date
52
+// 	endDate.max = aYearFromMinimumEnd.toLocaleDateString();
53
+
54
+	if(!isNaN(Date.parse(startDate.value)) && !isNaN(Date.parse(endDate.value))) {
55
+		if(Date.parse(startDate.value) > Date.parse(endDate.value)) {
56
+			startDate.value = endDate.value;
57
+		}
58
+	}
59
+
60
+}
61
+
62
+
63
+
64
+// For new experiences, the duration (in weeks) will be the rounded weeks from start to end dates
65
+function setDuration() {
66
+
67
+	// Calculate the duration in weeks
68
+	x = new Date(startDate.value);
69
+	x.setDate(x.getDate() + 1); // (additional 1 necessary because of line above, apparent 0-indexing)
70
+	y = new Date(endDate.value);
71
+	y.setDate(y.getDate() + 1); // (additional 1 necessary because of line above, apparent 0-indexing)
72
+	
73
+	duration.value = String(Math.max(Math.round((y - x) / 604800000), 0)); // (1000 * 60 * 60 * 24 * 7 = 604800000)
74
+
75
+}
76
+
77
+

+ 39
- 0
js/index.js View File

@@ -0,0 +1,39 @@
1
+///// !!! index.php !!! /////
2
+
3
+// Get tab links and tab panes
4
+let tabLinks = document.querySelectorAll('#main-sidebar a');
5
+let tabPanes = document.querySelectorAll('.main-content-box');
6
+
7
+
8
+
9
+// Add event listener to all tab links
10
+tabLinks.forEach(tabLink => {
11
+	tabLink.addEventListener('click', tabChange);
12
+});
13
+
14
+
15
+
16
+// Add selected link style and remove those who were not selected
17
+function tabChange(e) {
18
+
19
+    e.preventDefault();
20
+    
21
+    // Change the style of the links
22
+    tabLinks.forEach(tabLink => {
23
+    	if(tabLink === e.target) {
24
+    		tabLink.classList.add('active');
25
+    	} else {
26
+    		tabLink.classList.remove('active');
27
+    	}
28
+    });
29
+
30
+    // Change the opacity of each of the panes
31
+    tabPanes.forEach(tabPane => {
32
+    	if(tabPane.id === e.target.hash.substring(1)) {
33
+			tabPane.classList.add('show');
34
+    	} else {
35
+			tabPane.classList.remove('show');
36
+    	}
37
+    });
38
+
39
+}

+ 146
- 0
js/main.js View File

@@ -0,0 +1,146 @@
1
+///// !!! GLOBAL FUNCTIONS !!! /////
2
+
3
+
4
+
5
+// CHECKS THAT STRINGS ARE JSON
6
+function isJSON(item) {
7
+
8
+// 	item = (typeof item !== "string")
9
+// 		? JSON.stringify(item)
10
+// 		: item;
11
+
12
+    try {
13
+        item = JSON.parse(item);
14
+    } catch (e) {
15
+        return false;
16
+    }
17
+
18
+    return (typeof item === "object" && item !== null);
19
+
20
+}
21
+
22
+
23
+
24
+// MODAL SWITCHING FUNCTION (home.php & viewExperience.php)
25
+function nextModal(name) {
26
+	$('[data-toggle="tooltip"]').tooltip('hide');
27
+	setTimeout(() => $(name).modal('show'), 100);
28
+}
29
+
30
+
31
+
32
+// Disable 'enter' key from submitting forms
33
+// $('form').keypress(function(event){ if (event.which == '13') { event.preventDefault(); } } );
34
+// $('[form]:not(button[form])').keypress(function(event){ if (event.which == '13') { event.preventDefault(); } } );
35
+
36
+
37
+
38
+// NUMBER INPUT SANITIZATION (home.php & viewExperience.php)
39
+$('input[type="number"]').on('change keyup', () => {
40
+
41
+	// Remove invalid characters
42
+	var sanitized = $(this).val().replace(/[^0-9]/g, '');
43
+	
44
+	// Update value
45
+	$(this).val(sanitized);
46
+	
47
+});
48
+
49
+
50
+
51
+// DATE INPUT DATEPICKER (home.php & viewExperience.php)
52
+// Taken from: http://www.javascriptkit.com/javatutors/createelementcheck2.shtml
53
+// If browser doesn't support input type="date", load files for jQuery UI Date Picker
54
+let testDateField = document.createElement("input");
55
+
56
+testDateField.setAttribute("type", "date");
57
+
58
+if(testDateField.type != "date") {
59
+	
60
+	// First load the CSS ("base" theme) for the calendar
61
+	document.write('<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet" type="text/css" />\n');
62
+	
63
+	// Then load the calendar functionality
64
+    document.write('<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>\n');
65
+   	
66
+   	// Initialize date picker widget (on document.ready)
67
+   	// Help: https://jqueryui.com/datepicker/#min-max
68
+   	window.onload = () => {
69
+   		if($('input[type="date"]').length !== 0) {
70
+	   		jQuery(($) => $('input[type="date"]').datepicker({ minDate: 0, maxDate: "+1Y"}));
71
+   		}
72
+	}
73
+	
74
+}
75
+
76
+
77
+
78
+// FOOTER COPYRIGHT YEAR
79
+let date = new Date().getFullYear();
80
+document.getElementById('copyrightDate').innerHTML = date;
81
+
82
+
83
+
84
+
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
93
+
94
+
95
+// !!! FROM HERE ON DOWN, THERE'S ONLY OLD CODE !!! //
96
+
97
+
98
+
99
+// Declaration and initialization of the "naming counter" 
100
+var selectionCounter = 2;
101
+
102
+// WHEN WANTING TO ADD MULTIPLE QUESTIONNAIRES TO AN EXPERIENCE (newExperience.php and editExperience.php)
103
+function AddQuestionnaire() {
104
+
105
+    // We add two linebreaks so that there is space between each dropdown list
106
+    var br = document.createElement('br');
107
+    document.getElementById('addQuestionnaires').appendChild(br);
108
+    br = document.createElement('br');
109
+    document.getElementById('addQuestionnaires').appendChild(br);
110
+        
111
+    // We create a copy of the dropdown list we already have, so multiple questions can be added at the same time
112
+    var select = document.getElementById('questionnaire');
113
+    var clone = select.cloneNode(true);
114
+        
115
+    // The clones will have the same name as the original but with a number that will distinguish them
116
+    var name = select.getAttribute('name') + selectionCounter++;
117
+    clone.id = name;
118
+    clone.setAttribute('name', name);
119
+    document.getElementById('addQuestionnaires').appendChild(clone);
120
+    //document.getElementById("demo").innerHTML = selectionCounter;
121
+}
122
+
123
+// Reinitialization of the "naming counter"
124
+selectionCounter = 2;
125
+
126
+// WHEN WANTING TO ADD MULTIPLE QUESTIONS TO A QUESTIONNAIRE (newQuestionnaire.php and editQuestionnaire.php)
127
+function AddQuestion() { 
128
+    
129
+    // We add a linebreak so that there is space between each dropdown list
130
+    var br = document.createElement("br");
131
+    document.getElementById("addQuestions").appendChild(br)
132
+    var br2 = document.createElement("br");
133
+    document.getElementById("addQuestions").appendChild(br2)
134
+
135
+    // We create a copy of the dropdown list we already have, so multiple questions can be added at the same time.
136
+    var select = document.getElementById("question");
137
+    var clone = select.cloneNode(true);
138
+
139
+    // The clones will have the same name as the original but with a number that will distinguish them
140
+    var name = select.getAttribute("name") + selectionCounter++;
141
+    clone.id = name;
142
+    clone.setAttribute("name", name)
143
+    document.getElementById("addQuestions").appendChild(clone)
144
+    //document.getElementById("demo").innerHTML = selectionCounter;  	
145
+}
146
+

BIN
js/nameOfTheQuestionnair.xlsx View File


+ 242
- 0
js/viewExperience.js View File

@@ -0,0 +1,242 @@
1
+///// !!! viewExperience.php !!! /////
2
+
3
+
4
+
5
+// Get tab links and tab panes
6
+let tabLinks = document.querySelectorAll('#view-experience-tabs a');
7
+let tabPanes = document.querySelectorAll('.main-content-box');
8
+
9
+
10
+
11
+// Add event listener to all tab links
12
+// tabLinks.forEach(tabLink => {
13
+// 	tabLink.addEventListener('click', tabChange);
14
+// });
15
+window.onload = tabChange;
16
+window.onhashchange = tabChange;
17
+
18
+
19
+
20
+// Add selected link style and remove those who were not selected
21
+function tabChange() {
22
+
23
+	let hash = document.location.hash;
24
+	
25
+	validHashes = ['#calendar', '#questionnaires', '#moments', '#milestones'];
26
+	
27
+	if(!validHashes.includes(hash)) {
28
+		hash = '#calendar';
29
+	}
30
+
31
+    // Change the style of the links
32
+    tabLinks.forEach(tabLink => {
33
+    	if(tabLink.hash === hash) {//tabLink === e.target
34
+    		tabLink.classList.add('active');
35
+    	} else {
36
+    		tabLink.classList.remove('active');
37
+    	}
38
+    });
39
+
40
+    // Change the opacity of each of the panes
41
+    tabPanes.forEach(tabPane => {
42
+    	if(tabPane.id === hash.substring(1)) {// tabPane.id === e.target.hash.substring(1)
43
+			tabPane.classList.add('show');
44
+    	} else {
45
+    		tabPane.classList.remove('show');
46
+    	}
47
+    });
48
+    
49
+    // Re-render calendar
50
+    if(calendar && hash === '#calendar') {
51
+    	calendar.render();
52
+    }
53
+
54
+}
55
+
56
+		
57
+		
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+function newThing(e) {
67
+	let type = e.currentTarget.value;
68
+	let range = e.currentTarget.parentNode.parentNode.parentNode.nextElementSibling; // get the 4 (optional) inputs for scaled-type questions
69
+	range.style.display = (type === "1") ? 'block' : 'none'; // "1" corresponds to scaled questions
70
+}
71
+	
72
+	
73
+	
74
+// Add Question to Questionnaire							
75
+var Questions = 1;
76
+function addQuestion() {
77
+	// We add a linebreak so that there is space between each dropdown list
78
+	var br = document.createElement("br");
79
+	document.querySelector('#q'+Questions).parentElement.lastElementChild.previousElementSibling.previousElementSibling.insertAdjacentElement('afterend', br);
80
+
81
+	// We create a copy of the dropdown list we already have, so multiple questions can be added at the same time.
82
+	var newQuestion = document.getElementById("q"+Questions);
83
+	var clone = newQuestion.cloneNode(true);
84
+
85
+	//The clones will have the same name as the original but with a number that will distinguish them
86
+	var newName = 'q' + Number(Questions + 1);
87
+	clone.id = newName;
88
+								
89
+	document.querySelector('#q'+Questions).parentElement.lastElementChild.previousElementSibling.previousElementSibling.insertAdjacentElement('afterend', clone);
90
+    							
91
+	document.querySelector('#'+newName+' h4').innerHTML = 'Question '+Number(Questions+1);
92
+    							
93
+	document.querySelector('#'+newName+' #q_premise'+Questions).name = 'q_premise'+Number(Questions+1);
94
+	document.querySelector('#'+newName+' #q_premise'+Questions).id = 'q_premise'+Number(Questions+1);
95
+			
96
+	// Get the question type before changing it's name/id (for some reason it doesn't pass it on)
97
+	let type = $(newQuestion).find("#q_type"+Questions).val();
98
+	document.querySelector('#'+newName+' #q_type'+Questions).value = type;
99
+	document.querySelector('#'+newName+' #q_type'+Questions).name = 'q_type'+Number(Questions+1);
100
+	document.querySelector('#'+newName+' #q_type'+Questions).id = 'q_type'+Number(Questions+1);
101
+	
102
+	// Depending on the question type, display or hide min/max values/labels
103
+	if(type == "1") {
104
+		document.querySelector('#'+newName+' #range'+Questions).style.display = "block";
105
+	} else if(type == "2") {
106
+		document.querySelector('#'+newName+' #range'+Questions).style.display = "none";
107
+	}
108
+	
109
+	document.querySelector('#'+newName+' #range'+Questions).id = 'range'+Number(Questions+1);
110
+								
111
+	document.querySelector('#'+newName+' #min_val'+Questions).name = 'min_val'+Number(Questions+1);
112
+	document.querySelector('#'+newName+' #min_val'+Questions).id = 'min_val'+Number(Questions+1);
113
+								
114
+	document.querySelector('#'+newName+' #min_text'+Questions).name = 'min_text'+Number(Questions+1);
115
+	document.querySelector('#'+newName+' #min_text'+Questions).id = 'min_text'+Number(Questions+1);
116
+    							
117
+	document.querySelector('#'+newName+' #max_val'+Questions).name = 'max_val'+Number(Questions+1);
118
+	document.querySelector('#'+newName+' #max_val'+Questions).id = 'max_val'+Number(Questions+1);
119
+
120
+	document.querySelector('#'+newName+' #max_text'+Questions).name = 'max_text'+Number(Questions+1);
121
+	document.querySelector('#'+newName+' #max_text'+Questions).id = 'max_text'+Number(Questions+1);
122
+
123
+	// Get the question type before changing it's name/id (for some reason it doesn't pass it on)
124
+	let category = $(newQuestion).find("#q_category"+Questions).val();
125
+	document.querySelector('#'+newName+' #q_category'+Questions).value = category;
126
+	document.querySelector('#'+newName+' #q_category'+Questions).name = 'q_category'+Number(Questions+1);
127
+	document.querySelector('#'+newName+' #q_category'+Questions).id = 'q_category'+Number(Questions+1);
128
+
129
+	// Get the question type before changing it's name/id (for some reason it doesn't pass it on)
130
+	let subcategory = $(newQuestion).find("#q_subcategory"+Questions).val();
131
+	document.querySelector('#'+newName+' #q_subcategory'+Questions).value = subcategory;
132
+	document.querySelector('#'+newName+' #q_subcategory'+Questions).name = 'q_subcategory'+Number(Questions+1);
133
+	document.querySelector('#'+newName+' #q_subcategory'+Questions).id = 'q_subcategory'+Number(Questions+1);
134
+								
135
+	Questions++;
136
+	
137
+// 	$('[form]:not(button[form])').keypress(function(event){if (event.which == '13') { event.preventDefault(); } } );
138
+	
139
+}
140
+
141
+
142
+
143
+// For new questionnaires, create the dropdown for category selection
144
+let categoriesString = document.querySelector('#q_categories_tentative');
145
+categoriesString.addEventListener('change', function() {
146
+
147
+	// split input by commas
148
+	let x = document.getElementById('q_categories_tentative').value.split(',');
149
+	let y;// = '<option disabled selected>Category</option>';
150
+		
151
+	// clear any whitespace from each word in the split input
152
+	for(let i = 0; i < x.length; i++) {
153
+		x[i] = x[i].trim();
154
+		
155
+		// if string not empty and not whitespace, insert as category option
156
+		if(/\S/.test(x[i])) {
157
+			y += '<option value="'+x[i]+'">'+x[i]+'</option>';
158
+		}
159
+	}
160
+	
161
+	// change the selectable categories
162
+	$("[id^=q_category]").html(y);
163
+
164
+});
165
+
166
+
167
+
168
+// For new questionnaires, create the dropdowns for subcategory selection
169
+let subcategoriesString = document.querySelector('#q_subcategories_tentative');
170
+subcategoriesString.addEventListener('change', function() {
171
+
172
+	// split input by commas
173
+	let x = document.getElementById('q_subcategories_tentative').value.split(',');
174
+	let y;// = '<option disabled selected>Subcategory</option>';
175
+		
176
+	// clear any whitespace from each word in the split input
177
+	for(let i = 0; i < x.length; i++) {
178
+		x[i] = x[i].trim();
179
+		
180
+		// if string not empty and not whitespace, insert as category option
181
+		if(/\S/.test(x[i])) {
182
+			y += '<option value="'+x[i]+'">'+x[i]+'</option>';
183
+		}
184
+	}
185
+	
186
+	// change the selectable categories
187
+	$("[id^=q_subcategory]").html(y);
188
+
189
+});
190
+
191
+
192
+
193
+// For new moments, create the dropdowns for question selection
194
+let correspondingQuestionnaire = document.querySelector('select#m_questionnaire');
195
+correspondingQuestionnaire.addEventListener('change', function() {
196
+	$.post(document.location.protocol + "//tania.uprrp.edu/admin_nuevo/special.php",
197
+		{
198
+			id_questionnaire: correspondingQuestionnaire.value
199
+		},
200
+		function(data, status) {
201
+			$("select[id^=m_question_]").html(data);
202
+		}
203
+	);
204
+});
205
+
206
+
207
+
208
+// Target the input fields to be updated
209
+let newStartDate = document.querySelector('input[name=newStart]');
210
+let newEndDate = document.querySelector('input[name=newEnd]');
211
+let newDuration = document.querySelector('input[name=newDuration]');
212
+
213
+
214
+
215
+var selectableQuestions = 1;
216
+function addSelectableQuestion() {
217
+
218
+	var br = document.createElement("br");
219
+	document.querySelector('#qq'+selectableQuestions).parentElement.lastElementChild.previousElementSibling.previousElementSibling.insertAdjacentElement('afterend', br);
220
+	
221
+	// We create a copy of the dropdown list we already have, so multiple questions can be added at the same time.
222
+	var newQuestion = document.getElementById("qq"+selectableQuestions);
223
+	var clone = newQuestion.cloneNode(true);
224
+
225
+	//The clones will have the same name as the original but with a number that will distinguish them
226
+	var newName = 'qq' + Number(selectableQuestions + 1);
227
+	clone.id = newName;
228
+	
229
+	document.querySelector('#qq'+selectableQuestions).parentElement.lastElementChild.previousElementSibling.previousElementSibling.insertAdjacentElement('afterend', clone);
230
+    							
231
+	document.querySelector('#'+newName+' h4').innerHTML = 'Question '+Number(selectableQuestions+1);
232
+    							
233
+	document.querySelector('#'+newName+' #m_question_'+selectableQuestions).name = 'm_question_'+Number(selectableQuestions+1);
234
+	document.querySelector('#'+newName+' #m_question_'+selectableQuestions).id = 'm_question_'+Number(selectableQuestions+1);
235
+								
236
+	selectableQuestions++;
237
+	
238
+// 	$('[form]:not(button[form])').keypress(function(event){if (event.which == '13') { event.preventDefault(); } } );
239
+
240
+}
241
+
242
+

+ 5
- 0
js/viewMoment.js View File

@@ -0,0 +1,5 @@
1
+function newThing(e) {
2
+	let type = e.currentTarget.value;
3
+	let range = e.currentTarget.parentNode.parentNode.parentNode.nextElementSibling; // get the 4 (optional) inputs for scaled-type questions
4
+	range.style.display = (type === "1") ? 'block' : 'none'; // "1" corresponds to scaled questions
5
+}

+ 5
- 0
js/viewQuestionnaire.js View File

@@ -0,0 +1,5 @@
1
+function newThing(e) {
2
+	let type = e.currentTarget.value;
3
+	let range = e.currentTarget.parentNode.parentNode.parentNode.nextElementSibling; // get the 4 (optional) inputs for scaled-type questions
4
+	range.style.display = (type === "1") ? 'block' : 'none'; // "1" corresponds to scaled questions
5
+}

BIN
nameOfTheQuestionnair.xlsx View File


+ 342
- 0
old_code/bankOfQuestions.php View File

@@ -0,0 +1,342 @@
1
+<?php
2
+
3
+	require_once 'processes/config.php';
4
+	require_once 'processes/dbh.inc.php';
5
+	require_once 'processes/checkLogin.php';
6
+	include_once 'header.php';
7
+	
8
+	// IF USER HAS QUESTIONS, DISPLAY THEM
9
+	// ELSE DON'T DISPLAY THE EMPTY TABLE
10
+	// CAMBIAR $query A "SELECT * FROM `question` WHERE `id_researcher`='".$dbUserData['id_researcher']."';"
11
+	$query1 = "SELECT * FROM `question` WHERE `id_category` IN(SELECT `id` FROM `category`) AND `id_subcategory` IN(SELECT `id` FROM `subcategory`);";
12
+	$result1 = mysqli_query($connection, $query1);
13
+	$x = 1;
14
+	
15
+?>  
16
+		<!-- START OF bankOfQuestions.php -->
17
+		<div class='container'>
18
+		
19
+			<div class='row'>
20
+				<div class='col-sm-10'>
21
+					<h2>Bank Of Questions</h2>
22
+					<p>View, add, and delete any question you like so that, later on, you can create a questionnaire.</p>
23
+				</div>
24
+				<div class='col-sm-2'>
25
+					<br><br>
26
+					<button id='adding' type='button' class='btn btn-default' data-toggle='modal' data-target='#New'>Add Question</button>
27
+				</div>
28
+			</div><!--row-->
29
+		
30
+			<div class='row'><div class='col'><br><hr><br></div></div>
31
+			
32
+			<?php if($result1): ?>
33
+			<div class='row'>
34
+				<div class='col'>
35
+					<table class='table table-hover table-striped' id='tableEvaluations'>
36
+						<thead>
37
+							<tr>
38
+								<th><h4>#</h4></th>
39
+								<th><h4>Premise</h4></th>
40
+								<th><h4>Category</h4></th>
41
+								<th><h4>Subcategory</h4></th>
42
+							</tr>
43
+						</thead>
44
+						<tbody>
45
+						<?php
46
+							while($row = mysqli_fetch_array($result1)):
47
+								$subquery1 = "SELECT `category`.`categoria` FROM `category` WHERE `category`.`id`=(SELECT `question`.`id_category` FROM `question` WHERE `question`.`id`=".$row['id'].");";
48
+								$subresult1 = mysqli_query($connection, $subquery1);
49
+								$subrow1 = mysqli_fetch_array($subresult1);
50
+								$subquery2 = "SELECT `subcategory`.`subcategoria` FROM `subcategory` WHERE `subcategory`.`id`=(SELECT `question`.`id_subcategory` FROM `question` WHERE `question`.`id`=".$row['id'].");";
51
+								$subresult2 = mysqli_query($connection, $subquery2);
52
+								$subrow2 = mysqli_fetch_array($subresult2);
53
+						?>
54
+							<tr>
55
+								<th><?php echo $row['id']; ?></th>
56
+								<td class='text-justify' style='width:35em;'><p><?php echo $row['premise']; ?></p></td>
57
+								<td style='width:18em;'><p><?php echo $subrow1['categoria']; ?></p></td>
58
+								<td style='width:18em;'><p><?php echo $subrow2['subcategoria']; ?></p></td>
59
+								<td style='text-align:center;width:10em;'>
60
+									<div class='btn-group'>
61
+										<button type='button' class='btn btn-default btn-sm' data-toggle='modal' data-target='#Edit_<?php echo $row['id']; ?>'>Edit</button>
62
+										<button type='button' class='btn btn-danger btn-sm' data-toggle='modal' data-target='#Delete_<?php echo $row['id']; ?>'>Delete</button>
63
+									</div>
64
+								</td>
65
+							</tr>
66
+						<?php $x++; endwhile; ?>
67
+						</tbody>
68
+					</table>
69
+				</div><!--col-->
70
+			</div><!--row-->
71
+			<?php endif; ?>
72
+			
73
+		</div><!--container-->
74
+		
75
+		<!-- POPUP FOR NEW QUESTION -->
76
+		<form class='form-horizontal' action='processes/insertQuestion.php' method='POST'>
77
+			<div class='modal fade' id='New' tabindex='-1' role='dialog' aria-labelledby='NewLabel' aria-hidden='true'>
78
+				<div class='modal-dialog modal-dialog-centered' role='document'>
79
+ 					<div class='modal-content'>
80
+						
81
+						<div class='modal-header'>
82
+			  	 	  		<h3 class='modal-title' id='NewLabel'>New Question<button type='button' class='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button></h3>
83
+   						</div>
84
+ 						
85
+ 						<div class='modal-body'>
86
+
87
+							
88
+							
89
+							<br>
90
+							<!-- PREMISE -->
91
+							<div class='form-group'>
92
+								<label class='col-sm-offset-1 control-label col-sm-2' for='question_premise'>Premise:</label>
93
+								<div class='col-sm-7'>
94
+									<textarea type='text' class='form-control' id='question_premise' name='question_premise' rows=4 style='resize:vertical'></textarea>
95
+								</div>
96
+							</div>
97
+
98
+							<!-- CATEGORY -->
99
+							<div class='form-group'>
100
+								<label class='col-sm-offset-1 control-label col-sm-2' for='question_category'>Category:</label>
101
+								<div class='col-sm-7'>
102
+									<select name='question_category' id='question_category' style='width:100%;'>
103
+										<option disabled selected>Select the Category</option>
104
+										<?php
105
+											// CAMBIAR $query A "SELECT `id`, `categoria` FROM `category` WHERE `id_researcher`='".$dbUserData['id_researcher']."';"
106
+											$query2 = "SELECT `id`, `categoria` FROM `category`;";
107
+											$result2 = mysqli_query($connection, $query2);
108
+											foreach($result2 as $categorias):
109
+										?>
110
+										<option value="<?php echo $categorias['id']; ?>"><?php echo $categorias['categoria']; ?></option>
111
+										<?php endforeach; ?>
112
+									</select>
113
+ 								</div>
114
+							</div>
115
+
116
+							<!-- SUBCATEGORY -->
117
+							<div class='form-group'>
118
+								<label class='col-sm-offset-1 control-label col-sm-2' for='question_subcategory'>Subcategory:</label>
119
+								<div class='col-sm-7'>
120
+									<select name='question_subcategory' id='question_subcategory' style='width:100%;'>
121
+										<option disabled selected>Select the Subcategory</option>
122
+										<?php
123
+											// CAMBIAR $query A "SELECT `id`, `subcategoria` FROM `subcategory` WHERE `id_researcher`='".$dbUserData['id_researcher']."';"
124
+											$query3 = "SELECT `id`, `subcategoria` FROM `subcategory`;";
125
+											$result3 = mysqli_query($connection, $query3);
126
+											foreach($result3 as $subcategorias):
127
+										?>
128
+										<option value="<?php echo $subcategorias['id']; ?>"><?php echo $subcategorias['subcategoria']; ?></option>
129
+										<?php endforeach; ?>
130
+									</select>
131
+ 								</div>
132
+							</div>
133
+
134
+							<!-- TYPE -->
135
+							<div class='form-group'>
136
+								<label class='col-sm-offset-1 control-label col-sm-2' for='question_type'>Type:</label>
137
+								<div class='col-sm-7'>
138
+									<select name='question_type' id='question_type' style='width:100%;'>
139
+										<option disabled selected>Select the Type of Question</option>
140
+										<?php
141
+											// CAMBIAR $query A "SELECT `id`, `description` FROM `type_of_question` WHERE `id_researcher`='".$dbUserData['id_researcher']."';"
142
+											$query4 = "SELECT `id`, `description` FROM `type_of_question`;";
143
+											$result4 = mysqli_query($connection, $query4);
144
+											foreach($result4 as $types):
145
+										?>
146
+										<option value="<?php echo $types['id']; ?>"><?php echo $types['description']; ?></option>
147
+										<?php endforeach; ?>
148
+									</select>
149
+								</div>
150
+							</div>
151
+
152
+							<!-- REFERENCE -->
153
+							<div class='form-group'>
154
+								<label class='col-sm-offset-1 control-label col-sm-2' for='question_reference'>Reference:</label>
155
+								<div class='col-sm-7'>
156
+									<select name='question_reference' id='question_reference' style='width:100%;'>
157
+										<option disabled selected>Select the Reference</option>
158
+										<?php
159
+											// CAMBIAR $query A "SELECT `id`, `referencia` FROM `reference` WHERE `id_researcher`='".$dbUserData['id_researcher']."';"
160
+											$query5 = "SELECT `id`, `referencia` FROM `reference`;";
161
+											$result5 = mysqli_query($connection, $query5);
162
+											foreach($result5 as $references):
163
+										?>
164
+										<option value="<?php echo $references['id']; ?>"><?php echo $references['referencia']; ?></option>
165
+										<?php endforeach; ?>
166
+									</select>
167
+								</div>
168
+							</div>
169
+							<br>
170
+
171
+
172
+
173
+      					</div><!--modal-body-->
174
+      					
175
+      					<!-- SUBMIT OR CANCEL -->
176
+     					<div class='modal-footer'>
177
+       						<button type='button' class='btn btn-default' data-dismiss='modal'>Cancel</button>
178
+        					<button type='submit' class='btn btn-primary' name='insertQuestion' disabled>Save</button>
179
+      					</div>
180
+      					
181
+    				</div><!--modal-content-->
182
+  				</div><!--modal-dialog-->
183
+			</div><!--modal-->
184
+		</form>
185
+		
186
+		<?php $result1 = mysqli_query($connection, $query1); ?>
187
+		<?php while($row = mysqli_fetch_array($result1)): ?>
188
+		<!-- POPUP FOR EDIT QUESTION -->
189
+		<form class='form-horizontal' action='processes/updateQuestion.php' method='POST'>
190
+			<div class='modal fade' id='Edit_<?php echo $row['id']; ?>' tabindex='-1' role='dialog' aria-labelledby='EditLabel_<?php echo $row['id']; ?>' aria-hidden='true'>
191
+				<div class='modal-dialog modal-dialog-centered' role='document'>
192
+ 					<div class='modal-content'>
193
+						
194
+						<div class='modal-header'>
195
+			  	 	  		<h3 class='modal-title' id='EditLabel_<?php echo $row['id']; ?>'>Edit Question<button type='button' class='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button></h3>
196
+   						</div>
197
+ 						
198
+ 						<div class='modal-body'>
199
+
200
+							
201
+							
202
+							<br>
203
+							<!-- PREMISE -->
204
+							<div class='form-group'>
205
+								<label class='col-sm-offset-1 control-label col-sm-2' for='newPremise'>Premise:</label>
206
+								<div class='col-sm-7'>
207
+									<textarea type='text' class='form-control' id='newPremise' name='newPremise' rows=4 style='resize:vertical'><?php echo $row['premise']; ?></textarea>
208
+								</div>
209
+							</div>
210
+
211
+							<!-- CATEGORY -->
212
+							<div class='form-group'>
213
+								<label class='col-sm-offset-1 control-label col-sm-2' for='newCategory'>Category:</label>
214
+								<div class='col-sm-7'>
215
+									<select name='newCategory' id='newCategory' style='width:100%;'>
216
+										<option disabled selected>Select the Category</option>
217
+										<?php
218
+											// CAMBIAR $query A "SELECT `id`, `categoria` FROM `category` WHERE `id_researcher`='".$dbUserData['id_researcher']."';"
219
+											$query2 = "SELECT `id`, `categoria` FROM `category`;";
220
+											$result2 = mysqli_query($connection, $query2);
221
+											foreach($result2 as $categorias):
222
+										?>
223
+										<option value="<?php echo $categorias['id']; ?>"><?php echo $categorias['categoria']; ?></option>
224
+										<?php endforeach; ?>
225
+									</select>
226
+ 								</div>
227
+							</div>
228
+
229
+							<!-- SUBCATEGORY -->
230
+							<div class='form-group'>
231
+								<label class='col-sm-offset-1 control-label col-sm-2' for='newSubcategory'>Subcategory:</label>
232
+								<div class='col-sm-7'>
233
+									<select name='newSubcategory' id='newSubcategory' style='width:100%;'>
234
+										<option disabled selected>Select the Subcategory</option>
235
+										<?php
236
+											// CAMBIAR $query A "SELECT `id`, `subcategoria` FROM `subcategory` WHERE `id_researcher`='".$dbUserData['id_researcher']."';"
237
+											$query3 = "SELECT `id`, `subcategoria` FROM `subcategory`;";
238
+											$result3 = mysqli_query($connection, $query3);
239
+											foreach($result3 as $subcategorias):
240
+										?>
241
+										<option value="<?php echo $subcategorias['id']; ?>"><?php echo $subcategorias['subcategoria']; ?></option>
242
+										<?php endforeach; ?>
243
+									</select>
244
+ 								</div>
245
+							</div>
246
+
247
+							<!-- TYPE -->
248
+							<div class='form-group'>
249
+								<label class='col-sm-offset-1 control-label col-sm-2' for='newType'>Type:</label>
250
+								<div class='col-sm-7'>
251
+									<select name='newType' id='newType' style='width:100%;'>
252
+										<option disabled selected>Select the Type of Question</option>
253
+										<?php
254
+											// CAMBIAR $query A "SELECT `id`, `description` FROM `type_of_question` WHERE `id_researcher`='".$dbUserData['id_researcher']."';"
255
+											$query4 = "SELECT `id`, `description` FROM `type_of_question`;";
256
+											$result4 = mysqli_query($connection, $query4);
257
+											foreach($result4 as $types):
258
+										?>
259
+										<option value="<?php echo $types['id']; ?>"><?php echo $types['description']; ?></option>
260
+										<?php endforeach; ?>
261
+									</select>
262
+								</div>
263
+							</div>
264
+
265
+							<!-- REFERENCE -->
266
+							<div class='form-group'>
267
+								<label class='col-sm-offset-1 control-label col-sm-2' for='newReference'>Reference:</label>
268
+								<div class='col-sm-7'>
269
+									<select name='newReference' id='newReference' style='width:100%;'>
270
+										<option disabled selected>Select the Reference</option>
271
+										<?php
272
+											// CAMBIAR $query A "SELECT `id`, `referencia` FROM `reference` WHERE `id_researcher`='".$dbUserData['id_researcher']."';"
273
+											$query5 = "SELECT `id`, `referencia` FROM `reference`;";
274
+											$result5 = mysqli_query($connection, $query5);
275
+											foreach($result5 as $references):
276
+										?>
277
+										<option value="<?php echo $references['id']; ?>"><?php echo $references['referencia']; ?></option>
278
+										<?php endforeach; ?>
279
+									</select>
280
+								</div>
281
+							</div>
282
+							<br>
283
+
284
+
285
+
286
+      					</div><!--modal-body-->
287
+      					
288
+      					<!-- SUBMIT OR CANCEL -->
289
+     					<div class='modal-footer'>
290
+       						<button type='button' class='btn btn-default' data-dismiss='modal'>Cancel</button>
291
+        					<button type='submit' class='btn btn-primary' name='updateQuestion' disabled>Save</button>
292
+      					</div>
293
+      					
294
+    				</div><!--modal-content-->
295
+  				</div><!--modal-dialog-->
296
+			</div><!--modal-->
297
+		</form>
298
+		
299
+		<!-- POPUP FOR DELETE QUESTION -->
300
+		<form class='form-horizontal' action='processes/deleteQuestion.php' method='POST'>
301
+			<div class='modal fade' id='Delete_<?php echo $row['id']; ?>' tabindex='-1' role='dialog' aria-labelledby='DeleteLabel_<?php echo $row['id']; ?>' aria-hidden='true'>
302
+				<div class='modal-dialog modal-dialog-centered' role='document'>
303
+ 					<div class='modal-content'>
304
+
305
+						<div class='modal-header'>
306
+			  	 	  		<h3 class='modal-title' id='DeleteLabel_<?php echo $row['id']; ?>'>Delete Question<button type='button' class='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button></h3>
307
+   						</div>
308
+
309
+ 						<div class='modal-body'>
310
+
311
+
312
+
313
+ 							<!-- ID -->
314
+ 							<input type='hidden' name='id' value='<?php echo $row['id']; ?>'>
315
+ 							
316
+							<span class='text-center'>
317
+								<h3>Are you sure you want to delete this question?</h3>
318
+								<h3 style='color:#ff8f00;'><?php echo $row['premise']; ?></h3>
319
+							</span>
320
+							
321
+							<br>
322
+							<p class='alert alert-warning text-justify'>This action will delete the question, removing it from existing <b>questionnaires and subquestionnaires</b>, while also deleting <b>all results</b> that were made from this question. You should be aware of this and opt to edit manually any affected questionnaires and subquestionnaires in the following pages: <a class='alert-link' href='bankOfQuestions.php'>questions</a> and <a class='alert-link' href='questionnaires.php'>questionnaires</a>.</p>
323
+							<br>
324
+							
325
+							
326
+							
327
+      					</div><!--modal-body-->
328
+      					
329
+      					<!-- SUBMIT OR CANCEL -->
330
+     					<div class='modal-footer'>
331
+       						<button type='button' class='btn btn-default' data-dismiss='modal'>Cancel</button>
332
+        					<button type='submit' class='btn btn-danger' name='deleteQuestion' disabled>Delete Anyway</button>
333
+      					</div>
334
+      					
335
+    				</div><!--modal-content-->
336
+  				</div><!--modal-dialog-->
337
+			</div><!--modal-->
338
+		</form>
339
+		<?php endwhile; ?>		
340
+		<!-- END OF bankOfQuestions.php -->
341
+
342
+<?php include_once 'footer.php'; ?>

+ 240
- 0
old_code/categories.php View File

@@ -0,0 +1,240 @@
1
+<?php 
2
+	
3
+	require_once 'processes/config.php';
4
+	require_once 'processes/dbh.inc.php';
5
+	require_once 'processes/checkLogin.php';
6
+	include_once 'header.php';
7
+	
8
+	// IF USER HAS CATEGORIES, DISPLAY THEM
9
+	// ELSE DON'T DISPLAY THE EMPTY TABLE
10
+	// CAMBIAR $query A "SELECT * FROM `category` WHERE `id_researcher`='".$dbUserData['id_researcher']."';"
11
+	$query1 = "SELECT * FROM `category`;";
12
+	$result1 = mysqli_query($connection, $query1);
13
+	$x = 1;
14
+	
15
+?>
16
+		
17
+		<!-- START OF categories.php -->
18
+		<div class='container'>
19
+		
20
+			<div class='row'>
21
+				<div class='col-sm-10'>
22
+					<h2>Categories</h2>
23
+					<p>View, add, and delete any category you like so that, later on, you can categorize a question. You can also view, add, or delete any subcategory.</p>
24
+				</div>
25
+				<div class='col-sm-2'>
26
+					<br><br>
27
+					<button id='adding' type='button' class='btn btn-default' data-toggle='modal' data-target='#New'>Add Category</button>
28
+				</div>
29
+			</div><!--row-->
30
+			
31
+			<div class='row'><div class='col'><br><hr><br></div></div>
32
+			
33
+			<?php if($result1): ?>
34
+			<div class='row'>
35
+				<div class='col'>
36
+					<!-- DISPLAY AVAILABLE CATEGORIES -->
37
+					<table class='table table-hover table-striped' id='tableEvaluations' align='center'>
38
+						<thead>
39
+							<tr>
40
+								<th><h4>#</h4></th>
41
+								<th><h4>Category</h4></th>
42
+								<th><h4>Related Subcategories</h4></th>
43
+							</tr>
44
+						</thead>
45
+						<tbody>
46
+						<?php while($row = mysqli_fetch_array($result1)): ?>
47
+							<tr>
48
+								<th><?php echo $row['id']; ?></th>
49
+								<td><?php echo $row['categoria']; ?></td>
50
+								<td>
51
+									<ul>
52
+									<?php 
53
+										$query2 = "SELECT * FROM `subcategory` WHERE `id_categoria`=".$row['id'].";";
54
+										$result2 = mysqli_query($connection, $query2);
55
+										while($subrow = mysqli_fetch_array($result2)):
56
+									?>
57
+										<li><?php echo $subrow['subcategoria']; ?></li>
58
+									<?php endwhile; ?>
59
+									</ul>
60
+								</td>
61
+								<td style='text-align:center;'>
62
+									<div class='btn-group'>
63
+										<button type='button' class='btn btn-default btn-sm' data-toggle='modal' data-target='#Edit_<?php echo $row['id']; ?>'>Edit</button>
64
+										<button type='button' class='btn btn-danger btn-sm' data-toggle='modal' data-target='#Delete_<?php echo $row['id']; ?>'>Delete</button>
65
+									</div>
66
+								</td>
67
+							</tr>
68
+						<?php $x++; endwhile; ?>
69
+						</tbody>
70
+					</table>
71
+				</div><!--col-->
72
+			</div><!--row-->
73
+			<?php endif; ?>
74
+		
75
+		</div><!--container-->
76
+
77
+		<!-- POPUP FOR NEW CATEGORY -->
78
+		<form class='form-horizontal' action='processes/insertCategory.php' method='POST'>
79
+			<div class='modal fade' id='New' tabindex='-1' role='dialog' aria-labelledby='NewLabel' aria-hidden='true'>
80
+				<div class='modal-dialog modal-dialog-centered modal-lg' role='document'>
81
+ 					<div class='modal-content'>
82
+ 						<div class='modal-body'>
83
+
84
+
85
+
86
+							<!-- CLOSE BUTTON -->
87
+							<button type='button' class='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button>
88
+
89
+							<!-- NEW TITLE -->
90
+							<br>
91
+							<div class='form-group'>
92
+								<label class='col-sm-2 control-label'>Title:</label>
93
+								<div class='col-sm-7'>
94
+   									<input class='form-control' type='text' name='categoria'>
95
+ 								</div>
96
+ 								<button type='submit' class='btn btn-primary' name='insertCategory' disabled>Save</button>
97
+       						</div>
98
+
99
+
100
+
101
+      					</div><!--modal-body-->
102
+    				</div><!--modal-content-->
103
+  				</div><!--modal-dialog-->
104
+			</div><!--modal-->
105
+		</form>
106
+
107
+		<?php $result1 = mysqli_query($connection, $query1); ?>
108
+		<?php while($row = mysqli_fetch_array($result1)): ?>
109
+		<!-- POPUP FOR EDIT CATEGORY -->
110
+		<form class='form-horizontal' action='processes/updateCategory.php' method='POST'>
111
+			<div class='modal fade' id='Edit_<?php echo $row['id']; ?>' tabindex='-1' role='dialog' aria-labelledby='EditLabel_<?php echo $row['id']; ?>' aria-hidden='true'>
112
+				<div class='modal-dialog modal-dialog-centered' role='document'>
113
+ 					<div class='modal-content'>
114
+						
115
+						<div class='modal-header'>
116
+			  	 	  		<h3 class='modal-title' id='EditLabel_<?php echo $row['id']; ?>'>Edit Category<button type='button' class='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button></h3>
117
+   						</div>
118
+ 						
119
+ 						<div class='modal-body'>
120
+
121
+							
122
+							
123
+							<span class='text-center'>
124
+								<h3 style='color:#ff8f00;'><?php echo $row['categoria']; ?></h3>
125
+								<br>
126
+								<h4>Subcategories:</h4>
127
+								<h6>(check the ones you wish to delete)</h6>
128
+							</span>
129
+							<br>
130
+							<div class='row'>
131
+								<div class='col'>
132
+									<ul>
133
+									<?php 
134
+										$query2 = "SELECT * FROM `subcategory` WHERE `id_categoria`=".$row['id'].";";
135
+										$result2 = mysqli_query($connection, $query2);
136
+										while($subrow = mysqli_fetch_array($result2)):
137
+									?>
138
+										<div class='row'>
139
+											<li class='col-sm-offset-3 col-sm-5'><?php echo $subrow['subcategoria']; ?></li>
140
+											<input class='col-sm-1' type='checkbox' name='deleteSubcategory_<?php $subrow['id']; ?>' value='<?php $subrow['id']; ?>'>
141
+											<!--<li style='list-style:none;' class='col-sm-3'><a class='btn btn-danger btn-xs' href='#'>Remove</a></li>-->
142
+										</div>
143
+										<br>
144
+									<?php endwhile; ?>
145
+									</ul>
146
+								</div>
147
+							</div>
148
+							<br>
149
+							<div class='form-group'>
150
+								<label class='col-sm-offset-1 control-label col-sm-3' for='newSubcategory'>Add Subcategory:</label>
151
+								<div class='col-sm-5' id='addQuestionnaires'>
152
+									<!-- OJO TENGO QUE NOMBRAR EL ID DEL SELECT DIFERENTE-->
153
+									<select id='questionnaire' name='newSubcategory' style='width:100%;'>
154
+										<option disabled selected>Select the Subcategory</option>
155
+										<?php
156
+											// CAMBIAR $query A "SELECT * FROM `subcategory` WHERE `id_categoria`=".$row['id']." AND `id_researcher`='".$dbUserData['id_researcher']."';"
157
+											$query3 = "SELECT * FROM `subcategory`;";
158
+											$result3 = mysqli_query($connection, $query3);
159
+											foreach($result3 as $subcategories):
160
+										?>
161
+										<option value="<?php echo $subcategories['id']; ?>"><?php echo $subcategories['subcategoria']; ?></option>
162
+										<?php endforeach; ?>
163
+									</select>
164
+								</div>
165
+								<!-- ADD MORE SUBCATEGORIES -->
166
+								<div class='col-sm-2'>
167
+									<button type='button' class='btn btn-xs btn-warning' onclick='AddQuestionnaire()' style='color: white;'><b>Add More</b></button>
168
+								</div>
169
+							</div>
170
+							
171
+
172
+
173
+							
174
+							
175
+							
176
+							<br>
177
+							<p class='alert alert-warning text-justify'>Deleting any selected subcategory will change every <b>question</b> associated with it to have an <b>unknown subcategory</b>. You should be aware of this and opt to edit manually any affected question in the following page: <a class='alert-link' href='bankOfQuestions.php'>questions</a>.</p>
178
+							<br>
179
+
180
+
181
+
182
+      					</div><!--modal-body-->
183
+      					
184
+      					<!-- SUBMIT OR CANCEL -->
185
+     					<div class='modal-footer'>
186
+       						<button type='button' class='btn btn-default' data-dismiss='modal'>Cancel</button>
187
+        					<button type='submit' class='btn btn-primary' name='updateCategory' disabled>Save</button>
188
+      					</div>
189
+      					
190
+    				</div><!--modal-content-->
191
+  				</div><!--modal-dialog-->
192
+			</div><!--modal-->
193
+		</form>
194
+		
195
+		<!-- POPUP FOR DELETE CATEGORY -->
196
+		<form class='form-horizontal' action='processes/deleteCategory.php' method='POST'>
197
+			<div class='modal fade' id='Delete_<?php echo $row['id']; ?>' tabindex='-1' role='dialog' aria-labelledby='DeleteLabel_<?php echo $row['id']; ?>' aria-hidden='true'>
198
+				<div class='modal-dialog modal-dialog-centered' role='document'>
199
+ 					<div class='modal-content'>
200
+
201
+						<div class='modal-header'>
202
+			  	 	  		<h3 class='modal-title' id='DeleteLabel_<?php echo $row['id']; ?>'>Delete Category<button type='button' class='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button></h3>
203
+   						</div>
204
+
205
+ 						<div class='modal-body'>
206
+
207
+
208
+
209
+ 							<!-- ID -->
210
+ 							<input type='hidden' name='id' value='<?php echo $row['id']; ?>'>
211
+ 							
212
+							<span class='text-center'>
213
+								<h3>Are you sure you want to delete this category?</h3>
214
+								<h3 style='color:#ff8f00;'><?php echo $row['categoria']; ?></h3>
215
+							</span>
216
+							
217
+							<br>
218
+							<p class='alert alert-warning text-justify'>This action will delete the category and change every <b>question</b> associated with it to have an <b>unknown category (and subcategory)</b>. It will also delete any associated subcategory stored in the database. You should be aware of this and opt to edit manually any affected question in the following page: <a class='alert-link' href='bankOfQuestions.php'>questions</a>.</p>
219
+							<br>
220
+
221
+
222
+
223
+      					</div><!--modal-body-->
224
+      					
225
+      					<!-- SUBMIT OR CANCEL -->
226
+     					<div class='modal-footer'>
227
+       						<button type='button' class='btn btn-default' data-dismiss='modal'>Cancel</button>
228
+        					<button type='submit' class='btn btn-danger' name='deleteCategory' disabled>Delete Anyway</button>
229
+      					</div>
230
+      					
231
+    				</div><!--modal-content-->
232
+  				</div><!--modal-dialog-->
233
+			</div><!--modal-->
234
+		</form>
235
+		<?php endwhile; ?>
236
+		<!-- END OF categories.php -->
237
+
238
+<?php
239
+	include_once 'footer.php';
240
+?>

+ 6
- 0
old_code/conection.php View File

@@ -0,0 +1,6 @@
1
+<?php
2
+	$un = "proyecto_ema";
3
+	$up = "RUYCwNr2Xwah3PET";
4
+	$dbconnection = mysqli_connect("localhost", $un, $up, "proyecto.ema.upr") or die(mysqli_error());
5
+	mysqli_set_charset($dbconnection, 'utf8');
6
+?>

+ 37
- 0
old_code/deleteQuestion.php View File

@@ -0,0 +1,37 @@
1
+<!--- 
2
+
3
+Developer: Coralys Cubero Rivera
4
+Fall 2018
5
+
6
+This script deletes a selected row from the 'questions' table and then returns 
7
+the user to the bank of questions main page. 
8
+
9
+
10
+
11
+Updated by: Víctor A. Hernández
12
+Summer 2019
13
+
14
+--->
15
+
16
+<?php
17
+
18
+	require_once 'processes/config.php';
19
+	require_once 'processes/dbh.inc.php';
20
+
21
+	// IF USER ENTERS PAGE AFTER YES BUTTON HAS BEEN PRESSED (FROM confirmDeleteQuestion.php), DELETE QUESTION FROM DATABASE
22
+	// ELSE DO NOTHING
23
+	if(isset($_GET['del'])) {
24
+		$query = "DELETE FROM `question` WHERE `id`='".$_GET['del']."';";
25
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
26
+
27
+		// HAY QUE BORRAR CADA ASOCIACIÓN PREGUNTA-TIPODEPREGUNTA (sería con un while()? o se 'seleccionan' todos y se borran a la vez?)
28
+		/*
29
+		$query = "DELETE FROM `question_type` WHERE `id_question`='".$_GET['del']."';";
30
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));	
31
+		*/
32
+		
33
+		// WHY NOT USE header INSTEAD OF window.top.location?
34
+		//header('Location: http://emaapp.online/admin_nuevo/bankOfQuestions.php');
35
+		//exit();
36
+		echo "<script>window.top.location='http://emaapp.online/admin_nuevo/bankOfQuestions.php'</script>";
37
+	}

+ 30
- 0
old_code/deleteQuestionQuestionnaire.php View File

@@ -0,0 +1,30 @@
1
+<!--- 
2
+
3
+Developer: Coralys Cubero Rivera
4
+Fall 2018
5
+
6
+This script deletes an association between a question and a questionnaire,  and then returns 
7
+the user to the 'questionnaires' main page. 
8
+
9
+
10
+
11
+Updated by: Víctor A. Hernández
12
+Summer 2019
13
+
14
+--->
15
+
16
+<?php
17
+
18
+	require_once 'processes/config.php';
19
+	require_once 'processes/dbh.inc.php';
20
+ 
21
+	// IF USER ENTERS PAGE AFTER YES BUTTON HAS BEEN PRESSED (FROM confirmDeleteQuestionQuestionnaire.php), DISASSOCIATE QUESTION FROM QUESTIONNAIRE IN THE DATABASE
22
+	// ELSE DO NOTHING
23
+	if(isset($_GET['del']) AND isset($_GET['quest'])) {
24
+		$query = "DELETE FROM `questionnair_question` WHERE `id_question`=".$_GET['del']." AND `id_questionnair`=".$_GET['quest'].";";
25
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
26
+		// WHY NOT USE header INSTEAD OF window.top.location?
27
+		//header('Location: http://emaapp.online/admin_nuevo/viewQuestionnaire.php?view=".$_GET['quest']);
28
+		//exit();
29
+		echo "<script>window.top.location='http://emaapp.online/admin_nuevo/viewQuestionnaire.php?view=".$_GET['quest']."'</script>";
30
+	}

+ 37
- 0
old_code/deleteQuestionnaire.php View File

@@ -0,0 +1,37 @@
1
+<!--- 
2
+
3
+Developer: Coralys Cubero Rivera
4
+Fall 2018
5
+
6
+This script deletes a selected row from the 'questionnaires table and then returns 
7
+the user to the questionnaires main page. 
8
+
9
+
10
+
11
+Updated by: Víctor A. Hernández
12
+Summer 2019
13
+
14
+--->
15
+
16
+<?php
17
+
18
+	require_once 'processes/config.php';
19
+	require_once 'processes/dbh.inc.php';
20
+
21
+	// IF USER ENTERS PAGE AFTER YES BUTTON HAS BEEN PRESSED (FROM confirmDeleteQuestionnaire.php), DELETE QUESTIONNAIRE FROM DATABASE
22
+	// ELSE DO NOTHING
23
+	if(isset($_GET['del'])) {
24
+		$query = "DELETE FROM `questionnair` WHERE `id`='".$_GET['del']."';";
25
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
26
+		
27
+		// HAY QUE BORRAR CADA ASOCIACIÓN CUESTIONARIO-PREGUNTA (sería con un while()? o se 'seleccionan' todos y se borran a la vez?)
28
+		/*
29
+		$query = "DELETE FROM `questionnair_question` WHERE `id_questionnair`='".$_GET['del']."';";
30
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));	
31
+		*/
32
+		
33
+		// WHY NOT USE header INSTEAD OF window.top.location?
34
+		//header('Location: http://emaapp.online/admin_nuevo/questionnaires.php');
35
+		//exit();
36
+		echo "<script>window.top.location='http://emaapp.online/admin_nuevo/questionnaires.php'</script>";
37
+	}

+ 30
- 0
old_code/deleteQuestionnaireExperience.php View File

@@ -0,0 +1,30 @@
1
+<!--- 
2
+
3
+Developer: Coralys Cubero Rivera
4
+Fall 2018
5
+
6
+This script deletes an association between a questionnaire and an experience, then returns 
7
+the user to the experiences main page. 
8
+
9
+
10
+
11
+Updated by: Víctor A. Hernández
12
+Summer 2019
13
+
14
+--->
15
+
16
+<?php
17
+	
18
+	require_once 'processes/config.php';
19
+	require_once 'processes/dbh.inc.php';
20
+	
21
+	// IF USER ENTERS PAGE AFTER YES BUTTON HAS BEEN PRESSED (FROM confirmDeleteQuestionnaireExperience.php), DISASSOCIATE QUESTIONNAIRE FROM EXPERIENCE IN THE DATABASE
22
+	// ELSE DO NOTHING
23
+	if(isset($_GET['del']) AND isset($_GET['exp'])) {		
24
+		$query = "DELETE FROM `experience_questionnair` WHERE `id_questionnair`='".$_GET['del']."' AND `id_experience`='".$_GET['exp']."';";
25
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
26
+		// WHY NOT USE header INSTEAD OF window.top.location?
27
+		//header('Location: http://emaapp.online/admin_nuevo/viewExperience.php?view='.$_GET['exp']);
28
+		//exit();
29
+		echo "<script>window.top.location='http://emaapp.online/admin_nuevo/viewExperience.php?view=".$_GET['exp']."'</script>";
30
+	}

+ 98
- 0
old_code/editExperience.php View File

@@ -0,0 +1,98 @@
1
+<!--
2
+
3
+Developer: Coralys Cubero Rivera
4
+Fall 2018
5
+
6
+This file is meant to be for editing the information stored on a selected experience. At the
7
+end of the editing, the information will be sent to another script to be updated.
8
+
9
+
10
+
11
+Updated by: Víctor A. Hernández
12
+Summer 2019
13
+
14
+-->
15
+
16
+<?php
17
+	require_once 'processes/config.php';
18
+	require_once 'processes/dbh.inc.php';
19
+	include_once 'header.php';
20
+
21
+	if (isset($_GET['edit'])) {
22
+		$query = "SELECT * FROM `experience` WHERE `id`=".$_GET['edit'].";";
23
+		$result = mysqli_query($connection, $query);
24
+		if(!$result) die("Error: ".mysqli_error($connection));
25
+		$row = mysqli_fetch_array($result);
26
+	}
27
+?>
28
+
29
+		<!-- START OF editExperience.php -->
30
+		<div class='container'>
31
+			<h2>Experience <?php echo $row[0]; ?></h2>
32
+			<form class='form-horizontal' action='updateExperience.php' method='POST'>
33
+				
34
+				<!-- ID -->
35
+				<input type='hidden' name='id' value='<?php echo $row[0]; ?>'> 
36
+				
37
+				<!-- NEW TITLE -->
38
+				<div class='form-group'>
39
+					<label class='control-label col-sm-2'>Title:</label>
40
+					<div class='col-sm-10'>
41
+						<input type='text' class='form-control' name='newTitle' value='<?php echo $row[1]; ?>'>
42
+					</div>
43
+				</div>
44
+				
45
+				<!-- NEW DESCRIPTION -->
46
+				<div class='form-group'>
47
+					<label class='control-label col-sm-2'>Description:</label>
48
+					<div class='col-sm-10'>
49
+						<textarea class='form-control' name='newDescription' rows='3' style='resize:vertical;'><?php echo $row[2]; ?></textarea>
50
+					</div>
51
+				</div>
52
+
53
+				<!-- NEW TYPE -->
54
+				<div class='form-group'>
55
+					<label class='control-label col-sm-2'>Type:</label>
56
+					<div class='col-sm-10'>
57
+						<input type='text' class='form-control' name='newType' value='<?php echo $row[3]; ?>'>
58
+					</div>
59
+				</div>
60
+				
61
+				<!-- NEW DURATION -->
62
+				<div class='form-group'>
63
+					<label class='control-label col-sm-2'>Duration:</label>
64
+					<div class='col-sm-10'>
65
+						<input type='text' class='form-control' name='newDuration' value='<?php echo $row[4]; ?>'>
66
+					</div>
67
+				</div>
68
+				
69
+				<!-- NEW START DATE -->
70
+				<div class='form-group'>
71
+					<label class='control-label col-sm-2'>Start Date:</label>
72
+					<div class='col-sm-10'>
73
+						<input type='text' class='form-control' name='newStart' value='<?php echo $row[5]; ?>'>
74
+					</div>
75
+				</div>
76
+				
77
+				<!-- NEW END DATE -->
78
+				<div class='form-group'>
79
+					<label class='control-label col-sm-2'>End Date:</label>
80
+					<div class='col-sm-10'>
81
+						<input type='text' class='form-control' name='newEnd' value='<?php echo $row[6]; ?>'>
82
+					</div>
83
+				</div>
84
+				
85
+				<!-- SUBMIT -->
86
+				<div class='form-group text-center'>
87
+					<div class='col-sm-offset-2 col-sm-10'>
88
+						<button type='submit' class='btn btn-success' name='updateExperience' style='width:200px;'>Update Experience</button>
89
+					</div>
90
+				</div>
91
+			
92
+			</form>	
93
+		</div>
94
+		<!-- END OF editExperience.php -->
95
+
96
+<?php
97
+	include_once 'footer.html';
98
+?>

+ 59
- 0
old_code/insertQuestionnaire.php View File

@@ -0,0 +1,59 @@
1
+<!--- 
2
+
3
+Developer: Coralys Cubero Rivera
4
+Fall 2018
5
+
6
+This scripts inserts a new questionnaire into our system, including each of its questions. 
7
+
8
+
9
+
10
+Updated by: Víctor A. Hernández
11
+Summer 2019
12
+
13
+--->
14
+
15
+<?php
16
+
17
+	require_once 'processes/config.php';
18
+	require_once 'processes/dbh.inc.php';
19
+
20
+	// IF USER ENTERS PAGE AFTER SUBMIT BUTTON HAS BEEN PRESSED (FROM newQuestionnaire.php), INSERT QUESTIONNAIRE TO DATABASE
21
+	// ELSE DO NOTHING
22
+	if(isset($_POST['submitQuestionnaire'])) {
23
+	
24
+		// RECIBIR TODOS LOS INPUTS DE newQuestionnaire.php (TÍTULO, DESCRIPCIÓN Y CADA PREGUNTA A AÑADIRSE AL CUESTIONARIO) 
25
+		$keys = array();
26
+		$values = array();
27
+		foreach($_POST as $key => $value) {
28
+			$keys[] = $key;
29
+			$values[] = $value;
30
+		}
31
+		
32
+		// INSERTAR A TABLA questionair EL TÍTULO Y LA DESCRIPCIÓN DEL CUESTIONARIO NUEVO
33
+		$q_title = $values[0]; // usar POST['q_title'];
34
+		$q_description = $values[1]; // usar POST['q_description'];
35
+		$query = "INSERT INTO `questionnair` (`title`, `description`) VALUES ('".$q_title."', '".$q_description."');";
36
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
37
+		
38
+		// BUSCAR id DEL CUESTIONARIO ACABADO DE INSERTAR
39
+		$query = "SELECT `id` FROM `questionnair` WHERE `title`='".$q_title."';";
40
+		$result = mysqli_query($connection, $query);
41
+		if(!$result) die("Error: ".mysqli_error($connection));
42
+		//$row = mysqli_fetch_array($result);
43
+		//$id_questionnaire = $row[0];
44
+		foreach($result as $questionnaire) $questionnaire_id = $questionnaire["id"];
45
+		
46
+		// "INSERTAR" CADA PREGUNTA DESEADA AL CUESTIONARIO NUEVO (ASOCIANDO LOS ids A TRAVÉS DE LA TABLA questionnair_question)
47
+		// WARNING: ESTO NO PROVEE PROTECCIÓN POR SI EL VALUE DEL SELECT ES '' (PREGUNTA INVÁLIDA) O SI HAY UNA PREGUNTA REPETIDA
48
+		$num_questions = sizeof($values);
49
+		for($x = 2; $x < $num_questions - 1; $x++) {
50
+			$query = "INSERT INTO `questionnair_question` (`id_questionnair`, `id_question`) VALUES ('".$questionnaire_id."', '".$values[$x]."');";
51
+			$result = mysqli_query($connection, $query);
52
+			if(!$result) die("Error: ".mysqli_error($connection));	
53
+		}
54
+			
55
+		// WHY NOT USE header INSTEAD OF window.top.location?
56
+		//header('Location: http://emaapp.online/admin_nuevo/questionnaires.php');
57
+		//exit();	
58
+		echo "<script>window.top.location='http://emaapp.online/admin_nuevo/questionnaires.php'</script>";
59
+	}

+ 32
- 0
old_code/insertQuestionnaireExperience.php View File

@@ -0,0 +1,32 @@
1
+<!--- 
2
+
3
+Developer: Coralys Cubero Rivera
4
+Fall 2018
5
+
6
+This file contains the function that allows us to associate a questionnaire that already exists, 
7
+to a particular experience. 
8
+
9
+
10
+
11
+Updated by: Víctor A. Hernández
12
+Summer 2019
13
+
14
+--->
15
+
16
+<?php
17
+
18
+	require_once 'processes/config.php';
19
+	require_once 'processes/dbh.inc.php';
20
+
21
+	// IF USER ENTERS PAGE AFTER SUBMIT BUTTON HAS BEEN PRESSED (FROM viewExperience.php), ADD QUESTIONNAIRE TO EXPERIENCE
22
+	// ELSE DO NOTHING
23
+	// WARNING: ESTO NO PROVEE PROTECCIÓN POR SI EL VALOR DEL SELECT ES '' (CUESTIONARIO INVÁLIDO) O SI YA HAY UN CUESTIONARIO REPETIDO
24
+	if(isset($_POST['submitQuestionnaireQuestion'])) {
25
+		$query = "INSERT INTO `experience_questionnair` (`id_experience`, `id_questionnair`) VALUES ('".$_POST['id_experience']."', '".$_POST['questionnaire']."');";
26
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
27
+		// WHY NOT USE header INSTEAD OF window.top.location?
28
+		//header('Location: http://emaapp.online/admin_nuevo/viewExperience.php?='.$_POST['id_experience']);
29
+		//exit();
30
+		echo "<script>window.top.location='http://emaapp.online/admin_nuevo/viewExperience.php?view=".$_POST['id_experience']."'</script>";
31
+	
32
+	}

+ 116
- 0
old_code/newExperience.php View File

@@ -0,0 +1,116 @@
1
+<?php
2
+
3
+	require_once 'processes/config.php';
4
+	require_once 'processes/dbh.inc.php';
5
+	require_once 'processes/checkLogin.php';
6
+	include_once 'header.php';
7
+
8
+?>
9
+		
10
+	<!-- START OF newExperienceP1.php -->
11
+	<body>
12
+	
13
+		<header id="main-header">
14
+        	<a id="logo" href=".">TANIA</a>
15
+        	<div id="account">
16
+        	    <a class="nav-link" href="./questionnaires.php">Questionnaire Collection</a>
17
+        	    <a class="sign-out" href="./processes/logout.php">Sign Out</a>
18
+        	</div>
19
+    	</header>
20
+		
21
+		<div class='container' style="margin-top: 12vh;">
22
+		
23
+			<br>
24
+		
25
+			<div class='row'>
26
+				<div class='col-sm-10'>
27
+					<h2>Brand New Experience <small>(Basic Info)</small></h2>
28
+					<h3><small>Start creating a new experience by first adding its basic info.</small></h3>
29
+				</div>
30
+			</div><!--row-->
31
+			
32
+			<hr>
33
+<!-- 			<div class='row'><div class='col'><br><hr><br></div></div> -->
34
+		
35
+			<form class='form-horizontal' method='POST' action='processes/insertExperience.php'>
36
+				
37
+				<!-- TITLE -->
38
+				<div class='form-group'>
39
+					<label class='control-label col-sm-2' for='e_title'>Title:</label>
40
+					<div class='col-sm-9'>
41
+						<input type='text' class='form-control text-center' id='e_title' name='title' placeholder='New Experience Title' required>
42
+					</div>
43
+				</div>
44
+				
45
+				<!-- DESCRIPTION -->
46
+				<div class='form-group'>
47
+					<label class='control-label col-sm-2' for='e_description'>Description:</label>
48
+					<div class='col-sm-9'>
49
+						<textarea class='form-control text-center' id='e_description' name='description' rows='1' style='resize:vertical;' placeholder='New Experience Description' required></textarea>
50
+					</div>
51
+				</div>
52
+				
53
+				<!-- TYPE -->
54
+				<div class='form-group'>
55
+					<label class='control-label col-sm-2' for='e_description'>Type:</label>
56
+					<div class='col-sm-9'>
57
+						<input type='text' class='form-control text-center' id='e_description' name='type' placeholder='New Experience Type' required>
58
+					</div>
59
+				</div>
60
+				
61
+				<!-- DURATION -->
62
+				<div class='form-group'>
63
+					<label class='control-label col-sm-2' for='e_description'>Duration:</label>
64
+					<div class='col-sm-9'>
65
+						<input type='number' class='form-control text-center' id='e_description' name='duration' placeholder='New Experience Duration' required>
66
+					</div>
67
+				</div>
68
+				
69
+				<!-- START DATE -->
70
+				<div class='form-group'>
71
+					<label class='control-label col-sm-2' for='e_start'>Start Date:</label>
72
+					<div class='col-sm-9'>
73
+						<input type='date' class='form-control text-center' id='e_start' name='start' placeholder='New Experience Start Date' required>
74
+					</div>
75
+				</div>
76
+				
77
+				<!-- END DATE -->
78
+				<div class='form-group'>
79
+					<label class='control-label col-sm-2' for='e_end'>End Date:</label>
80
+					<div class='col-sm-9'>
81
+						<input type='date' class='form-control text-center' id='e_end' name='end' placeholder='New Experience End Date' required>
82
+					</div>
83
+				</div>
84
+				
85
+				<!-- INSTITUTION -->
86
+				<div class='form-group'>
87
+					<label class='control-label col-sm-2' for='e_institution'>Institution:</label>
88
+					<div class='col-sm-9'>
89
+						<select id='e_institution' name='institution' style='width:100%;' required>
90
+							<option disabled selected>Select an Institution</option>
91
+							<?php
92
+								$query = "SELECT * FROM `institution`;";
93
+								$result = mysqli_query($connection, $query);
94
+								while($row = mysqli_fetch_assoc($result)):
95
+							?>
96
+							<option value='<?php echo $row['id']; ?>'><?php echo $row['name']; ?></option>
97
+							<?php endwhile; ?>
98
+						</select>
99
+					</div>
100
+				</div>
101
+				
102
+				<!-- SUBMIT -->
103
+				<br><br>
104
+				<div class='form-group text-center'>
105
+					<div class='col-sm-offset-10 col-sm-2'>
106
+						<button id='adding' type='submit' class='btn btn-default' name='submitExperience'>Create Experience</button>
107
+					</div>
108
+				</div>
109
+								
110
+			</form>
111
+		</div>
112
+	<!-- END OF newExperienceP1.php -->
113
+	
114
+	<!-- INSTITUTION, EXPERIENCE_QUESTIONNAIR, SUBQUESTIONNAIR, EXPERIENCE_SUBQUESTIONNAIR, REMINDER_SUBQUESTIONNAIR?, SCHEDULE?, REMINDER_STUDENT_SUBQUESTIONNAIR?-->
115
+	
116
+<?php include_once 'footer.php'; ?>

+ 59
- 0
old_code/subquestionnaires.php View File

@@ -0,0 +1,59 @@
1
+<!--- 
2
+
3
+Developer: Coralys Cubero Rivera
4
+Fall 2018
5
+
6
+The program displays a table listing all the subquestionnaires that are saved in our system. 
7
+It gives the user the ability to add more and to delete whichever one he doesn't want. 
8
+
9
+
10
+
11
+Updated by: Víctor A. Hernández
12
+Summer 2019
13
+
14
+--->
15
+
16
+
17
+<?php 
18
+	require_once 'processes/config.php';
19
+	require_once 'processes/dbh.inc.php';
20
+	include_once 'header.php';
21
+?>
22
+
23
+		<!-- Subquestionnaires -->
24
+    	<div class='container'>
25
+			<br>
26
+			<h3>SUB-QUESTIONNAIRES</h3>
27
+			<br>
28
+        	<a class='btn btn-info' href='newSubquestionnaire.php' style='color:white'><b> New Subquestionnaire </b></a>
29
+        	<br><br>
30
+			<table class='table table-hover' id='tableEvaluations'>
31
+      			<?php
32
+      				$query = "SELECT * FROM `subquestionnair`;";
33
+      				$result = mysqli_query($connection, $query);
34
+     			 	echo "
35
+					<thead>
36
+						<tr>
37
+							<th> ID </th>
38
+							<th> Title </th>
39
+							<th> Description </th>
40
+						</tr>
41
+					</thead>
42
+					<tbody>";
43
+					while($row = mysqli_fetch_array($result)) {
44
+						echo "<tr>";
45
+						echo "<td> <p> ".$row['id']." </p> </td>";
46
+						echo "<td> <p> ".$row['title']." </p> </td>";
47
+						echo "<td> <p> ".$row['description']." </p> </td>";
48
+						echo '<td> <a href="viewSubquestionnaire.php?view='.$row['id'].'"> <b> View </b> </a> </td>';
49
+						echo "<td> <a href='confirmDeleteSubquestionnaire.php?del=".$row['id']."'> <b> Delete </b> </a> </td>";
50
+						echo "</tr>";
51
+					}
52
+					echo "</tbody>"
53
+				?>
54
+      		</table>
55
+      	</div>
56
+	
57
+<?php
58
+	include_once 'footer.html';
59
+?>

+ 57
- 0
old_code/updateQuestionnaire.php View File

@@ -0,0 +1,57 @@
1
+<!--- 
2
+
3
+Developer: Coralys Cubero Rivera
4
+Fall 2018
5
+
6
+This scripts updates any changes made to a questionnaire when editing its information. 
7
+
8
+
9
+
10
+Updated by: Víctor A. Hernández
11
+Summer 2019
12
+
13
+--->
14
+
15
+<?php
16
+
17
+	require_once 'processes/config.php';
18
+	require_once 'processes/dbh.inc.php';
19
+
20
+	// IF USER ENTERS PAGE AFTER SUBMIT BUTTON HAS BEEN PRESSED (FROM editQuestionnaire.php), EDIT QUESTIONNAIRE FROM DATABASE
21
+	// ELSE DO NOTHING
22
+	if(isset($_POST['submitQuestionnaire'])) {
23
+
24
+		// RECIBIR TODOS LOS INPUTS DE newQuestionnaire.php (TÍTULO, DESCRIPCIÓN Y CADA PREGUNTA A AÑADIRSE AL CUESTIONARSE) 
25
+		$keys = array();
26
+		$values = array();
27
+		foreach($_POST as $key => $value) {
28
+			//echo "$value";
29
+			$keys[] = $key;
30
+			$values[] = $value;
31
+		}
32
+		
33
+		// ######ESTO NO OVERWRITEARÍA LOS FIELDS QUE NO ESTÁN SETEADOS?????#####
34
+		if(isset($_POST['newTitle']) OR isset($_POST['newDescription']) OR isset($_POST['question'])) {
35
+		
36
+			// CAMBIAR EL TÍTULO Y LA DESCRIPCIÓN DEL CUESTIONARIO EN LA TABLA questionair
37
+			$newTitle = $values[0];
38
+			$newDescription = $values[1];
39
+			$id_questionnaire = $values[2];
40
+			$query = "UPDATE `questionnair` SET `q_title`='".$newTitle."', `description`='".$newDescription."' WHERE `id`='".$id_questionnaire."';";
41
+			$result = mysqli_query($connection, $query);
42
+			if(!$result) die("Error: ".mysqli_error($connection));
43
+
44
+			// "INSERTAR" CADA PREGUNTA (ADICIONAL) DESEADA AL CUESTIONARIO EN CUESTIÓN (ASOCIANDO LOS ids CON LA TABLA questionnair_question)
45
+			$num_questions = sizeof($values);	
46
+			for ($x = 3; $x < $num_questions - 1; $x++) {
47
+				$query = "INSERT INTO `questionnair_question` (`id_questionnair`, `id_question`) VALUES ('".$id_questionnaire."', '".$values[$x]."');";
48
+				$result = mysqli_query($connection, $query);
49
+				if (!$result) die("Error: ".mysqli_error($connection));
50
+			}
51
+		}
52
+
53
+		// WHY NOT USE header INSTEAD OF window.top.location?
54
+		//header('Location: http://emaapp.online/admin_nuevo/questionnaires.php');
55
+		//exit();	
56
+		echo "<script>window.top.location='http://emaapp.online/admin_nuevo/questionnaires.php'</script>";			
57
+	}

+ 145
- 0
old_code/viewQuestionnaireExperience.php View File

@@ -0,0 +1,145 @@
1
+<!--- 
2
+
3
+Developer: Coralys Cubero Rivera
4
+Fall 2018
5
+
6
+This script allows the user to see the specific information of a questionnaire associated to an experience.
7
+ 
8
+ 
9
+ 
10
+ Updated by: Víctor A. Hernández
11
+ Summer 2019
12
+ 
13
+--->
14
+
15
+<?php
16
+
17
+	require_once 'processes/config.php';
18
+	require_once 'processes/dbh.inc.php';
19
+ 
20
+	if(isset($_GET['view'])) {
21
+		$query = "SELECT * FROM `questionnair` WHERE `id`='".$_GET['view']."';";
22
+		$result = mysqli_query($connection, $query);
23
+		if(!$result) die("Error: ".mysqli_error($connection));
24
+		$row = mysqli_fetch_array($result);
25
+	}
26
+
27
+	include_once 'header.php';
28
+?>
29
+
30
+		<div class='container'>
31
+			<br>
32
+			<h2>QUESTIONNAIRE <?php echo $row[0]; ?></h2>
33
+			<br>
34
+			<p> <font size='4'> <b> Title: </b> <?php echo $row[1]; ?> </font> </p>
35
+			<p> <font size='4'> <b> Description: </b> <?php echo $row[2]; ?> </font>
36
+				<a class='btn btn-info' style='float: right;' href='editQuestionnaire.php?edit=<?php echo $row[0]; ?>'> Edit Questionnaire </a>
37
+			</p>
38
+			<table class='table table-hover' id='tableEvaluations'>
39
+			<?php
40
+				$result = mysqli_query($connection, "SELECT `id`, `premise` FROM `question` WHERE `id` IN (SELECT `id_question` FROM `questionnair_question` WHERE `id_questionnair`='".$row[0]."');");
41
+				echo "
42
+				<thead>
43
+					<tr>
44
+						<th> ID </th>
45
+						<th> Questions </th>
46
+					</tr>
47
+				</thead>
48
+				<tbody>";
49
+				while($row = mysqli_fetch_array($result)) {
50
+					echo " <tr>";
51
+					echo "<td> <p> ".$row['id']."</p> </td>";
52
+					echo "<td> <p> ".$row['premise']." </p> </td>";
53
+					echo "</tr>";
54
+				}		
55
+				echo "</tbody>"
56
+			?>
57
+			</table>
58
+			<br><br>
59
+		</div>
60
+
61
+<?php include_once 'footer.html'; ?>
62
+
63
+<?php
64
+/*
65
+		<!-- POPUP FOR EDIT EXPERIENCE -->
66
+		<form class='form-horizontal' action='processes/updateExperience.php' method='POST'>
67
+			<div class='modal fade' id='Edit_<?php echo $row['id']; ?>' tabindex='-1' role='dialog' aria-labelledby='EditLabel_<?php echo $row['id']; ?>' aria-hidden='true'>
68
+				<div class='modal-dialog' role='document'>
69
+ 					<div class='modal-content'>
70
+						<div class='modal-header'>
71
+					   		<h3 class='modal-title' id='EditLabel_<?php echo $row['id']; ?>'>Experience Basic Info</h3>
72
+      					</div>
73
+      					<div class='modal-body'>
74
+      						
75
+      						
76
+      						
77
+      						<!-- ID -->
78
+							<input type='hidden' name='id' value='<?php echo $row['id']; ?>'>
79
+							
80
+							<!-- NEW TITLE -->
81
+							<div class='form-group form-horizontal'>
82
+								<label class='col-sm-offset-1 col-sm-2 control-label'>Title:</label>
83
+								<div class='col-sm-8'>
84
+       								<input class='form-control' type='text' name='newTitle' value='<?php echo $row['title']; ?>'>
85
+								</div>
86
+							</div>
87
+       										
88
+       						<!-- NEW DESCRIPTION -->
89
+							<div class='form-group form-horizontal'>
90
+								<label class='col-sm-offset-1 col-sm-2 control-label'>Description:</label>
91
+								<div class='col-sm-8'>
92
+	   								<input class='form-control' type='text' name='newDescription' value='<?php echo $row['description']; ?>'>
93
+								</div>
94
+							</div>
95
+												
96
+							<!-- NEW TYPE -->
97
+							<div class='form-group form-horizontal'>
98
+    							<label class='col-sm-offset-1 col-sm-2 control-label'>Type:</label>
99
+								<div class='col-sm-8'>
100
+   	 								<input class='form-control' type='text' name='newType' value='<?php echo $row['type']; ?>'>
101
+								</div>
102
+   	    					</div>
103
+       											
104
+       						<!-- NEW DURATION -->
105
+							<div class='form-group form-horizontal'>
106
+   	    						<label class='col-sm-offset-1 col-sm-2 control-label'>Duration:</label>
107
+   	    						<div class='col-sm-8'>
108
+   	 								<input class='form-control' type='text' name='newDuration' value='<?php echo $row['duration_weeks']; ?>'>
109
+   								</div>
110
+   	    					</div>
111
+       											
112
+       						<!-- NEW START -->
113
+
114
+							<div class='form-group form-horizontal'>
115
+								<label class='col-sm-offset-1 col-sm-2 control-label'>Start Date:</label>
116
+								<div class='col-sm-8'>
117
+									<input class='form-control' type='text' name='newStart' value='<?php echo $row['start_date']; ?>'>
118
+								</div>
119
+							</div>
120
+
121
+												
122
+							<!-- NEW END -->
123
+							<div class='form-group form-horizontal'>
124
+								<label class='col-sm-offset-1 col-sm-2 control-label'>End Date:</label>
125
+								<div class='col-sm-8'>
126
+   	 								<input class='form-control' type='text' name='newEnd' value='<?php echo $row['end_date']; ?>'>
127
+								</div>
128
+   	    					</div>
129
+   	    							
130
+   	    							
131
+
132
+      					</div><!--modal-body-->
133
+      					
134
+      					<!-- SUBMIT OR CANCEL -->
135
+     					<div class='modal-footer'>
136
+       						<button type='button' class='btn btn-default' data-dismiss='modal'>Close</button>
137
+        					<button type='submit' class='btn btn-primary' name='updateExperience'>Save Changes</button>
138
+      					</div><!--modal-footer-->
139
+      					
140
+    				</div><!--modal-content-->
141
+  				</div><!--modal-dialog-->
142
+			</div><!--modal-->
143
+		</form>
144
+*/
145
+?>

+ 67
- 0
processes/addExistingQuestionToMoment.php View File

@@ -0,0 +1,67 @@
1
+<?php
2
+
3
+	require_once 'config.php';
4
+	require_once 'dbh.inc.php';
5
+	require_once 'checkLogin.php';
6
+	
7
+	
8
+	// EXAMPLE INPUT...
9
+	// array(3) { ["momentID"]=> string(3) "137" ["questionID"]=> string(3) "266" ["addExistingQuestionToMoment"]=> string(0) "" }
10
+
11
+
12
+	if(isset($_POST['addExistingQuestionToMoment'])) {
13
+		
14
+
15
+
16
+		$momentID = mysqli_real_escape_string($connection, trim($_POST['momentID']));
17
+		$questionID = mysqli_real_escape_string($connection, trim($_POST['questionID']));
18
+		
19
+		
20
+		
21
+		// Check that moment ID is not empty string
22
+		// And that it's registered in the database
23
+		if($momentID === "") {
24
+			http_response_code(400);
25
+			echo json_encode(array("error" => "Please specify moment ID."));
26
+			exit();
27
+		} else if(mysqli_query($connection, "SELECT * FROM subquestionnair WHERE id = '$momentID';")->num_rows !== 1) {
28
+			http_response_code(400);
29
+			echo json_encode(array("error" => "Given moment ID ($momentID) not in database."));
30
+			exit();
31
+		}
32
+		
33
+		
34
+		
35
+		// Check that question ID is not empty string
36
+		// And that it's registered in the database
37
+		// And that it belongs to the Questionnaire the Moment belongs to
38
+		// And that it isn't a duplicate inside the Moment
39
+		if($questionID === "") {
40
+			http_response_code(400);
41
+			echo json_encode(array("error" => "Please specify question ID."));
42
+			exit();
43
+		} else if(mysqli_query($connection, "SELECT * FROM question WHERE id = '$questionID';")->num_rows !== 1) {
44
+			http_response_code(400);
45
+			echo json_encode(array("error" => "Given question ID ($questionID) not in database."));
46
+			exit();
47
+		} else if(mysqli_query($connection, "SELECT * FROM question WHERE id = '$questionID' AND id IN (SELECT id_question FROM questionnair_question WHERE id_questionnair = (SELECT id_questionnair FROM subquestionnair WHERE id = '$momentID'));")->num_rows !== 1) {
48
+			http_response_code(400);
49
+			echo json_encode(array("error" => "Given question ID ($questionID) is outside the Moment's corresponding Questionnair's scope."));
50
+			exit();
51
+		} else if(mysqli_query($connection, "SELECT * FROM subquestionnair_question WHERE id_question = '$questionID' AND id_subquestionnair = '$momentID';")->num_rows !== 0) {
52
+			http_response_code(400);
53
+			echo json_encode(array("error" => "Question already in moment."));
54
+			exit();
55
+		}
56
+
57
+	
58
+	
59
+		// Add question to moment
60
+		$query = "INSERT INTO subquestionnair_question (id_subquestionnair, id_question) VALUES ('$momentID','$questionID');";
61
+		$result = mysqli_query($connection, $query) or die("Error: ".mysqli_error($connection));
62
+		
63
+	
64
+
65
+
66
+	
67
+	}

+ 122
- 0
processes/callback.php View File

@@ -0,0 +1,122 @@
1
+<?php
2
+
3
+	require_once 'config.php';
4
+
5
+	// IF A SESSION ALREADY EXISTS, USE EXISTING TOKEN
6
+	// ELSE IF THERE'S NO SESSION BUT $_GET HAS USER AUTHCODE, OBTAIN NEW TOKEN
7
+	// ELSE REDIRECT TO ERROR PAGE
8
+	if(isset($_SESSION['token'])) {
9
+		$client->setAccessToken($_SESSION['token']);
10
+	}
11
+	else if(isset($_GET['code'])) {
12
+		$token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
13
+		
14
+		// IF 'code' IS NOT AUTHENTIC, TOKEN IS AN ARRAY WITH 'error' SET TO SOMETHING (i.e. 'invalid_grant')
15
+		if(isset($token['error'])) {
16
+			header('Location: ./logout.php');
17
+			die();
18
+		}
19
+		
20
+		$_SESSION['token'] = $token;
21
+	}
22
+	else {
23
+		header('Location: ../home.php');
24
+		exit();
25
+	}
26
+	
27
+// 	var_dump($_GET);
28
+// 	var_dump($_SESSION);
29
+		
30
+	$oAuth = new Google_Service_Oauth2($client);
31
+	$userData = $oAuth->userinfo_v2_me->get();
32
+	
33
+	/*
34
+			Algunos keys de los datos que se pueden extraer:
35
+			
36
+			(USADOS)
37
+			-SCOPE 'profile': name, picture
38
+			-SCOPE 'email': email
39
+			
40
+			(NO USADOS)
41
+			*-SCOPE 'profile': gender, familyName, givenName, hd, id, link*, locale, verifiedEmail
42
+			*-SCOPE 'profile': internal_gapi_mappings, modelData, processed
43
+
44
+			Lista completa de scopes: https://developers.google.com/identity/protocols/googlescopes
45
+	*/
46
+	
47
+	require_once 'dbh.inc.php';
48
+	
49
+	$query = 'SELECT * FROM `researcher` WHERE `email` = "'.$userData['email'].'";';
50
+	$result = mysqli_query($connection, $query);
51
+	$dbUserData = mysqli_fetch_assoc($result);
52
+	
53
+	$_SESSION['result'] = $result;
54
+	
55
+	// IF DB CAN'T FETCH USER DATA, IT MUST BE BECAUSE USER IS UNAUTHORIZED
56
+	// ELSE KEEP RETRIEVING USER DATA FROM DB
57
+	if($dbUserData == NULL) {
58
+		$_SESSION['error'] = 'unauthorized';
59
+	}
60
+	else {
61
+	
62
+		// NECESSARY FOR RETRIEVING DATA FROM DB ON LATER PAGES
63
+		$_SESSION['email'] = $userData['email'];
64
+		
65
+		//### OPTIONAL ###
66
+		$_SESSION['newUser'] = false;
67
+	
68
+		// IF USER IS NEW, UPDATE DB WITH USER INFO FROM GOOGLE
69
+		if($dbUserData['name'] == NULL && $dbUserData['picture'] == NULL) {
70
+			$query = 'UPDATE `researcher` SET `name`="'.$userData['name'].'", `picture`="'.$userData['picture'].'" WHERE `email`="'.$userData['email'].'";';
71
+			mysqli_query($connection, $query);
72
+			
73
+			//### OPTIONAL ###
74
+			$_SESSION['newUser'] = true;
75
+		}
76
+		
77
+	}
78
+
79
+	//### FOR DEBUGGING ###
80
+	$_SESSION['dbUserData'] = $dbUserData;
81
+	$_SESSION['error_set'] = isset($_SESSION['error']);
82
+	//### FOR DEBUGGING ###
83
+	
84
+	header('Location: ../home.php');
85
+	exit();
86
+
87
+
88
+
89
+
90
+
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+
106
+
107
+
108
+
109
+
110
+
111
+	/*
112
+			Additional links that helped:
113
+			
114
+			Google Developers Tutorial (Javascript): https://developers.google.com/identity/sign-in/web/sign-in
115
+			Sample Code: https://github.com/GoogleChromeLabs/google-sign-in
116
+			Branding Guidelines: https://developers.google.com/identity/branding-guidelines
117
+			Developer's Console: https://console.developers.google.com
118
+			
119
+			Tutorials:
120
+				-Login With Google Account Using PHP & Client API: https://www.youtube.com/watch?v=hazMyK_cnzk
121
+				-Login with Google Account using PHP: https://www.codexworld.com/login-with-google-api-using-php/
122
+	*/

+ 13
- 0
processes/checkLogin.php View File

@@ -0,0 +1,13 @@
1
+<?php
2
+
3
+	// IF NOT LOGGED IN THROUGH GOOGLE, SEND USER TO GENERAL ERROR PAGE
4
+	// ELSE IF LOGGED IN THROUGH GOOGLE BUT USER IS UNAUTHORIZED, SEND USER TO UNAUTHORIZED PAGE
5
+	// ELSE PRESENT NORMAL PAGE
6
+	if(empty($_SESSION)) {
7
+		header('Location: https://tania.uprrp.edu/admin_nuevo/error.php');
8
+		exit();
9
+	}
10
+	else if(!empty($_SESSION) && (isset($_SESSION['error']) && $_SESSION['error'] == 'unauthorized')) {
11
+		header('Location: https://tania.uprrp.edu/admin_nuevo/unauthorized.php');
12
+		exit();
13
+	}

+ 20
- 0
processes/config.php View File

@@ -0,0 +1,20 @@
1
+<?php
2
+
3
+	if(session_status() == PHP_SESSION_NONE) session_start();
4
+	require_once 'google-api-php-client-2.2.2/vendor/autoload.php';
5
+	
6
+	$CLIENT_ID = '76698467712-44aghb60h3ou9d3t3qcbkdokubseaiaa.apps.googleusercontent.com';
7
+	$CLIENT_SECRET = '9j17D7aVD1FnPxUmcAmQKnNy';
8
+	$APP_NAME = 'TANIA Administrative Page';
9
+	$REDIRECT_URI = 'https://tania.uprrp.edu/admin_nuevo/processes/callback.php'; // CHANGE IF SERVER CHANGES
10
+	
11
+	$client = new Google_Client();
12
+	$client->setClientId($CLIENT_ID);
13
+	$client->setClientSecret($CLIENT_SECRET);
14
+	$client->setApplicationName($APP_NAME);
15
+	$client->setRedirectUri($REDIRECT_URI);
16
+	$client->setPrompt('consent'); // FORCE USER TO CHOOSE GOOGLE ACCOUNT (INSTEAD OF ASUMING AUTOMATICALLY)
17
+	$client->addScope('profile');
18
+	$client->addScope('email');
19
+	
20
+	$loginURL = $client->createAuthUrl();

+ 25
- 0
processes/dbh.inc.php View File

@@ -0,0 +1,25 @@
1
+<?php
2
+
3
+	$dbServerName = "localhost";			// $_SERVER['NAME']
4
+	$dbUsername = "proyecto_ema"; 			// $_SERVER['USER'] ? victor.hernandez17
5
+	$dbPassword = "RUYCwNr2Xwah3PET";		// $_SERVER['PASSWORD'] ? cIMkSqsqXu1vkByz
6
+	$dbName = "proyecto.ema.upr";//marle.prueba.desarrollo";	// Name of database ? proyecto.ema.upr
7
+
8
+	$connection = mysqli_connect($dbServerName, $dbUsername, $dbPassword, $dbName) or die(mysqli_error());
9
+
10
+	mysqli_set_charset($connection, "utf8");
11
+	
12
+	
13
+	
14
+	// mysqli_error() vs. mysqli_connect_error() vs. mysqli_connect_errno()
15
+	
16
+	
17
+	
18
+	/*
19
+	
20
+public function connect() {
21
+   mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
22
+   $this->connection = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
23
+}	
24
+	
25
+	*/

+ 102
- 0
processes/deleteExperience.php View File

@@ -0,0 +1,102 @@
1
+<?php
2
+	
3
+	require_once 'config.php';
4
+	require_once 'dbh.inc.php';
5
+	require_once 'checkLogin.php';
6
+	
7
+	exit();
8
+	while(TRUE) {
9
+		exit();
10
+	}
11
+	exit();
12
+
13
+	// IF USER ENTERS PAGE AFTER 'Delete Anyway' BUTTON HAS BEEN PRESSED (FROM home.php), DELETE EXPERIENCE WITH ALL ITS ASSOCIATIONS, ANSWERS, AND SUBQUESTIONNAIRES FROM DATABASE
14
+	// ELSE (IF USER ENTERED THIS PAGE WITHOUT SUBMITING A FORM) REDIRECT TO home.php
15
+	if(isset($_POST['deleteExperience'])) {
16
+		
17
+		// NO NEED TO CLEAN ID, SINCE USER NEVER INPUTS ID
18
+		$id = $_POST['id'];
19
+		
20
+		// BORRAR INFORMACIÓN BÁSICA DE LA EXPERIENCIA
21
+		$query = "DELETE FROM `experience` WHERE `id`='".$id."';";
22
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
23
+				
24
+		// *BORRAR ASOCIACIÓN EXPERIENCIA-CUESTIONARIO (sería con un while? si es que pueden haber más de un cuestionario por experiencia...)
25
+		$query = "DELETE FROM `experience_questionnair` WHERE `id_experience`='".$id."';";
26
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
27
+		
28
+		// *BORRAR RESPUESTAS DE LA PRE-PRUEBA DE LA EXPERIENCIA (sería con un while?)
29
+		$query = "DELETE FROM `answerPre` WHERE `id_experience`='".$id."';";
30
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
31
+
32
+		// *BORRAR RESPUESTAS DE LA POST-PRUEBA DE LA EXPERIENCIA (sería con un while?)
33
+		$query = "DELETE FROM `answerPost` WHERE `id_experience`='".$id."';";
34
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
35
+		
36
+		// *BORRAR RESPUESTAS DE TODOS LOS SUBCUESTIONARIOS DE LA EXPERIENCIA (sería con un while?)
37
+		$query = "DELETE FROM `answer` WHERE `id_experience`='".$id."';";
38
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
39
+		
40
+		// *BORRAR LA ASOCIACIÓN DE CADA ESTUDIANTE A UNA EXPERIENCIA (sería con un while?)
41
+		$query = "DELETE FROM `student_participate_experience` WHERE `id_experience`='".$id."';";
42
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
43
+		
44
+		
45
+		
46
+		
47
+		
48
+		
49
+		
50
+		
51
+		// SACAR TODOS LOS ID DE LOS SUBCUESTIONARIOS DE LA EXPERIENCIA
52
+		$query = "SELECT `id_subquestionnair` FROM `experience_subquestionnair` WHERE `id_experience`='".$id."';";
53
+		$result = mysqli_query($connection, $query);
54
+		if(!$result) die("Error: ".mysqli_error($connection));
55
+		
56
+		// IR UNO A UNO POR CADA SUBCUESTIONARIO
57
+		while($row = mysqli_fetch_array($result) {
58
+		
59
+			// *BORRAR TODOS LAS ASOCIACIONES REMINDER-SUBCUESTIONARIO DE LA EXPERIENCIA (sería con un while?)
60
+			$query = "DELETE FROM `reminder_subquestionnair` WHERE `id_subquestionnair`='".$row['id_subquestionnair']."';";
61
+			if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
62
+			
63
+			// *BORRAR EL SCHEDULE ASOCIADO A UN SUBCUESTIONARIO A LA EXPERIENCIA (sería con un while?)
64
+			$query = "DELETE FROM `schedule` WHERE `id_subquestionnair`='".$row['id_subquestionnair']."';";
65
+			if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
66
+
67
+			// *BORRAR LA ASOCIACIÓN DE CADA ESTUDANTE A UN SUBCUESTIONARIO DE LA EXPERIENCIA (sería con un while?)
68
+			$query = "DELETE FROM `student_subquestionnair` WHERE `id_subquestionnair`='".$row['id_subquestionnair']."';";
69
+			if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
70
+			
71
+			// *BORRAR LA INFORMACIÓN BÁSICA DE UN SUBCUESTIONARIO DE LA EXPERIENCIA
72
+			$query = "DELETE FROM `subquestionnair` WHERE `id`='".$row['id_subquestionnair']."';";
73
+			if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
74
+			
75
+			// *BORRAR LA ASOCIACIÓN DE CADA PREGUNTA A UN SUBCUESTIONARIO DE LA EXPERIENCIA (sería con un while?)
76
+			$query = "DELETE FROM `subquestionnair_question` WHERE `id_subquestionnair`='".$row['id_subquestionnair']."';";
77
+			if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
78
+
79
+			// *BORRAR EL TIEMPO QUE LE TOMA CONTESTAR A CADA ESTUDIANTE UN SUBCUESTIONARIO DE LA EXPERIENCIA (sería con un while?)
80
+			$query = "DELETE FROM `tempTiempo` WHERE `id_subquestionnair`='".$row['id_subquestionnair']."';";
81
+			if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
82
+
83
+		}
84
+
85
+		// *BORRAR ASOCIACIÓN EXPERIENCIA-SUBCUESTIONARIO (sería con un while?)
86
+		// *WARNING: ESTE QUERY TIENE QUE VENIR DESPUÉS DE HABER EXTRAÍDO CADA id_subquestionnair
87
+		$query = "DELETE FROM `experience_subquestionnair` WHERE `id_experience`='".$id."';";
88
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
89
+		
90
+		// ***BORRAR ASOCIACIÓN EXPERIENCIA-INSTITUCIÓN (borramos institución también?, necesitaríamos extraer id_institution antes de borrar)
91
+		$query = "DELETE FROM `institution_experience` WHERE `id_experience`='".$id."';";
92
+		if(!mysqli_query($connection, $query)) die("Error: ".mysqli_error($connection));
93
+
94
+		//*qué son pareoPrePostEma y phone_fourDigit_tempX? si tienen que ver con los estudiantes también habría que borrarlos
95
+
96
+		//borramos student profiles? y qué es studentOri? yo diría que no
97
+
98
+
99
+	}
100
+	
101
+	header('Location: ../home.php');
102
+	exit();

+ 68
- 0
processes/deleteMoment.php View File

@@ -0,0 +1,68 @@
1
+<?php
2
+
3
+	require_once 'config.php';
4
+	require_once 'dbh.inc.php';
5
+	require_once 'checkLogin.php';
6
+	
7
+	
8
+	// EXAMPLE INPUT...
9
+	// array(2) { ["momentID"]=> string(3) "137" ["deleteMoment"]=> string(0) "" }
10
+	
11
+	// WARNING: SHOULD CONFIRM THAT MOMENT BELONGS TO THE CORRECT USER (AUTHENTICATE THE TRANSACTION)
12
+
13
+
14
+	if(isset($_POST['deleteMoment'])) {
15
+		
16
+
17
+
18
+		$momentID = mysqli_real_escape_string($connection, trim($_POST['momentID']));
19
+		
20
+		
21
+		// Check that moment ID is not empty string
22
+		if($momentID === "") {
23
+			http_response_code(400);
24
+			echo json_encode(array("error" => "Please specify moment ID."));
25
+			exit();
26
+		}
27
+		
28
+		
29
+		// Check that moment is registered in the database
30
+		if(mysqli_query($connection, "SELECT * FROM subquestionnair WHERE id = '$momentID';")->num_rows !== 1) {
31
+			http_response_code(400);
32
+			echo json_encode(array("error" => "Given moment ID ($momentID) not in database."));
33
+			exit();
34
+		}
35
+		
36
+		
37
+		// Check that the moment hasn't been answered yet
38
+		if(mysqli_query($connection, "SELECT * FROM student_subquestionnair WHERE id_subquestionnair = '$momentID';")->num_rows !== 0) {
39
+			http_response_code(400);
40
+			echo json_encode(array("error" => "Moment already active, deletion denied."));
41
+			exit();
42
+		}
43
+		
44
+		
45
+		
46
+		/*** STEPS ***/
47
+
48
+		// DELETE MOMENT-QUESTION RELATIONS
49
+		// DELETE EXPERIENCE-MOMENT RELATION
50
+		// DELETE MOMENT
51
+
52
+
53
+
54
+		// Delete moment-question relations
55
+		$queryUnhookQuestionFromMoment = "DELETE FROM subquestionnair_question WHERE id_subquestionnair = '$momentID';";
56
+		$result = mysqli_query($connection, $queryUnhookQuestionFromMoment) or die("Error: ".mysqli_error($connection));
57
+
58
+		// Delete experience-moment relation
59
+		$queryUnhookMomentFromExperience = "DELETE FROM experience_subquestionnair WHERE id_subquestionnair = '$momentID';";
60
+		$result = mysqli_query($connection, $queryUnhookMomentFromExperience) or die("Error: ".mysqli_error($connection));
61
+
62
+		// Delete moments
63
+		$queryDeleteMoments = "DELETE FROM subquestionnair WHERE id = '$momentID';";
64
+		$result = mysqli_query($connection, $queryDeleteMoments) or die("Error: ".mysqli_error($connection));
65
+		
66
+		
67
+	
68
+	}

+ 77
- 0
processes/deleteQuestion.php View File

@@ -0,0 +1,77 @@
1
+<?php
2
+
3
+	require_once 'config.php';
4
+	require_once 'dbh.inc.php';
5
+	require_once 'checkLogin.php';
6
+	
7
+	
8
+	// EXAMPLE INPUT...
9
+	// array(2) { ["questionID"]=> string(3) "267" ["deleteQuestion"]=> string(0) "" }
10
+	
11
+	// WARNING: SHOULD CONFIRM THAT QUESTION BELONGS TO THE CORRECT USER (AUTHENTICATE THE TRANSACTION)
12
+	// WARNING: IF USER DELETES ALL QUESTIONS FROM A QUESTIONNAIRE USING THIS METHOD, THE DATABASE WILL HAVE UNUSED CATEGORIES/SUBCATEGORIES, AS THEY ARE NOT ASSOCIATED DIRECTLY TO THE QUESTIONNAIRE
13
+	
14
+// 	var_dump($_POST);
15
+// 	exit();
16
+
17
+
18
+	if(isset($_POST['deleteQuestion'])) {
19
+		
20
+
21
+
22
+		$questionID = mysqli_real_escape_string($connection, trim($_POST['questionID']));
23
+		
24
+		
25
+		// Check that question ID is not empty string
26
+		if($questionID === "") {
27
+			http_response_code(400);
28
+			echo json_encode(array("error" => "Please specify question ID."));
29
+			exit();
30
+		}
31
+		
32
+		
33
+		// Check that question is registered in the database
34
+		if(mysqli_query($connection, "SELECT * FROM question WHERE id = '$questionID';")->num_rows !== 1) {
35
+			http_response_code(400);
36
+			echo json_encode(array("error" => "Given question ID ($questionID) not in database."));
37
+			exit();
38
+		}
39
+		
40
+		
41
+		// Check that question hasn't been answered yet
42
+		if(mysqli_query($connection, "SELECT * FROM answer WHERE id_question = '$questionID';")->num_rows !== 0) {
43
+			http_response_code(400);
44
+			echo json_encode(array("error" => "Question has already been answered by one or more people, deletion denied."));
45
+			exit();
46
+		}
47
+		
48
+		
49
+		
50
+		/*** STEPS ***/
51
+
52
+		// DELETE MOMENT-QUESTION RELATION
53
+		// DELETE QUESTIONNAIRE-QUESTION RELATION
54
+		// DELETE QUESTION-TYPES
55
+		// DELETE QUESTION
56
+
57
+
58
+		
59
+		// Delete moment-question relation
60
+		$queryUnhookQuestionFromMoment = "DELETE FROM subquestionnair_question WHERE id_question = '$questionID';";
61
+		$result = mysqli_query($connection, $queryUnhookQuestionFromMoment) or die("Error: ".mysqli_error($connection));
62
+
63
+		// Delete questionnaire-question relation
64
+		$queryUnhookQuestionFromQuestionnaire = "DELETE FROM questionnair_question WHERE id_question = '$questionID';";
65
+		$result = mysqli_query($connection, $queryUnhookQuestionFromQuestionnaire) or die("Error: ".mysqli_error($connection));
66
+	
67
+		// Delete question types
68
+		$queryDeleteQuestionTypes = "DELETE FROM question_type WHERE id_question = '$questionID';";
69
+		$result = mysqli_query($connection, $queryDeleteQuestionTypes) or die("Error: ".mysqli_error($connection));
70
+
71
+		// Delete question
72
+		$queryDeleteQuestion = "DELETE FROM question WHERE id = '$questionID';";
73
+		$result = mysqli_query($connection, $queryDeleteQuestion) or die("Error: ".mysqli_error($connection));
74
+	
75
+		
76
+	
77
+	}

+ 110
- 0
processes/deleteQuestionnaire.php View File

@@ -0,0 +1,110 @@
1
+<?php
2
+
3
+	require_once 'config.php';
4
+	require_once 'dbh.inc.php';
5
+	require_once 'checkLogin.php';
6
+	
7
+	
8
+	// EXAMPLE INPUT...
9
+	// array(2) { ["questionnaireID"]=> string(3) "137" ["deleteQuestionnaire"]=> string(0) "" }
10
+	
11
+	// WARNING: SHOULD CONFIRM THAT QUESTIONNAIRE BELONGS TO THE CORRECT USER (AUTHENTICATE THE TRANSACTION)
12
+
13
+
14
+	if(isset($_POST['deleteQuestionnaire'])) {
15
+		
16
+
17
+
18
+		$questionnaireID = mysqli_real_escape_string($connection, trim($_POST['questionnaireID']));
19
+		
20
+		
21
+		// Check that questionnaire ID is not empty string
22
+		if($questionnaireID === "") {
23
+			http_response_code(400);
24
+			echo json_encode(array("error" => "Please specify questionnaire ID."));
25
+			exit();
26
+		}
27
+		
28
+		
29
+		// Check that questionnaire is registered in the database
30
+		if(mysqli_query($connection, "SELECT * FROM questionnair WHERE id = '$questionnaireID';")->num_rows !== 1) {
31
+			http_response_code(400);
32
+			echo json_encode(array("error" => "Given questionnaire ID ($questionnaireID) not in database."));
33
+			exit();
34
+		}
35
+		
36
+		
37
+		// Check that no corresponding moments have been answered yet
38
+		if(mysqli_query($connection, "SELECT * FROM student_subquestionnair WHERE id_subquestionnair IN (SELECT id FROM subquestionnair WHERE id_questionnair = '$questionnaireID');")->num_rows !== 0) {
39
+			http_response_code(400);
40
+			echo json_encode(array("error" => "Questionnaire already active, deletion denied."));
41
+			exit();
42
+		}
43
+		
44
+		
45
+		
46
+		/*** STEPS ***/
47
+		
48
+		// DELETE CATEGORIES	 	(USE QUESTIONNAIRE-QUESTION, THEN QUESTION TABLE TO GET TO CATEGORY TABLE)*
49
+		// DELETE SUBCATEGORIES 	(USE QUESTIONNAIRE-QUESTION, THEN QUESTION TABLE TO GET TO SUBCATEGORY TABLE)*
50
+		// DELETE REFERENCE 		(USE QUESTIONNAIRE-QUESTION, THEN QUESTION TABLE TO GET TO REFERENCE TABLE)*
51
+		// DELETE QUESTION-TYPE 	(USE QUESTIONNAIRE-QUESTION TABLE)*
52
+		// DELETE QUESTIONS 		(USE QUESTIONNAIRE-QUESTION TABLE)*
53
+
54
+		// DELETE MOMENT-QUESTION RELATIONS 	(USE MOMENT TABLE TO GET TO MOMENT-QUESTION TABLE)*
55
+		// DELETE EXPERIENCE-MOMENT RELATIONS 	(USE MOMENT TABLE TO GET TO EXPERIENCE-MOMENT TABLE)*
56
+		// DELETE MOMENTS
57
+
58
+		// DELETE QUESTIONNAIRE-QUESTION RELATIONS
59
+		// DELETE EXPERIENCE-QUESTIONNAIRE RELATION
60
+		// DELETE QUESTIONNAIRE
61
+
62
+
63
+
64
+		// Delete categories
65
+		$queryDeleteCategories = "DELETE FROM category WHERE id IN (SELECT DISTINCT id_category FROM question WHERE id IN (SELECT id_question FROM questionnair_question WHERE id_questionnair = '$questionnaireID'));";
66
+		$result = mysqli_query($connection, $queryDeleteCategories) or die("Error: ".mysqli_error($connection));
67
+		
68
+		// Delete subcategories
69
+		$queryDeleteSubcategories = "DELETE FROM subcategory WHERE id IN (SELECT DISTINCT id_subcategory FROM question WHERE id IN (SELECT id_question FROM questionnair_question WHERE id_questionnair = '$questionnaireID'));";
70
+		$result = mysqli_query($connection, $queryDeleteSubcategories) or die("Error: ".mysqli_error($connection));
71
+	
72
+		// Delete reference
73
+		$queryDeleteReference = "DELETE FROM reference WHERE id IN (SELECT DISTINCT id_referencia FROM question WHERE id IN (SELECT id_question FROM questionnair_question WHERE id_questionnair = '$questionnaireID'));";
74
+		$result = mysqli_query($connection, $queryDeleteReference) or die("Error: ".mysqli_error($connection));
75
+
76
+		// Delete question types
77
+		$queryDeleteQuestionTypes = "DELETE FROM question_type WHERE id_question IN (SELECT id_question FROM questionnair_question WHERE id_questionnair = '$questionnaireID');";
78
+		$result = mysqli_query($connection, $queryDeleteQuestionTypes) or die("Error: ".mysqli_error($connection));
79
+
80
+		// Delete questions
81
+		$queryDeleteQuestions = "DELETE FROM question WHERE id IN (SELECT id_question FROM questionnair_question WHERE id_questionnair = '$questionnaireID');";
82
+		$result = mysqli_query($connection, $queryDeleteQuestions) or die("Error: ".mysqli_error($connection));
83
+		
84
+		// Delete moment-question relations
85
+		$queryUnhookQuestionFromMoment = "DELETE FROM subquestionnair_question WHERE id_subquestionnair IN (SELECT id FROM subquestionnair WHERE id_questionnair = '$questionnaireID');";
86
+		$result = mysqli_query($connection, $queryUnhookQuestionFromMoment) or die("Error: ".mysqli_error($connection));
87
+
88
+		// Delete experience-moment relations
89
+		$queryUnhookMomentFromExperience = "DELETE FROM experience_subquestionnair WHERE id_subquestionnair IN (SELECT id FROM subquestionnair WHERE id_questionnair = '$questionnaireID');";
90
+		$result = mysqli_query($connection, $queryUnhookMomentFromExperience) or die("Error: ".mysqli_error($connection));
91
+
92
+		// Delete moments
93
+		$queryDeleteMoments = "DELETE FROM subquestionnair WHERE id_questionnair = '$questionnaireID';";
94
+		$result = mysqli_query($connection, $queryDeleteMoments) or die("Error: ".mysqli_error($connection));
95
+
96
+		// Delete questionnaire-question relations
97
+		$queryUnhookQuestionFromQuestionnaire = "DELETE FROM questionnair_question WHERE id_questionnair = '$questionnaireID';";
98
+		$result = mysqli_query($connection, $queryUnhookQuestionFromQuestionnaire) or die("Error: ".mysqli_error($connection));
99
+
100
+		// Delete experience-questionnaire relations
101
+		$queryUnhookQuestionnaireFromExperience = "DELETE FROM experience_questionnair WHERE id_questionnair = '$questionnaireID';";
102
+		$result = mysqli_query($connection, $queryUnhookQuestionnaireFromExperience) or die("Error: ".mysqli_error($connection));	
103
+
104
+		// Delete questionnaire
105
+		$queryDeleteQuestionnaire = "DELETE FROM questionnair WHERE id = '$questionnaireID';";
106
+		$result = mysqli_query($connection, $queryDeleteQuestionnaire) or die("Error: ".mysqli_error($connection));
107
+		
108
+		
109
+	
110
+	}

+ 118
- 0
processes/duplicateQuestionnaire.php View File

@@ -0,0 +1,118 @@
1
+<?php 
2
+
3
+	require_once 'config.php';
4
+	require_once 'dbh.inc.php';
5
+	require_once 'checkLogin.php';	
6
+	
7
+	// EXAMPLE INPUT...
8
+	// array(3) { ["fromQuestionnaireID"]=> string(1) "1" ["toExperienceID"]=> string(1) "11" ["duplicateQuestionnaire"]=> string(1) "" }
9
+
10
+	if(isset($_POST['duplicateQuestionnaire'])) {
11
+	
12
+	
13
+
14
+		/*** FETCH INPUT ***/
15
+		// WARNING: SHOULD VERIFY IF THESE ACTUALLY EXIST
16
+		$fromQuestionnaireID = mysqli_real_escape_string($connection, $_POST['fromQuestionnaireID']);
17
+		$toExperienceID = mysqli_real_escape_string($connection, $_POST['toExperienceID']);
18
+		
19
+		
20
+		/*** FETCH THE QUESTIONNAIRE INFO ***/
21
+		$queryOldQuestionnaire = "SELECT * FROM questionnair WHERE id = $fromQuestionnaireID";
22
+		$resultOldQuestionnaire = mysqli_query($connection, $queryOldQuestionnaire) or die("Error: Couldn't fetch questionnaire info from given ID<br>".mysqli_error($connection));
23
+		$rowOldQuestionnaire = mysqli_fetch_assoc($resultOldQuestionnaire);
24
+		
25
+		
26
+		/*** DUPLICATE QUESTIONNAIRE, RETRIEVE ITS ID (TO USE IT IN TABLES experience_questionnair AND questionnair_question) AND HOOK TO CURRENT EXPERIENCE ***/
27
+		$queryQuestionnaire = "INSERT INTO questionnair (`q_title`, `description`) VALUES ('".$rowOldQuestionnaire['q_title']."', '".$rowOldQuestionnaire['description']."');";
28
+		if(!mysqli_query($connection, $queryQuestionnaire)) {
29
+			echo $queryQuestionnaire . "<br>";
30
+			die("Error: Couldn't create questionnaire<br>".mysqli_error($connection));
31
+		}
32
+
33
+		$questionnaireID = mysqli_insert_id($connection) or die("Error: Couldn't fetch questionnaire id after creating it<br>".mysqli_error($connection));
34
+
35
+		$queryHookQuestionnaireToExperience = "INSERT INTO experience_questionnair (`id_experience`, `id_questionnair`) VALUES ('".$toExperienceID."', '".$questionnaireID."');";
36
+		if(!mysqli_query($connection, $queryHookQuestionnaireToExperience)) {
37
+			echo $queryHookQuestionnaireToExperience . "<br>";
38
+			die("Error: Couldn't hook questionnaire to experience<br>".mysqli_error($connection));
39
+		}
40
+
41
+
42
+
43
+// WE DON'T NEED TO INSERT A NEW REFERENCE, WE JUST NEED TO DUPLICATE THE QUESTIONS (WHICH HAVE THE REFERENCE ID ALREADY)
44
+// WE DON'T NEED TO CREATE THE NEW CATEGORIES, WE JUST NEED TO DUPLICATE THE QUESTIONS (WHICH HAVE THE CATEGORY ID ALREADY)
45
+// WE DON'T NEED TO CREATE THE NEW SUBCATEGORIES, WE JUST NEED TO DUPLICATE THE QUESTIONS (WHICH HAVE THE SUBCATEGORY ID ALREADY)
46
+
47
+
48
+		
49
+		$queryForQuestions = "SELECT id_question FROM questionnair_question WHERE id_questionnair = $fromQuestionnaireID;";
50
+		$resultForQuestions = mysqli_query($connection, $queryForQuestions);
51
+		
52
+		/*** CREATE QUESTIONS ONE BY ONE, RETRIEVE THEIR RESPECTIVE IDs (TO USE IN TABLES question_type AND questionnair_question), ENTER THE MIN/MAX VALUES/TEXTS, AND HOOK QUESTION TO QUESTIONNAIR ***/
53
+		while($rowForQuestions = mysqli_fetch_assoc($resultForQuestions)) {
54
+			
55
+			
56
+			// FETCH THE INFO FOR A GIVEN QUESTION
57
+			$queryOldQuestion = "SELECT * FROM question WHERE id = " . $rowForQuestions['id_question'];
58
+			$resultOldQuestion = mysqli_query($connection, $queryOldQuestion);
59
+			$rowOldQuestion = mysqli_fetch_assoc($resultOldQuestion);
60
+			
61
+			
62
+			// DUPLICATE QUESTION
63
+			$queryQuestion = "INSERT INTO question (`premise`, `id_category`, `id_subcategory`, `id_type`, `id_referencia`) VALUES ('".mysqli_real_escape_string($connection, $rowOldQuestion['premise'])."', '".$rowOldQuestion['id_category']."', '".$rowOldQuestion['id_subcategory']."', '".$rowOldQuestion['id_type']."', '".$rowOldQuestion['id_referencia']."');";
64
+			if(!mysqli_query($connection, $queryQuestion)) {
65
+				echo $queryQuestion . "<br>";
66
+				die("Error: Couldn't duplicate question with id ".$rowForQuestions['id_question']."<br>".mysqli_error($connection));
67
+			}
68
+			
69
+			// FETCH DUPLICATE QUESTION ID
70
+ 			$questionID = mysqli_insert_id($connection) or die("Error: Couldn't fetch new question id (from old question id ".$rowForQuestions['id_question'].")<br>".mysqli_error($connection));
71
+
72
+
73
+			// IF QUESTION IS SCALED, DUPLICATE MIN/MAX VALUES/TEXT
74
+			if($rowOldQuestion['id_type'] == '1') {
75
+			
76
+			
77
+				// FETCH THE QUESTION TYPES FOR A GIVEN QUESTION
78
+				$queryOldQuestionTypes = "SELECT * FROM question_type WHERE id_question = " . $rowForQuestions['id_question'];
79
+				$resultOldQuestionTypes = mysqli_query($connection, $queryOldQuestionTypes);
80
+				
81
+				
82
+				// LOOP THROUGH ALL QUESTION TYPES 
83
+				while($rowOldQuestionTypes = mysqli_fetch_assoc($resultOldQuestionTypes)) {
84
+					
85
+					$queryMinVal = "INSERT INTO question_type (`id_type`, `id_question`, `label`, `value`) VALUES ('".$rowOldQuestionTypes['id_type']."', '".$questionID."', '".$rowOldQuestionTypes['label']."', '".$rowOldQuestionTypes['value']."');";
86
+					if(!mysqli_query($connection, $queryMinVal)) {
87
+						echo $queryMinVal . "<br>";
88
+						die("Error: Couldn't duplicate question ".$rowOldQuestionTypes['label']." (from old question with id ".$rowForQuestions['id_question'].")<br>".mysqli_error($connection));
89
+					}
90
+				
91
+				}
92
+
93
+				
94
+			}
95
+			
96
+			$queryHookQuestionToQuestionnaire = "INSERT INTO questionnair_question (`id_questionnair`, `id_question`) VALUES ('".$questionnaireID."', '".$questionID."');";
97
+			if(!mysqli_query($connection, $queryHookQuestionToQuestionnaire)) {
98
+				echo $queryHookQuestionToQuestionnaire . "<br>";
99
+				die("Error: Couldn't hook question to questionnaire  (Question ID: ".$questionID.")<br>".mysqli_error($connection));
100
+			}
101
+		
102
+		}
103
+		
104
+		
105
+
106
+
107
+		
108
+		
109
+		header('Location: ../questionnaires.php');
110
+		exit();
111
+
112
+
113
+
114
+	}
115
+
116
+
117
+
118
+?>

+ 77
- 0
processes/export.php View File

@@ -0,0 +1,77 @@
1
+<?php 
2
+
3
+	require_once 'config.php';
4
+	require_once 'dbh.inc.php'; // has to use proyecto.ema.upr DB!!!
5
+	require_once 'checkLogin.php';
6
+	
7
+// 	include("../conection.php");
8
+
9
+		
10
+
11
+	if(isset($_POST['export']) && isset($_POST['id_exp'])) {
12
+	
13
+		$id_experience = mysqli_real_escape_string($connection, $_POST['id_exp']);
14
+// 		$id_student = mysqli_real_escape_string($connection, $_POST['id_student']);
15
+// 		$res_type = mysqli_real_escape_string($connection, $_POST['res_type']);
16
+	
17
+		header_remove();
18
+		header('Content-Type: text/csv; charset=utf-8');
19
+		header('Content-Disposition: attachment; filename="Resultados_'.$id_experience.'.csv"');
20
+		$output = fopen('php://output', 'w');
21
+		
22
+		
23
+		
24
+		
25
+// 		$answersQuery = "SELECT a.id_student, a.id_subquestionnair, a.id_question, a.value FROM `answer` a, `question` q WHERE `id_subquestionnair` IN (SELECT `id_subquestionnair` FROM experience_subquestionnair WHERE `id_experience`=10);";
26
+//  	$resultAnswers = mysqli_query($connection, $answersQuery);
27
+// 		while($rowAnswers = mysqli_fetch_assoc()) {
28
+// 			$rowAnswers['value'];
29
+// 		}
30
+// 		$subquestionnairQuery = "SELECT `title` FROM `subquestionnair` WHERE `id`=".id_subquestionnair.";
31
+//		id_subquestionnair: se usará para el nombre del subquestionnair
32
+//		id_question: premise, id_category, id_subcategory
33
+		
34
+		
35
+		
36
+		
37
+		
38
+		
39
+		/*** QUEREMOS: question premise, question category, question subcategory, student id, subquestionnair title, answer value ***/
40
+		
41
+		// (CORRADA) GENERA 1541 FILAS PERO ES CON NÚMEROS NADA MÁS
42
+		$query = "SELECT DISTINCT q.id, q.premise, q.id_category, q.id_subcategory, a.id_student, a.id_subquestionnair, a.value FROM `experience_questionnair` eq, `subquestionnair` qs, `questionnair_question` qq, `question` q, `answer` a WHERE a.id_question=q.id and eq.id_questionnair=qs.id_questionnair and eq.id_questionnair=qq.id_questionnair and qq.id_question=q.id and eq.id_experience=".$id_experience." ORDER BY q.id, a.id_subquestionnair, a.id_student ASC;";
43
+		$header = array('Question ID', 'Question Premise', 'Corresponding Moment', 'Question Category', 'Question Subcategory', 'Student ID', 'Answer');
44
+
45
+		// (VÍCTOR) GENERA 1215 FILAS
46
+// 		$query = "SELECT q.premise, a.value, sq.title, c.categoria, sc.subcategoria, a.id_student FROM answer a, question q, subquestionnair sq, category c, subcategory sc WHERE (a.`id_subquestionnair` IN (SELECT `id_subquestionnair` FROM experience_subquestionnair WHERE `id_experience`=".$id_experience.")) AND q.id=a.id_question AND sq.id=a.id_subquestionnair AND c.id=q.id_category AND sc.id=q.id_subcategory;";
47
+//		$header = array('Question Premise', 'Answer', 'Corresponding Moment', 'Question Category', 'Question Subcategory', 'Student ID');		
48
+		
49
+
50
+		fputcsv($output, $header);
51
+		
52
+		$result = mysqli_query($connection, $query);
53
+		
54
+		while($row = mysqli_fetch_assoc($result)) {
55
+			
56
+			$queryCategory = "SELECT categoria FROM `category` WHERE id=".$row['id_category'].";";
57
+			$resultCategory = mysqli_query($connection, $queryCategory);
58
+			$rowCategory = mysqli_fetch_assoc($resultCategory);
59
+			
60
+			// QUERY USES SUBCATEGORY ID FROM ANOTHER SELECT BECAUSE $row['id_subcategory'] GIVES AN ERROR
61
+			$querySubcategory = "SELECT subcategoria FROM `subcategory` WHERE id=(SELECT id_subcategory FROM `question` WHERE id=".$row['id'].");";
62
+			$resultSubcategory = mysqli_query($connection, $querySubcategory);
63
+			$rowSubcategory = mysqli_fetch_assoc($resultSubcategory);
64
+			
65
+			$queryMoment = "SELECT title FROM `subquestionnair` WHERE id=".$row['id_subquestionnair'].";";
66
+			$resultMoment = mysqli_query($connection, $queryMoment);
67
+			$rowMoment = mysqli_fetch_assoc($resultMoment);
68
+		
69
+			fputcsv($output, array($row['id'], $row['premise'], $rowMoment['title'], $rowCategory['categoria'], $rowSubcategory['subcategoria'], $row['id_student'], $row['value']));
70
+			
71
+		}
72
+		
73
+		fclose($output);
74
+
75
+	}
76
+
77
+?>

+ 20
- 0
processes/fullcalendar/LICENSE.txt View File

@@ -0,0 +1,20 @@
1
+Copyright (c) 2019 Adam Shaw
2
+
3
+Permission is hereby granted, free of charge, to any person obtaining
4
+a copy of this software and associated documentation files (the
5
+"Software"), to deal in the Software without restriction, including
6
+without limitation the rights to use, copy, modify, merge, publish,
7
+distribute, sublicense, and/or sell copies of the Software, and to
8
+permit persons to whom the Software is furnished to do so, subject to
9
+the following conditions:
10
+
11
+The above copyright notice and this permission notice shall be
12
+included in all copies or substantial portions of the Software.
13
+
14
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 10
- 0
processes/fullcalendar/README.md View File

@@ -0,0 +1,10 @@
1
+# FullCalendar [![Build Status](https://travis-ci.com/fullcalendar/fullcalendar.svg?branch=master)](https://travis-ci.com/fullcalendar/fullcalendar)
2
+
3
+A full-sized drag & drop JavaScript event calendar
4
+
5
+- [Project website and demos](http://fullcalendar.io/)
6
+- [Documentation](http://fullcalendar.io/docs)
7
+- [Support](http://fullcalendar.io/support)
8
+- [Contributing](CONTRIBUTING.md)
9
+- [Changelog](CHANGELOG.md)
10
+- [License](LICENSE.txt)

+ 109
- 0
processes/fullcalendar/examples/background-events.html View File

@@ -0,0 +1,109 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='../packages/core/main.css' rel='stylesheet' />
6
+<link href='../packages/daygrid/main.css' rel='stylesheet' />
7
+<link href='../packages/timegrid/main.css' rel='stylesheet' />
8
+<link href='../packages/list/main.css' rel='stylesheet' />
9
+<script src='../packages/core/main.js'></script>
10
+<script src='../packages/interaction/main.js'></script>
11
+<script src='../packages/daygrid/main.js'></script>
12
+<script src='../packages/timegrid/main.js'></script>
13
+<script src='../packages/list/main.js'></script>
14
+<script>
15
+
16
+  document.addEventListener('DOMContentLoaded', function() {
17
+    var calendarEl = document.getElementById('calendar');
18
+
19
+    var calendar = new FullCalendar.Calendar(calendarEl, {
20
+      plugins: [ 'interaction', 'dayGrid', 'timeGrid', 'list' ],
21
+      header: {
22
+        left: 'prev,next today',
23
+        center: 'title',
24
+        right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth'
25
+      },
26
+      defaultDate: '2019-08-12',
27
+      navLinks: true, // can click day/week names to navigate views
28
+      businessHours: true, // display business hours
29
+      editable: true,
30
+      events: [
31
+        {
32
+          title: 'Business Lunch',
33
+          start: '2019-08-03T13:00:00',
34
+          constraint: 'businessHours'
35
+        },
36
+        {
37
+          title: 'Meeting',
38
+          start: '2019-08-13T11:00:00',
39
+          constraint: 'availableForMeeting', // defined below
40
+          color: '#257e4a'
41
+        },
42
+        {
43
+          title: 'Conference',
44
+          start: '2019-08-18',
45
+          end: '2019-08-20'
46
+        },
47
+        {
48
+          title: 'Party',
49
+          start: '2019-08-29T20:00:00'
50
+        },
51
+
52
+        // areas where "Meeting" must be dropped
53
+        {
54
+          groupId: 'availableForMeeting',
55
+          start: '2019-08-11T10:00:00',
56
+          end: '2019-08-11T16:00:00',
57
+          rendering: 'background'
58
+        },
59
+        {
60
+          groupId: 'availableForMeeting',
61
+          start: '2019-08-13T10:00:00',
62
+          end: '2019-08-13T16:00:00',
63
+          rendering: 'background'
64
+        },
65
+
66
+        // red areas where no events can be dropped
67
+        {
68
+          start: '2019-08-24',
69
+          end: '2019-08-28',
70
+          overlap: false,
71
+          rendering: 'background',
72
+          color: '#ff9f89'
73
+        },
74
+        {
75
+          start: '2019-08-06',
76
+          end: '2019-08-08',
77
+          overlap: false,
78
+          rendering: 'background',
79
+          color: '#ff9f89'
80
+        }
81
+      ]
82
+    });
83
+
84
+    calendar.render();
85
+  });
86
+
87
+</script>
88
+<style>
89
+
90
+  body {
91
+    margin: 40px 10px;
92
+    padding: 0;
93
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
94
+    font-size: 14px;
95
+  }
96
+
97
+  #calendar {
98
+    max-width: 900px;
99
+    margin: 0 auto;
100
+  }
101
+
102
+</style>
103
+</head>
104
+<body>
105
+
106
+  <div id='calendar'></div>
107
+
108
+</body>
109
+</html>

+ 109
- 0
processes/fullcalendar/examples/daygrid-views.html View File

@@ -0,0 +1,109 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='../packages/core/main.css' rel='stylesheet' />
6
+<link href='../packages/daygrid/main.css' rel='stylesheet' />
7
+<script src='../packages/core/main.js'></script>
8
+<script src='../packages/interaction/main.js'></script>
9
+<script src='../packages/daygrid/main.js'></script>
10
+<script>
11
+
12
+  document.addEventListener('DOMContentLoaded', function() {
13
+    var calendarEl = document.getElementById('calendar');
14
+
15
+    var calendar = new FullCalendar.Calendar(calendarEl, {
16
+      plugins: [ 'interaction', 'dayGrid' ],
17
+      header: {
18
+        left: 'prevYear,prev,next,nextYear today',
19
+        center: 'title',
20
+        right: 'dayGridMonth,dayGridWeek,dayGridDay'
21
+      },
22
+      defaultDate: '2019-08-12',
23
+      navLinks: true, // can click day/week names to navigate views
24
+      editable: true,
25
+      eventLimit: true, // allow "more" link when too many events
26
+      events: [
27
+        {
28
+          title: 'All Day Event',
29
+          start: '2019-08-01'
30
+        },
31
+        {
32
+          title: 'Long Event',
33
+          start: '2019-08-07',
34
+          end: '2019-08-10'
35
+        },
36
+        {
37
+          groupId: 999,
38
+          title: 'Repeating Event',
39
+          start: '2019-08-09T16:00:00'
40
+        },
41
+        {
42
+          groupId: 999,
43
+          title: 'Repeating Event',
44
+          start: '2019-08-16T16:00:00'
45
+        },
46
+        {
47
+          title: 'Conference',
48
+          start: '2019-08-11',
49
+          end: '2019-08-13'
50
+        },
51
+        {
52
+          title: 'Meeting',
53
+          start: '2019-08-12T10:30:00',
54
+          end: '2019-08-12T12:30:00'
55
+        },
56
+        {
57
+          title: 'Lunch',
58
+          start: '2019-08-12T12:00:00'
59
+        },
60
+        {
61
+          title: 'Meeting',
62
+          start: '2019-08-12T14:30:00'
63
+        },
64
+        {
65
+          title: 'Happy Hour',
66
+          start: '2019-08-12T17:30:00'
67
+        },
68
+        {
69
+          title: 'Dinner',
70
+          start: '2019-08-12T20:00:00'
71
+        },
72
+        {
73
+          title: 'Birthday Party',
74
+          start: '2019-08-13T07:00:00'
75
+        },
76
+        {
77
+          title: 'Click for Google',
78
+          url: 'http://google.com/',
79
+          start: '2019-08-28'
80
+        }
81
+      ]
82
+    });
83
+
84
+    calendar.render();
85
+  });
86
+
87
+</script>
88
+<style>
89
+
90
+  body {
91
+    margin: 40px 10px;
92
+    padding: 0;
93
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
94
+    font-size: 14px;
95
+  }
96
+
97
+  #calendar {
98
+    max-width: 900px;
99
+    margin: 0 auto;
100
+  }
101
+
102
+</style>
103
+</head>
104
+<body>
105
+
106
+  <div id='calendar'></div>
107
+
108
+</body>
109
+</html>

+ 75
- 0
processes/fullcalendar/examples/external-dragging-2cals.html View File

@@ -0,0 +1,75 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='../packages/core/main.css' rel='stylesheet' />
6
+<link href='../packages/daygrid/main.css' rel='stylesheet' />
7
+<script src='../packages/core/main.js'></script>
8
+<script src='../packages/interaction/main.js'></script>
9
+<script src='../packages/daygrid/main.js'></script>
10
+<script>
11
+
12
+  document.addEventListener('DOMContentLoaded', function() {
13
+    var srcCalendarEl = document.getElementById('source-calendar');
14
+    var destCalendarEl = document.getElementById('destination-calendar');
15
+
16
+    var srcCalendar = new FullCalendar.Calendar(srcCalendarEl, {
17
+      plugins: [ 'interaction', 'dayGrid' ],
18
+      editable: true,
19
+      defaultDate: '2019-08-12',
20
+      events: [
21
+        {
22
+          title: 'event1',
23
+          start: '2019-08-11T10:00:00',
24
+          end: '2019-08-11T16:00:00'
25
+        },
26
+        {
27
+          title: 'event2',
28
+          start: '2019-08-13T10:00:00',
29
+          end: '2019-08-13T16:00:00'
30
+        }
31
+      ],
32
+      eventLeave: function(info) {
33
+        console.log('event left!', info.event);
34
+      }
35
+    });
36
+
37
+    var destCalendar = new FullCalendar.Calendar(destCalendarEl, {
38
+      plugins: [ 'interaction', 'dayGrid' ],
39
+      defaultDate: '2019-08-12',
40
+      editable: true,
41
+      droppable: true, // will let it receive events!
42
+      eventReceive: function(info) {
43
+        console.log('event received!', info.event);
44
+      }
45
+    });
46
+
47
+    srcCalendar.render();
48
+    destCalendar.render();
49
+  });
50
+
51
+</script>
52
+<style>
53
+
54
+  body {
55
+    margin: 20px 0 0 20px;
56
+    font-size: 14px;
57
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
58
+  }
59
+
60
+  #source-calendar,
61
+  #destination-calendar {
62
+    float: left;
63
+    width: 600px;
64
+    margin: 0 20px 20px 0;
65
+  }
66
+
67
+</style>
68
+</head>
69
+<body>
70
+
71
+  <div id='source-calendar'></div>
72
+  <div id='destination-calendar'></div>
73
+
74
+</body>
75
+</html>

+ 149
- 0
processes/fullcalendar/examples/external-dragging-builtin.html View File

@@ -0,0 +1,149 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='../packages/core/main.css' rel='stylesheet' />
6
+<link href='../packages/daygrid/main.css' rel='stylesheet' />
7
+<link href='../packages/timegrid/main.css' rel='stylesheet' />
8
+<link href='../packages/list/main.css' rel='stylesheet' />
9
+<script src='../packages/core/main.js'></script>
10
+<script src='../packages/interaction/main.js'></script>
11
+<script src='../packages/daygrid/main.js'></script>
12
+<script src='../packages/timegrid/main.js'></script>
13
+<script src='../packages/list/main.js'></script>
14
+<script>
15
+
16
+  document.addEventListener('DOMContentLoaded', function() {
17
+    var Calendar = FullCalendar.Calendar;
18
+    var Draggable = FullCalendarInteraction.Draggable
19
+
20
+    /* initialize the external events
21
+    -----------------------------------------------------------------*/
22
+
23
+    var containerEl = document.getElementById('external-events-list');
24
+    new Draggable(containerEl, {
25
+      itemSelector: '.fc-event',
26
+      eventData: function(eventEl) {
27
+        return {
28
+          title: eventEl.innerText.trim()
29
+        }
30
+      }
31
+    });
32
+
33
+    //// the individual way to do it
34
+    // var containerEl = document.getElementById('external-events-list');
35
+    // var eventEls = Array.prototype.slice.call(
36
+    //   containerEl.querySelectorAll('.fc-event')
37
+    // );
38
+    // eventEls.forEach(function(eventEl) {
39
+    //   new Draggable(eventEl, {
40
+    //     eventData: {
41
+    //       title: eventEl.innerText.trim(),
42
+    //     }
43
+    //   });
44
+    // });
45
+
46
+    /* initialize the calendar
47
+    -----------------------------------------------------------------*/
48
+
49
+    var calendarEl = document.getElementById('calendar');
50
+    var calendar = new Calendar(calendarEl, {
51
+      plugins: [ 'interaction', 'dayGrid', 'timeGrid', 'list' ],
52
+      header: {
53
+        left: 'prev,next today',
54
+        center: 'title',
55
+        right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
56
+      },
57
+      editable: true,
58
+      droppable: true, // this allows things to be dropped onto the calendar
59
+      drop: function(arg) {
60
+        // is the "remove after drop" checkbox checked?
61
+        if (document.getElementById('drop-remove').checked) {
62
+          // if so, remove the element from the "Draggable Events" list
63
+          arg.draggedEl.parentNode.removeChild(arg.draggedEl);
64
+        }
65
+      }
66
+    });
67
+    calendar.render();
68
+
69
+  });
70
+
71
+</script>
72
+<style>
73
+
74
+  body {
75
+    margin-top: 40px;
76
+    font-size: 14px;
77
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
78
+  }
79
+
80
+  #wrap {
81
+    width: 1100px;
82
+    margin: 0 auto;
83
+  }
84
+
85
+  #external-events {
86
+    float: left;
87
+    width: 150px;
88
+    padding: 0 10px;
89
+    border: 1px solid #ccc;
90
+    background: #eee;
91
+    text-align: left;
92
+  }
93
+
94
+  #external-events h4 {
95
+    font-size: 16px;
96
+    margin-top: 0;
97
+    padding-top: 1em;
98
+  }
99
+
100
+  #external-events .fc-event {
101
+    margin: 10px 0;
102
+    cursor: pointer;
103
+  }
104
+
105
+  #external-events p {
106
+    margin: 1.5em 0;
107
+    font-size: 11px;
108
+    color: #666;
109
+  }
110
+
111
+  #external-events p input {
112
+    margin: 0;
113
+    vertical-align: middle;
114
+  }
115
+
116
+  #calendar {
117
+    float: right;
118
+    width: 900px;
119
+  }
120
+
121
+</style>
122
+</head>
123
+<body>
124
+  <div id='wrap'>
125
+
126
+    <div id='external-events'>
127
+      <h4>Draggable Events</h4>
128
+
129
+      <div id='external-events-list'>
130
+        <div class='fc-event'>My Event 1</div>
131
+        <div class='fc-event'>My Event 2</div>
132
+        <div class='fc-event'>My Event 3</div>
133
+        <div class='fc-event'>My Event 4</div>
134
+        <div class='fc-event'>My Event 5</div>
135
+      </div>
136
+
137
+      <p>
138
+        <input type='checkbox' id='drop-remove' />
139
+        <label for='drop-remove'>remove after drop</label>
140
+      </p>
141
+    </div>
142
+
143
+    <div id='calendar'></div>
144
+
145
+    <div style='clear:both'></div>
146
+
147
+  </div>
148
+</body>
149
+</html>

+ 129
- 0
processes/fullcalendar/examples/full-height.html View File

@@ -0,0 +1,129 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='../packages/core/main.css' rel='stylesheet' />
6
+<link href='../packages/daygrid/main.css' rel='stylesheet' />
7
+<link href='../packages/timegrid/main.css' rel='stylesheet' />
8
+<link href='../packages/list/main.css' rel='stylesheet' />
9
+<script src='../packages/core/main.js'></script>
10
+<script src='../packages/interaction/main.js'></script>
11
+<script src='../packages/daygrid/main.js'></script>
12
+<script src='../packages/timegrid/main.js'></script>
13
+<script src='../packages/list/main.js'></script>
14
+<script>
15
+
16
+  document.addEventListener('DOMContentLoaded', function() {
17
+    var calendarEl = document.getElementById('calendar');
18
+
19
+    var calendar = new FullCalendar.Calendar(calendarEl, {
20
+      plugins: [ 'interaction', 'dayGrid', 'timeGrid', 'list' ],
21
+      height: 'parent',
22
+      header: {
23
+        left: 'prev,next today',
24
+        center: 'title',
25
+        right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
26
+      },
27
+      defaultView: 'dayGridMonth',
28
+      defaultDate: '2019-08-12',
29
+      navLinks: true, // can click day/week names to navigate views
30
+      editable: true,
31
+      eventLimit: true, // allow "more" link when too many events
32
+      events: [
33
+        {
34
+          title: 'All Day Event',
35
+          start: '2019-08-01',
36
+        },
37
+        {
38
+          title: 'Long Event',
39
+          start: '2019-08-07',
40
+          end: '2019-08-10'
41
+        },
42
+        {
43
+          groupId: 999,
44
+          title: 'Repeating Event',
45
+          start: '2019-08-09T16:00:00'
46
+        },
47
+        {
48
+          groupId: 999,
49
+          title: 'Repeating Event',
50
+          start: '2019-08-16T16:00:00'
51
+        },
52
+        {
53
+          title: 'Conference',
54
+          start: '2019-08-11',
55
+          end: '2019-08-13'
56
+        },
57
+        {
58
+          title: 'Meeting',
59
+          start: '2019-08-12T10:30:00',
60
+          end: '2019-08-12T12:30:00'
61
+        },
62
+        {
63
+          title: 'Lunch',
64
+          start: '2019-08-12T12:00:00'
65
+        },
66
+        {
67
+          title: 'Meeting',
68
+          start: '2019-08-12T14:30:00'
69
+        },
70
+        {
71
+          title: 'Happy Hour',
72
+          start: '2019-08-12T17:30:00'
73
+        },
74
+        {
75
+          title: 'Dinner',
76
+          start: '2019-08-12T20:00:00'
77
+        },
78
+        {
79
+          title: 'Birthday Party',
80
+          start: '2019-08-13T07:00:00'
81
+        },
82
+        {
83
+          title: 'Click for Google',
84
+          url: 'http://google.com/',
85
+          start: '2019-08-28'
86
+        }
87
+      ]
88
+    });
89
+
90
+    calendar.render();
91
+  });
92
+
93
+</script>
94
+<style>
95
+
96
+  html, body {
97
+    overflow: hidden; /* don't do scrollbars */
98
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
99
+    font-size: 14px;
100
+  }
101
+
102
+  #calendar-container {
103
+    position: fixed;
104
+    top: 0;
105
+    left: 0;
106
+    right: 0;
107
+    bottom: 0;
108
+  }
109
+
110
+  .fc-header-toolbar {
111
+    /*
112
+    the calendar will be butting up against the edges,
113
+    but let's scoot in the header's buttons
114
+    */
115
+    padding-top: 1em;
116
+    padding-left: 1em;
117
+    padding-right: 1em;
118
+  }
119
+
120
+</style>
121
+</head>
122
+<body>
123
+
124
+  <div id='calendar-container'>
125
+    <div id='calendar'></div>
126
+  </div>
127
+
128
+</body>
129
+</html>

+ 86
- 0
processes/fullcalendar/examples/google-calendar.html View File

@@ -0,0 +1,86 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='../packages/core/main.css' rel='stylesheet' />
6
+<link href='../packages/daygrid/main.css' rel='stylesheet' />
7
+<link href='../packages/list/main.css' rel='stylesheet' />
8
+<script src='../packages/core/main.js'></script>
9
+<script src='../packages/interaction/main.js'></script>
10
+<script src='../packages/daygrid/main.js'></script>
11
+<script src='../packages/list/main.js'></script>
12
+<script src='../packages/google-calendar/main.js'></script>
13
+<script>
14
+
15
+  document.addEventListener('DOMContentLoaded', function() {
16
+    var calendarEl = document.getElementById('calendar');
17
+
18
+    var calendar = new FullCalendar.Calendar(calendarEl, {
19
+
20
+      plugins: [ 'interaction', 'dayGrid', 'list', 'googleCalendar' ],
21
+
22
+      header: {
23
+        left: 'prev,next today',
24
+        center: 'title',
25
+        right: 'dayGridMonth,listYear'
26
+      },
27
+
28
+      displayEventTime: false, // don't show the time column in list view
29
+
30
+      // THIS KEY WON'T WORK IN PRODUCTION!!!
31
+      // To make your own Google API key, follow the directions here:
32
+      // http://fullcalendar.io/docs/google_calendar/
33
+      googleCalendarApiKey: 'AIzaSyDcnW6WejpTOCffshGDDb4neIrXVUA1EAE',
34
+
35
+      // US Holidays
36
+      events: 'en.usa#holiday@group.v.calendar.google.com',
37
+
38
+      eventClick: function(arg) {
39
+        // opens events in a popup window
40
+        window.open(arg.event.url, 'google-calendar-event', 'width=700,height=600');
41
+
42
+        arg.jsEvent.preventDefault() // don't navigate in main tab
43
+      },
44
+
45
+      loading: function(bool) {
46
+        document.getElementById('loading').style.display =
47
+          bool ? 'block' : 'none';
48
+      }
49
+
50
+    });
51
+
52
+    calendar.render();
53
+  });
54
+
55
+</script>
56
+<style>
57
+
58
+  body {
59
+    margin: 40px 10px;
60
+    padding: 0;
61
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
62
+    font-size: 14px;
63
+  }
64
+
65
+  #loading {
66
+    display: none;
67
+    position: absolute;
68
+    top: 10px;
69
+    right: 10px;
70
+  }
71
+
72
+  #calendar {
73
+    max-width: 900px;
74
+    margin: 0 auto;
75
+  }
76
+
77
+</style>
78
+</head>
79
+<body>
80
+
81
+  <div id='loading'>loading...</div>
82
+
83
+  <div id='calendar'></div>
84
+
85
+</body>
86
+</html>

+ 141
- 0
processes/fullcalendar/examples/js/theme-chooser.js View File

@@ -0,0 +1,141 @@
1
+
2
+function initThemeChooser(settings) {
3
+  var isInitialized = false;
4
+  var currentThemeSystem; // don't set this directly. use setThemeSystem
5
+  var currentStylesheetEl;
6
+  var loadingEl = document.getElementById('loading');
7
+  var systemSelectEl = document.querySelector('#theme-system-selector select');
8
+  var themeSelectWrapEls = Array.prototype.slice.call( // convert to real array
9
+    document.querySelectorAll('.selector[data-theme-system]')
10
+  );
11
+
12
+  systemSelectEl.addEventListener('change', function() {
13
+    setThemeSystem(this.value);
14
+  });
15
+
16
+  setThemeSystem(systemSelectEl.value);
17
+
18
+  themeSelectWrapEls.forEach(function(themeSelectWrapEl) {
19
+    var themeSelectEl = themeSelectWrapEl.querySelector('select');
20
+
21
+    themeSelectWrapEl.addEventListener('change', function() {
22
+      setTheme(
23
+        currentThemeSystem,
24
+        themeSelectEl.options[themeSelectEl.selectedIndex].value
25
+      );
26
+    });
27
+  });
28
+
29
+
30
+  function setThemeSystem(themeSystem) {
31
+    var selectedTheme;
32
+
33
+    currentThemeSystem = themeSystem;
34
+
35
+    themeSelectWrapEls.forEach(function(themeSelectWrapEl) {
36
+      var themeSelectEl = themeSelectWrapEl.querySelector('select');
37
+
38
+      if (themeSelectWrapEl.getAttribute('data-theme-system') === themeSystem) {
39
+        selectedTheme = themeSelectEl.options[themeSelectEl.selectedIndex].value;
40
+        themeSelectWrapEl.style.display = 'inline-block';
41
+      } else {
42
+        themeSelectWrapEl.style.display = 'none';
43
+      }
44
+    });
45
+
46
+    setTheme(themeSystem, selectedTheme);
47
+  }
48
+
49
+
50
+  function setTheme(themeSystem, themeName) {
51
+    var stylesheetUrl = generateStylesheetUrl(themeSystem, themeName);
52
+    var stylesheetEl;
53
+
54
+    function done() {
55
+      if (!isInitialized) {
56
+        isInitialized = true;
57
+        settings.init(themeSystem);
58
+      }
59
+      else {
60
+        settings.change(themeSystem);
61
+      }
62
+
63
+      showCredits(themeSystem, themeName);
64
+    }
65
+
66
+    if (stylesheetUrl) {
67
+      stylesheetEl = document.createElement('link');
68
+      stylesheetEl.setAttribute('rel', 'stylesheet');
69
+      stylesheetEl.setAttribute('href', stylesheetUrl);
70
+      document.querySelector('head').appendChild(stylesheetEl);
71
+
72
+      loadingEl.style.display = 'inline';
73
+
74
+      whenStylesheetLoaded(stylesheetEl, function() {
75
+        if (currentStylesheetEl) {
76
+          currentStylesheetEl.parentNode.removeChild(currentStylesheetEl);
77
+        }
78
+        currentStylesheetEl = stylesheetEl;
79
+        loadingEl.style.display = 'none';
80
+        done();
81
+      });
82
+    } else {
83
+      if (currentStylesheetEl) {
84
+        currentStylesheetEl.parentNode.removeChild(currentStylesheetEl);
85
+        currentStylesheetEl = null
86
+      }
87
+      done();
88
+    }
89
+  }
90
+
91
+
92
+  function generateStylesheetUrl(themeSystem, themeName) {
93
+    if (themeSystem === 'bootstrap') {
94
+      if (themeName) {
95
+        return 'https://bootswatch.com/4/' + themeName + '/bootstrap.min.css';
96
+      }
97
+      else { // the default bootstrap theme
98
+        return 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css';
99
+      }
100
+    }
101
+  }
102
+
103
+
104
+  function showCredits(themeSystem, themeName) {
105
+    var creditId;
106
+
107
+    if (themeSystem.match('bootstrap')) {
108
+      if (themeName) {
109
+        creditId = 'bootstrap-custom';
110
+      }
111
+      else {
112
+        creditId = 'bootstrap-standard';
113
+      }
114
+    }
115
+
116
+    Array.prototype.slice.call( // convert to real array
117
+      document.querySelectorAll('.credits')
118
+    ).forEach(function(creditEl) {
119
+      if (creditEl.getAttribute('data-credit-id') === creditId) {
120
+        creditEl.style.display = 'block';
121
+      } else {
122
+        creditEl.style.display = 'none';
123
+      }
124
+    })
125
+  }
126
+
127
+
128
+  function whenStylesheetLoaded(linkNode, callback) {
129
+    var isReady = false;
130
+
131
+    function ready() {
132
+      if (!isReady) { // avoid double-call
133
+        isReady = true;
134
+        callback();
135
+      }
136
+    }
137
+
138
+    linkNode.onload = ready; // does not work cross-browser
139
+    setTimeout(ready, 2000); // max wait. also handles browsers that don't support onload
140
+  }
141
+}

+ 93
- 0
processes/fullcalendar/examples/json.html View File

@@ -0,0 +1,93 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='../packages/core/main.css' rel='stylesheet' />
6
+<link href='../packages/daygrid/main.css' rel='stylesheet' />
7
+<link href='../packages/timegrid/main.css' rel='stylesheet' />
8
+<link href='../packages/list/main.css' rel='stylesheet' />
9
+<script src='../packages/core/main.js'></script>
10
+<script src='../packages/interaction/main.js'></script>
11
+<script src='../packages/daygrid/main.js'></script>
12
+<script src='../packages/timegrid/main.js'></script>
13
+<script src='../packages/list/main.js'></script>
14
+<script>
15
+
16
+  document.addEventListener('DOMContentLoaded', function() {
17
+    var calendarEl = document.getElementById('calendar');
18
+
19
+    var calendar = new FullCalendar.Calendar(calendarEl, {
20
+      plugins: [ 'interaction', 'dayGrid', 'timeGrid', 'list' ],
21
+      header: {
22
+        left: 'prev,next today',
23
+        center: 'title',
24
+        right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
25
+      },
26
+      defaultDate: '2019-08-12',
27
+      editable: true,
28
+      navLinks: true, // can click day/week names to navigate views
29
+      eventLimit: true, // allow "more" link when too many events
30
+      events: {
31
+        url: 'php/get-events.php',
32
+        failure: function() {
33
+          document.getElementById('script-warning').style.display = 'block'
34
+        }
35
+      },
36
+      loading: function(bool) {
37
+        document.getElementById('loading').style.display =
38
+          bool ? 'block' : 'none';
39
+      }
40
+    });
41
+
42
+    calendar.render();
43
+  });
44
+
45
+</script>
46
+<style>
47
+
48
+  body {
49
+    margin: 0;
50
+    padding: 0;
51
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
52
+    font-size: 14px;
53
+  }
54
+
55
+  #script-warning {
56
+    display: none;
57
+    background: #eee;
58
+    border-bottom: 1px solid #ddd;
59
+    padding: 0 10px;
60
+    line-height: 40px;
61
+    text-align: center;
62
+    font-weight: bold;
63
+    font-size: 12px;
64
+    color: red;
65
+  }
66
+
67
+  #loading {
68
+    display: none;
69
+    position: absolute;
70
+    top: 10px;
71
+    right: 10px;
72
+  }
73
+
74
+  #calendar {
75
+    max-width: 900px;
76
+    margin: 40px auto;
77
+    padding: 0 10px;
78
+  }
79
+
80
+</style>
81
+</head>
82
+<body>
83
+
84
+  <div id='script-warning'>
85
+    <code>php/get-events.php</code> must be running.
86
+  </div>
87
+
88
+  <div id='loading'>loading...</div>
89
+
90
+  <div id='calendar'></div>
91
+
92
+</body>
93
+</html>

+ 56
- 0
processes/fullcalendar/examples/json/events.json View File

@@ -0,0 +1,56 @@
1
+[
2
+  {
3
+    "title": "All Day Event",
4
+    "start": "2019-08-01"
5
+  },
6
+  {
7
+    "title": "Long Event",
8
+    "start": "2019-08-07",
9
+    "end": "2019-08-10"
10
+  },
11
+  {
12
+    "id": "999",
13
+    "title": "Repeating Event",
14
+    "start": "2019-08-09T16:00:00-05:00"
15
+  },
16
+  {
17
+    "id": "999",
18
+    "title": "Repeating Event",
19
+    "start": "2019-08-16T16:00:00-05:00"
20
+  },
21
+  {
22
+    "title": "Conference",
23
+    "start": "2019-08-11",
24
+    "end": "2019-08-13"
25
+  },
26
+  {
27
+    "title": "Meeting",
28
+    "start": "2019-08-12T10:30:00-05:00",
29
+    "end": "2019-08-12T12:30:00-05:00"
30
+  },
31
+  {
32
+    "title": "Lunch",
33
+    "start": "2019-08-12T12:00:00-05:00"
34
+  },
35
+  {
36
+    "title": "Meeting",
37
+    "start": "2019-08-12T14:30:00-05:00"
38
+  },
39
+  {
40
+    "title": "Happy Hour",
41
+    "start": "2019-08-12T17:30:00-05:00"
42
+  },
43
+  {
44
+    "title": "Dinner",
45
+    "start": "2019-08-12T20:00:00"
46
+  },
47
+  {
48
+    "title": "Birthday Party",
49
+    "start": "2019-08-13T07:00:00-05:00"
50
+  },
51
+  {
52
+    "title": "Click for Google",
53
+    "url": "http://google.com/",
54
+    "start": "2019-08-28"
55
+  }
56
+]

+ 118
- 0
processes/fullcalendar/examples/list-views.html View File

@@ -0,0 +1,118 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='../packages/core/main.css' rel='stylesheet' />
6
+<link href='../packages/list/main.css' rel='stylesheet' />
7
+<script src='../packages/core/main.js'></script>
8
+<script src='../packages/list/main.js'></script>
9
+<script>
10
+
11
+  document.addEventListener('DOMContentLoaded', function() {
12
+    var calendarEl = document.getElementById('calendar');
13
+
14
+    var calendar = new FullCalendar.Calendar(calendarEl, {
15
+      plugins: [ 'list' ],
16
+
17
+      header: {
18
+        left: 'prev,next today',
19
+        center: 'title',
20
+        right: 'listDay,listWeek,dayGridMonth'
21
+      },
22
+
23
+      // customize the button names,
24
+      // otherwise they'd all just say "list"
25
+      views: {
26
+        listDay: { buttonText: 'list day' },
27
+        listWeek: { buttonText: 'list week' }
28
+      },
29
+
30
+      defaultView: 'listWeek',
31
+      defaultDate: '2019-08-12',
32
+      navLinks: true, // can click day/week names to navigate views
33
+      editable: true,
34
+      eventLimit: true, // allow "more" link when too many events
35
+      events: [
36
+        {
37
+          title: 'All Day Event',
38
+          start: '2019-08-01'
39
+        },
40
+        {
41
+          title: 'Long Event',
42
+          start: '2019-08-07',
43
+          end: '2019-08-10'
44
+        },
45
+        {
46
+          groupId: 999,
47
+          title: 'Repeating Event',
48
+          start: '2019-08-09T16:00:00'
49
+        },
50
+        {
51
+          groupId: 999,
52
+          title: 'Repeating Event',
53
+          start: '2019-08-16T16:00:00'
54
+        },
55
+        {
56
+          title: 'Conference',
57
+          start: '2019-08-11',
58
+          end: '2019-08-13'
59
+        },
60
+        {
61
+          title: 'Meeting',
62
+          start: '2019-08-12T10:30:00',
63
+          end: '2019-08-12T12:30:00'
64
+        },
65
+        {
66
+          title: 'Lunch',
67
+          start: '2019-08-12T12:00:00'
68
+        },
69
+        {
70
+          title: 'Meeting',
71
+          start: '2019-08-12T14:30:00'
72
+        },
73
+        {
74
+          title: 'Happy Hour',
75
+          start: '2019-08-12T17:30:00'
76
+        },
77
+        {
78
+          title: 'Dinner',
79
+          start: '2019-08-12T20:00:00'
80
+        },
81
+        {
82
+          title: 'Birthday Party',
83
+          start: '2019-08-13T07:00:00'
84
+        },
85
+        {
86
+          title: 'Click for Google',
87
+          url: 'http://google.com/',
88
+          start: '2019-08-28'
89
+        }
90
+      ]
91
+    });
92
+
93
+    calendar.render();
94
+  });
95
+
96
+</script>
97
+<style>
98
+
99
+  body {
100
+    margin: 40px 10px;
101
+    padding: 0;
102
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
103
+    font-size: 14px;
104
+  }
105
+
106
+  #calendar {
107
+    max-width: 900px;
108
+    margin: 0 auto;
109
+  }
110
+
111
+</style>
112
+</head>
113
+<body>
114
+
115
+  <div id='calendar'></div>
116
+
117
+</body>
118
+</html>

+ 152
- 0
processes/fullcalendar/examples/locales.html View File

@@ -0,0 +1,152 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='../packages/core/main.css' rel='stylesheet' />
6
+<link href='../packages/daygrid/main.css' rel='stylesheet' />
7
+<link href='../packages/timegrid/main.css' rel='stylesheet' />
8
+<link href='../packages/list/main.css' rel='stylesheet' />
9
+<script src='../packages/core/main.js'></script>
10
+<script src='../packages/core/locales-all.js'></script>
11
+<script src='../packages/interaction/main.js'></script>
12
+<script src='../packages/daygrid/main.js'></script>
13
+<script src='../packages/timegrid/main.js'></script>
14
+<script src='../packages/list/main.js'></script>
15
+<script>
16
+
17
+  document.addEventListener('DOMContentLoaded', function() {
18
+    var initialLocaleCode = 'en';
19
+    var localeSelectorEl = document.getElementById('locale-selector');
20
+    var calendarEl = document.getElementById('calendar');
21
+
22
+    var calendar = new FullCalendar.Calendar(calendarEl, {
23
+      plugins: [ 'interaction', 'dayGrid', 'timeGrid', 'list' ],
24
+      header: {
25
+        left: 'prev,next today',
26
+        center: 'title',
27
+        right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth'
28
+      },
29
+      defaultDate: '2019-08-12',
30
+      locale: initialLocaleCode,
31
+      buttonIcons: false, // show the prev/next text
32
+      weekNumbers: true,
33
+      navLinks: true, // can click day/week names to navigate views
34
+      editable: true,
35
+      eventLimit: true, // allow "more" link when too many events
36
+      events: [
37
+        {
38
+          title: 'All Day Event',
39
+          start: '2019-08-01'
40
+        },
41
+        {
42
+          title: 'Long Event',
43
+          start: '2019-08-07',
44
+          end: '2019-08-10'
45
+        },
46
+        {
47
+          groupId: 999,
48
+          title: 'Repeating Event',
49
+          start: '2019-08-09T16:00:00'
50
+        },
51
+        {
52
+          groupId: 999,
53
+          title: 'Repeating Event',
54
+          start: '2019-08-16T16:00:00'
55
+        },
56
+        {
57
+          title: 'Conference',
58
+          start: '2019-08-11',
59
+          end: '2019-08-13'
60
+        },
61
+        {
62
+          title: 'Meeting',
63
+          start: '2019-08-12T10:30:00',
64
+          end: '2019-08-12T12:30:00'
65
+        },
66
+        {
67
+          title: 'Lunch',
68
+          start: '2019-08-12T12:00:00'
69
+        },
70
+        {
71
+          title: 'Meeting',
72
+          start: '2019-08-12T14:30:00'
73
+        },
74
+        {
75
+          title: 'Happy Hour',
76
+          start: '2019-08-12T17:30:00'
77
+        },
78
+        {
79
+          title: 'Dinner',
80
+          start: '2019-08-12T20:00:00'
81
+        },
82
+        {
83
+          title: 'Birthday Party',
84
+          start: '2019-08-13T07:00:00'
85
+        },
86
+        {
87
+          title: 'Click for Google',
88
+          url: 'http://google.com/',
89
+          start: '2019-08-28'
90
+        }
91
+      ]
92
+    });
93
+
94
+    calendar.render();
95
+
96
+    // build the locale selector's options
97
+    calendar.getAvailableLocaleCodes().forEach(function(localeCode) {
98
+      var optionEl = document.createElement('option');
99
+      optionEl.value = localeCode;
100
+      optionEl.selected = localeCode == initialLocaleCode;
101
+      optionEl.innerText = localeCode;
102
+      localeSelectorEl.appendChild(optionEl);
103
+    });
104
+
105
+    // when the selected option changes, dynamically change the calendar option
106
+    localeSelectorEl.addEventListener('change', function() {
107
+      if (this.value) {
108
+        calendar.setOption('locale', this.value);
109
+      }
110
+    });
111
+
112
+  });
113
+
114
+</script>
115
+<style>
116
+
117
+  body {
118
+    margin: 0;
119
+    padding: 0;
120
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
121
+    font-size: 14px;
122
+  }
123
+
124
+  #top {
125
+    background: #eee;
126
+    border-bottom: 1px solid #ddd;
127
+    padding: 0 10px;
128
+    line-height: 40px;
129
+    font-size: 12px;
130
+  }
131
+
132
+  #calendar {
133
+    max-width: 900px;
134
+    margin: 40px auto;
135
+    padding: 0 10px;
136
+  }
137
+
138
+</style>
139
+</head>
140
+<body>
141
+
142
+  <div id='top'>
143
+
144
+    Locales:
145
+    <select id='locale-selector'></select>
146
+
147
+  </div>
148
+
149
+  <div id='calendar'></div>
150
+
151
+</body>
152
+</html>

+ 103
- 0
processes/fullcalendar/examples/month-view.html View File

@@ -0,0 +1,103 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='../packages/core/main.css' rel='stylesheet' />
6
+<link href='../packages/daygrid/main.css' rel='stylesheet' />
7
+<script src='../packages/core/main.js'></script>
8
+<script src='../packages/interaction/main.js'></script>
9
+<script src='../packages/daygrid/main.js'></script>
10
+<script>
11
+
12
+  document.addEventListener('DOMContentLoaded', function() {
13
+    var calendarEl = document.getElementById('calendar');
14
+
15
+    var calendar = new FullCalendar.Calendar(calendarEl, {
16
+      plugins: [ 'interaction', 'dayGrid' ],
17
+      defaultDate: '2019-08-12',
18
+      editable: true,
19
+      eventLimit: true, // allow "more" link when too many events
20
+      events: [
21
+        {
22
+          title: 'All Day Event',
23
+          start: '2019-08-01'
24
+        },
25
+        {
26
+          title: 'Long Event',
27
+          start: '2019-08-07',
28
+          end: '2019-08-10'
29
+        },
30
+        {
31
+          groupId: 999,
32
+          title: 'Repeating Event',
33
+          start: '2019-08-09T16:00:00'
34
+        },
35
+        {
36
+          groupId: 999,
37
+          title: 'Repeating Event',
38
+          start: '2019-08-16T16:00:00'
39
+        },
40
+        {
41
+          title: 'Conference',
42
+          start: '2019-08-11',
43
+          end: '2019-08-13'
44
+        },
45
+        {
46
+          title: 'Meeting',
47
+          start: '2019-08-12T10:30:00',
48
+          end: '2019-08-12T12:30:00'
49
+        },
50
+        {
51
+          title: 'Lunch',
52
+          start: '2019-08-12T12:00:00'
53
+        },
54
+        {
55
+          title: 'Meeting',
56
+          start: '2019-08-12T14:30:00'
57
+        },
58
+        {
59
+          title: 'Happy Hour',
60
+          start: '2019-08-12T17:30:00'
61
+        },
62
+        {
63
+          title: 'Dinner',
64
+          start: '2019-08-12T20:00:00'
65
+        },
66
+        {
67
+          title: 'Birthday Party',
68
+          start: '2019-08-13T07:00:00'
69
+        },
70
+        {
71
+          title: 'Click for Google',
72
+          url: 'http://google.com/',
73
+          start: '2019-08-28'
74
+        }
75
+      ]
76
+    });
77
+
78
+    calendar.render();
79
+  });
80
+
81
+</script>
82
+<style>
83
+
84
+  body {
85
+    margin: 40px 10px;
86
+    padding: 0;
87
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
88
+    font-size: 14px;
89
+  }
90
+
91
+  #calendar {
92
+    max-width: 900px;
93
+    margin: 0 auto;
94
+  }
95
+
96
+</style>
97
+</head>
98
+<body>
99
+
100
+  <div id='calendar'></div>
101
+
102
+</body>
103
+</html>

+ 50
- 0
processes/fullcalendar/examples/php/get-events.php View File

@@ -0,0 +1,50 @@
1
+<?php
2
+
3
+//--------------------------------------------------------------------------------------------------
4
+// This script reads event data from a JSON file and outputs those events which are within the range
5
+// supplied by the "start" and "end" GET parameters.
6
+//
7
+// An optional "timeZone" GET parameter will force all ISO8601 date stings to a given timeZone.
8
+//
9
+// Requires PHP 5.2.0 or higher.
10
+//--------------------------------------------------------------------------------------------------
11
+
12
+// Require our Event class and datetime utilities
13
+require dirname(__FILE__) . '/utils.php';
14
+
15
+// Short-circuit if the client did not give us a date range.
16
+if (!isset($_GET['start']) || !isset($_GET['end'])) {
17
+  die("Please provide a date range.");
18
+}
19
+
20
+// Parse the start/end parameters.
21
+// These are assumed to be ISO8601 strings with no time nor timeZone, like "2013-12-29".
22
+// Since no timeZone will be present, they will parsed as UTC.
23
+$range_start = parseDateTime($_GET['start']);
24
+$range_end = parseDateTime($_GET['end']);
25
+
26
+// Parse the timeZone parameter if it is present.
27
+$time_zone = null;
28
+if (isset($_GET['timeZone'])) {
29
+  $time_zone = new DateTimeZone($_GET['timeZone']);
30
+}
31
+
32
+// Read and parse our events JSON file into an array of event data arrays.
33
+$json = file_get_contents(dirname(__FILE__) . '/../json/events.json');
34
+$input_arrays = json_decode($json, true);
35
+
36
+// Accumulate an output array of event data arrays.
37
+$output_arrays = array();
38
+foreach ($input_arrays as $array) {
39
+
40
+  // Convert the input array into a useful Event object
41
+  $event = new Event($array, $time_zone);
42
+
43
+  // If the event is in-bounds, add it to the output
44
+  if ($event->isWithinDayRange($range_start, $range_end)) {
45
+    $output_arrays[] = $event->toArray();
46
+  }
47
+}
48
+
49
+// Send JSON to the client.
50
+echo json_encode($output_arrays);

+ 9
- 0
processes/fullcalendar/examples/php/get-time-zones.php View File

@@ -0,0 +1,9 @@
1
+<?php
2
+
3
+//--------------------------------------------------------------------------------------------------
4
+// This script outputs a JSON array of all timezones (like "America/Chicago") that PHP supports.
5
+//
6
+// Requires PHP 5.2.0 or higher.
7
+//--------------------------------------------------------------------------------------------------
8
+
9
+echo json_encode(DateTimeZone::listIdentifiers());

+ 130
- 0
processes/fullcalendar/examples/php/utils.php View File

@@ -0,0 +1,130 @@
1
+<?php
2
+
3
+//--------------------------------------------------------------------------------------------------
4
+// Utilities for our event-fetching scripts.
5
+//
6
+// Requires PHP 5.2.0 or higher.
7
+//--------------------------------------------------------------------------------------------------
8
+
9
+// PHP will fatal error if we attempt to use the DateTime class without this being set.
10
+date_default_timezone_set('UTC');
11
+
12
+
13
+class Event {
14
+
15
+  // Tests whether the given ISO8601 string has a time-of-day or not
16
+  const ALL_DAY_REGEX = '/^\d{4}-\d\d-\d\d$/'; // matches strings like "2013-12-29"
17
+
18
+  public $title;
19
+  public $allDay; // a boolean
20
+  public $start; // a DateTime
21
+  public $end; // a DateTime, or null
22
+  public $properties = array(); // an array of other misc properties
23
+
24
+
25
+  // Constructs an Event object from the given array of key=>values.
26
+  // You can optionally force the timeZone of the parsed dates.
27
+  public function __construct($array, $timeZone=null) {
28
+
29
+    $this->title = $array['title'];
30
+
31
+    if (isset($array['allDay'])) {
32
+      // allDay has been explicitly specified
33
+      $this->allDay = (bool)$array['allDay'];
34
+    }
35
+    else {
36
+      // Guess allDay based off of ISO8601 date strings
37
+      $this->allDay = preg_match(self::ALL_DAY_REGEX, $array['start']) &&
38
+        (!isset($array['end']) || preg_match(self::ALL_DAY_REGEX, $array['end']));
39
+    }
40
+
41
+    if ($this->allDay) {
42
+      // If dates are allDay, we want to parse them in UTC to avoid DST issues.
43
+      $timeZone = null;
44
+    }
45
+
46
+    // Parse dates
47
+    $this->start = parseDateTime($array['start'], $timeZone);
48
+    $this->end = isset($array['end']) ? parseDateTime($array['end'], $timeZone) : null;
49
+
50
+    // Record misc properties
51
+    foreach ($array as $name => $value) {
52
+      if (!in_array($name, array('title', 'allDay', 'start', 'end'))) {
53
+        $this->properties[$name] = $value;
54
+      }
55
+    }
56
+  }
57
+
58
+
59
+  // Returns whether the date range of our event intersects with the given all-day range.
60
+  // $rangeStart and $rangeEnd are assumed to be dates in UTC with 00:00:00 time.
61
+  public function isWithinDayRange($rangeStart, $rangeEnd) {
62
+
63
+    // Normalize our event's dates for comparison with the all-day range.
64
+    $eventStart = stripTime($this->start);
65
+
66
+    if (isset($this->end)) {
67
+      $eventEnd = stripTime($this->end); // normalize
68
+    }
69
+    else {
70
+      $eventEnd = $eventStart; // consider this a zero-duration event
71
+    }
72
+
73
+    // Check if the two whole-day ranges intersect.
74
+    return $eventStart < $rangeEnd && $eventEnd >= $rangeStart;
75
+  }
76
+
77
+
78
+  // Converts this Event object back to a plain data array, to be used for generating JSON
79
+  public function toArray() {
80
+
81
+    // Start with the misc properties (don't worry, PHP won't affect the original array)
82
+    $array = $this->properties;
83
+
84
+    $array['title'] = $this->title;
85
+
86
+    // Figure out the date format. This essentially encodes allDay into the date string.
87
+    if ($this->allDay) {
88
+      $format = 'Y-m-d'; // output like "2013-12-29"
89
+    }
90
+    else {
91
+      $format = 'c'; // full ISO8601 output, like "2013-12-29T09:00:00+08:00"
92
+    }
93
+
94
+    // Serialize dates into strings
95
+    $array['start'] = $this->start->format($format);
96
+    if (isset($this->end)) {
97
+      $array['end'] = $this->end->format($format);
98
+    }
99
+
100
+    return $array;
101
+  }
102
+
103
+}
104
+
105
+
106
+// Date Utilities
107
+//----------------------------------------------------------------------------------------------
108
+
109
+
110
+// Parses a string into a DateTime object, optionally forced into the given timeZone.
111
+function parseDateTime($string, $timeZone=null) {
112
+  $date = new DateTime(
113
+    $string,
114
+    $timeZone ? $timeZone : new DateTimeZone('UTC')
115
+      // Used only when the string is ambiguous.
116
+      // Ignored if string has a timeZone offset in it.
117
+  );
118
+  if ($timeZone) {
119
+    // If our timeZone was ignored above, force it.
120
+    $date->setTimezone($timeZone);
121
+  }
122
+  return $date;
123
+}
124
+
125
+
126
+// Takes the year/month/date values of the given DateTime and converts them to a new DateTime,
127
+// but in UTC.
128
+function stripTime($datetime) {
129
+  return new DateTime($datetime->format('Y-m-d'));
130
+}

+ 73
- 0
processes/fullcalendar/examples/rrule.html View File

@@ -0,0 +1,73 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='../packages/core/main.css' rel='stylesheet' />
6
+<link href='../packages/daygrid/main.css' rel='stylesheet' />
7
+<link href='../packages/timegrid/main.css' rel='stylesheet' />
8
+<link href='../packages/list/main.css' rel='stylesheet' />
9
+<script src='../vendor/rrule.js'></script>
10
+<script src='../packages/core/main.js'></script>
11
+<script src='../packages/interaction/main.js'></script>
12
+<script src='../packages/daygrid/main.js'></script>
13
+<script src='../packages/timegrid/main.js'></script>
14
+<script src='../packages/list/main.js'></script>
15
+<script src='../packages/rrule/main.js'></script>
16
+<script>
17
+
18
+  document.addEventListener('DOMContentLoaded', function() {
19
+    var calendarEl = document.getElementById('calendar');
20
+
21
+    var calendar = new FullCalendar.Calendar(calendarEl, {
22
+      plugins: [ 'interaction', 'dayGrid', 'timeGrid', 'list', 'rrule' ],
23
+      header: {
24
+        left: 'prev,next today',
25
+        center: 'title',
26
+        right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth'
27
+      },
28
+      defaultDate: '2019-08-12',
29
+      editable: true,
30
+      events: [
31
+        {
32
+          title: 'rrule event',
33
+          rrule: {
34
+            dtstart: '2019-08-09T13:00:00',
35
+            // until: '2019-08-01',
36
+            freq: 'weekly'
37
+          },
38
+          duration: '02:00'
39
+        }
40
+      ],
41
+      eventClick: function(arg) {
42
+        if (confirm('delete event?')) {
43
+          arg.event.remove()
44
+        }
45
+      }
46
+    });
47
+
48
+    calendar.render();
49
+  });
50
+
51
+</script>
52
+<style>
53
+
54
+  body {
55
+    margin: 40px 10px;
56
+    padding: 0;
57
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
58
+    font-size: 14px;
59
+  }
60
+
61
+  #calendar {
62
+    max-width: 900px;
63
+    margin: 0 auto;
64
+  }
65
+
66
+</style>
67
+</head>
68
+<body>
69
+
70
+  <div id='calendar'></div>
71
+
72
+</body>
73
+</html>

+ 125
- 0
processes/fullcalendar/examples/selectable.html View File

@@ -0,0 +1,125 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='../packages/core/main.css' rel='stylesheet' />
6
+<link href='../packages/daygrid/main.css' rel='stylesheet' />
7
+<link href='../packages/timegrid/main.css' rel='stylesheet' />
8
+<script src='../packages/core/main.js'></script>
9
+<script src='../packages/interaction/main.js'></script>
10
+<script src='../packages/daygrid/main.js'></script>
11
+<script src='../packages/timegrid/main.js'></script>
12
+<script>
13
+
14
+  document.addEventListener('DOMContentLoaded', function() {
15
+    var calendarEl = document.getElementById('calendar');
16
+
17
+    var calendar = new FullCalendar.Calendar(calendarEl, {
18
+      plugins: [ 'interaction', 'dayGrid', 'timeGrid' ],
19
+      header: {
20
+        left: 'prev,next today',
21
+        center: 'title',
22
+        right: 'dayGridMonth,timeGridWeek,timeGridDay'
23
+      },
24
+      defaultDate: '2019-08-12',
25
+      navLinks: true, // can click day/week names to navigate views
26
+      selectable: true,
27
+      selectMirror: true,
28
+      select: function(arg) {
29
+        var title = prompt('Event Title:');
30
+        if (title) {
31
+          calendar.addEvent({
32
+            title: title,
33
+            start: arg.start,
34
+            end: arg.end,
35
+            allDay: arg.allDay
36
+          })
37
+        }
38
+        calendar.unselect()
39
+      },
40
+      editable: true,
41
+      eventLimit: true, // allow "more" link when too many events
42
+      events: [
43
+        {
44
+          title: 'All Day Event',
45
+          start: '2019-08-01'
46
+        },
47
+        {
48
+          title: 'Long Event',
49
+          start: '2019-08-07',
50
+          end: '2019-08-10'
51
+        },
52
+        {
53
+          groupId: 999,
54
+          title: 'Repeating Event',
55
+          start: '2019-08-09T16:00:00'
56
+        },
57
+        {
58
+          groupId: 999,
59
+          title: 'Repeating Event',
60
+          start: '2019-08-16T16:00:00'
61
+        },
62
+        {
63
+          title: 'Conference',
64
+          start: '2019-08-11',
65
+          end: '2019-08-13'
66
+        },
67
+        {
68
+          title: 'Meeting',
69
+          start: '2019-08-12T10:30:00',
70
+          end: '2019-08-12T12:30:00'
71
+        },
72
+        {
73
+          title: 'Lunch',
74
+          start: '2019-08-12T12:00:00'
75
+        },
76
+        {
77
+          title: 'Meeting',
78
+          start: '2019-08-12T14:30:00'
79
+        },
80
+        {
81
+          title: 'Happy Hour',
82
+          start: '2019-08-12T17:30:00'
83
+        },
84
+        {
85
+          title: 'Dinner',
86
+          start: '2019-08-12T20:00:00'
87
+        },
88
+        {
89
+          title: 'Birthday Party',
90
+          start: '2019-08-13T07:00:00'
91
+        },
92
+        {
93
+          title: 'Click for Google',
94
+          url: 'http://google.com/',
95
+          start: '2019-08-28'
96
+        }
97
+      ]
98
+    });
99
+
100
+    calendar.render();
101
+  });
102
+
103
+</script>
104
+<style>
105
+
106
+  body {
107
+    margin: 40px 10px;
108
+    padding: 0;
109
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
110
+    font-size: 14px;
111
+  }
112
+
113
+  #calendar {
114
+    max-width: 900px;
115
+    margin: 0 auto;
116
+  }
117
+
118
+</style>
119
+</head>
120
+<body>
121
+
122
+  <div id='calendar'></div>
123
+
124
+</body>
125
+</html>

+ 215
- 0
processes/fullcalendar/examples/theming.html View File

@@ -0,0 +1,215 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='https://use.fontawesome.com/releases/v5.0.6/css/all.css' rel='stylesheet'>
6
+<link href='../packages/core/main.css' rel='stylesheet' />
7
+<link href='../packages/bootstrap/main.css' rel='stylesheet' />
8
+<link href='../packages/timegrid/main.css' rel='stylesheet' />
9
+<link href='../packages/daygrid/main.css' rel='stylesheet' />
10
+<link href='../packages/list/main.css' rel='stylesheet' />
11
+<script src='../packages/core/main.js'></script>
12
+<script src='../packages/interaction/main.js'></script>
13
+<script src='../packages/bootstrap/main.js'></script>
14
+<script src='../packages/daygrid/main.js'></script>
15
+<script src='../packages/timegrid/main.js'></script>
16
+<script src='../packages/list/main.js'></script>
17
+<script src='js/theme-chooser.js'></script>
18
+<script>
19
+
20
+  document.addEventListener('DOMContentLoaded', function() {
21
+    var calendarEl = document.getElementById('calendar');
22
+    var calendar;
23
+
24
+    initThemeChooser({
25
+
26
+      init: function(themeSystem) {
27
+        calendar = new FullCalendar.Calendar(calendarEl, {
28
+          plugins: [ 'bootstrap', 'interaction', 'dayGrid', 'timeGrid', 'list' ],
29
+          themeSystem: themeSystem,
30
+          header: {
31
+            left: 'prev,next today',
32
+            center: 'title',
33
+            right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth'
34
+          },
35
+          defaultDate: '2019-08-12',
36
+          weekNumbers: true,
37
+          navLinks: true, // can click day/week names to navigate views
38
+          editable: true,
39
+          eventLimit: true, // allow "more" link when too many events
40
+          events: [
41
+            {
42
+              title: 'All Day Event',
43
+              start: '2019-08-01'
44
+            },
45
+            {
46
+              title: 'Long Event',
47
+              start: '2019-08-07',
48
+              end: '2019-08-10'
49
+            },
50
+            {
51
+              groupId: 999,
52
+              title: 'Repeating Event',
53
+              start: '2019-08-09T16:00:00'
54
+            },
55
+            {
56
+              groupId: 999,
57
+              title: 'Repeating Event',
58
+              start: '2019-08-16T16:00:00'
59
+            },
60
+            {
61
+              title: 'Conference',
62
+              start: '2019-08-11',
63
+              end: '2019-08-13'
64
+            },
65
+            {
66
+              title: 'Meeting',
67
+              start: '2019-08-12T10:30:00',
68
+              end: '2019-08-12T12:30:00'
69
+            },
70
+            {
71
+              title: 'Lunch',
72
+              start: '2019-08-12T12:00:00'
73
+            },
74
+            {
75
+              title: 'Meeting',
76
+              start: '2019-08-12T14:30:00'
77
+            },
78
+            {
79
+              title: 'Happy Hour',
80
+              start: '2019-08-12T17:30:00'
81
+            },
82
+            {
83
+              title: 'Dinner',
84
+              start: '2019-08-12T20:00:00'
85
+            },
86
+            {
87
+              title: 'Birthday Party',
88
+              start: '2019-08-13T07:00:00'
89
+            },
90
+            {
91
+              title: 'Click for Google',
92
+              url: 'http://google.com/',
93
+              start: '2019-08-28'
94
+            }
95
+          ]
96
+        });
97
+        calendar.render();
98
+      },
99
+
100
+      change: function(themeSystem) {
101
+        calendar.setOption('themeSystem', themeSystem);
102
+      }
103
+
104
+    });
105
+
106
+  });
107
+
108
+</script>
109
+<style>
110
+
111
+  body {
112
+    margin: 0;
113
+    padding: 0;
114
+    font-size: 14px;
115
+  }
116
+
117
+  #top,
118
+  #calendar.fc-unthemed {
119
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
120
+  }
121
+
122
+  #top {
123
+    background: #eee;
124
+    border-bottom: 1px solid #ddd;
125
+    padding: 0 10px;
126
+    line-height: 40px;
127
+    font-size: 12px;
128
+    color: #000;
129
+  }
130
+
131
+  #top .selector {
132
+    display: inline-block;
133
+    margin-right: 10px;
134
+  }
135
+
136
+  #top select {
137
+    font: inherit; /* mock what Boostrap does, don't compete  */
138
+  }
139
+
140
+  .left { float: left }
141
+  .right { float: right }
142
+  .clear { clear: both }
143
+
144
+  #calendar {
145
+    max-width: 900px;
146
+    margin: 40px auto;
147
+    padding: 0 10px;
148
+  }
149
+
150
+</style>
151
+</head>
152
+<body>
153
+
154
+  <div id='top'>
155
+
156
+    <div class='left'>
157
+
158
+      <div id='theme-system-selector' class='selector'>
159
+        Theme System:
160
+
161
+        <select>
162
+          <option value='bootstrap' selected>Bootstrap 4</option>
163
+          <option value='standard'>unthemed</option>
164
+        </select>
165
+      </div>
166
+
167
+      <div data-theme-system="bootstrap" class='selector' style='display:none'>
168
+        Theme Name:
169
+
170
+        <select>
171
+          <option value='' selected>Default</option>
172
+          <option value='cerulean'>Cerulean</option>
173
+          <option value='cosmo'>Cosmo</option>
174
+          <option value='cyborg'>Cyborg</option>
175
+          <option value='darkly'>Darkly</option>
176
+          <option value='flatly'>Flatly</option>
177
+          <option value='journal'>Journal</option>
178
+          <option value='litera'>Litera</option>
179
+          <option value='lumen'>Lumen</option>
180
+          <option value='lux'>Lux</option>
181
+          <option value='materia'>Materia</option>
182
+          <option value='minty'>Minty</option>
183
+          <option value='pulse'>Pulse</option>
184
+          <option value='sandstone'>Sandstone</option>
185
+          <option value='simplex'>Simplex</option>
186
+          <option value='sketchy'>Sketchy</option>
187
+          <option value='slate'>Slate</option>
188
+          <option value='solar'>Solar</option>
189
+          <option value='spacelab'>Spacelab</option>
190
+          <option value='superhero'>Superhero</option>
191
+          <option value='united'>United</option>
192
+          <option value='yeti'>Yeti</option>
193
+        </select>
194
+      </div>
195
+
196
+      <span id='loading' style='display:none'>loading theme...</span>
197
+
198
+    </div>
199
+
200
+    <div class='right'>
201
+      <span class='credits' data-credit-id='bootstrap-standard' style='display:none'>
202
+        <a href='https://getbootstrap.com/docs/3.3/' target='_blank'>Theme by Bootstrap</a>
203
+      </span>
204
+      <span class='credits' data-credit-id='bootstrap-custom' style='display:none'>
205
+        <a href='https://bootswatch.com/' target='_blank'>Theme by Bootswatch</a>
206
+      </span>
207
+    </div>
208
+
209
+    <div class='clear'></div>
210
+  </div>
211
+
212
+  <div id='calendar'></div>
213
+
214
+</body>
215
+</html>

+ 145
- 0
processes/fullcalendar/examples/time-zones.html View File

@@ -0,0 +1,145 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='../packages/core/main.css' rel='stylesheet' />
6
+<link href='../packages/daygrid/main.css' rel='stylesheet' />
7
+<link href='../packages/timegrid/main.css' rel='stylesheet' />
8
+<link href='../packages/list/main.css' rel='stylesheet' />
9
+<script src='../packages/core/main.js'></script>
10
+<script src='../packages/interaction/main.js'></script>
11
+<script src='../packages/daygrid/main.js'></script>
12
+<script src='../packages/timegrid/main.js'></script>
13
+<script src='../packages/list/main.js'></script>
14
+<script>
15
+
16
+  document.addEventListener('DOMContentLoaded', function() {
17
+    var initialTimeZone = 'local';
18
+    var timeZoneSelectorEl = document.getElementById('time-zone-selector');
19
+    var loadingEl = document.getElementById('loading');
20
+    var calendarEl = document.getElementById('calendar');
21
+
22
+    var calendar = new FullCalendar.Calendar(calendarEl, {
23
+      plugins: [ 'interaction', 'dayGrid', 'timeGrid', 'list' ],
24
+      timeZone: initialTimeZone,
25
+      header: {
26
+        left: 'prev,next today',
27
+        center: 'title',
28
+        right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
29
+      },
30
+      defaultDate: '2019-08-12',
31
+      navLinks: true, // can click day/week names to navigate views
32
+      editable: true,
33
+      selectable: true,
34
+      eventLimit: true, // allow "more" link when too many events
35
+      events: {
36
+        url: 'php/get-events.php',
37
+        failure: function() {
38
+          document.getElementById('script-warning').style.display = 'inline'; // show
39
+        }
40
+      },
41
+      loading: function(bool) {
42
+        if (bool) {
43
+          loadingEl.style.display = 'inline'; // show
44
+        } else {
45
+          loadingEl.style.display = 'none'; // hide
46
+        }
47
+      },
48
+
49
+      eventTimeFormat: { hour: 'numeric', minute: '2-digit', timeZoneName: 'short' },
50
+
51
+      dateClick: function(arg) {
52
+        console.log('dateClick', calendar.formatIso(arg.date));
53
+      },
54
+      select: function(arg) {
55
+        console.log('select', calendar.formatIso(arg.start), calendar.formatIso(arg.end));
56
+      }
57
+    });
58
+
59
+    calendar.render();
60
+
61
+    // load the list of available timezones, build the <select> options
62
+    // it's HIGHLY recommended to use a different library for network requests, not this internal util func
63
+    FullCalendar.requestJson('GET', 'php/get-time-zones.php', {}, function(timeZones) {
64
+
65
+      timeZones.forEach(function(timeZone) {
66
+        var optionEl;
67
+
68
+        if (timeZone !== 'UTC') { // UTC is already in the list
69
+          optionEl = document.createElement('option');
70
+          optionEl.value = timeZone;
71
+          optionEl.innerText = timeZone;
72
+          timeZoneSelectorEl.appendChild(optionEl);
73
+        }
74
+      });
75
+    }, function() {
76
+      // TODO: handle error
77
+    });
78
+
79
+    // when the timezone selector changes, dynamically change the calendar option
80
+    timeZoneSelectorEl.addEventListener('change', function() {
81
+      calendar.setOption('timeZone', this.value);
82
+    });
83
+  });
84
+
85
+</script>
86
+<style>
87
+
88
+  body {
89
+    margin: 0;
90
+    padding: 0;
91
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
92
+    font-size: 14px;
93
+  }
94
+
95
+  #top {
96
+    background: #eee;
97
+    border-bottom: 1px solid #ddd;
98
+    padding: 0 10px;
99
+    line-height: 40px;
100
+    font-size: 12px;
101
+  }
102
+  .left { float: left }
103
+  .right { float: right }
104
+  .clear { clear: both }
105
+
106
+  #script-warning, #loading { display: none }
107
+  #script-warning { font-weight: bold; color: red }
108
+
109
+  #calendar {
110
+    max-width: 900px;
111
+    margin: 40px auto;
112
+    padding: 0 10px;
113
+  }
114
+
115
+  .tzo {
116
+    color: #000;
117
+  }
118
+
119
+</style>
120
+</head>
121
+<body>
122
+
123
+  <div id='top'>
124
+
125
+    <div class='left'>
126
+      Timezone:
127
+      <select id='time-zone-selector'>
128
+        <option value='local' selected>local</option>
129
+        <option value='UTC'>UTC</option>
130
+      </select>
131
+    </div>
132
+
133
+    <div class='right'>
134
+      <span id='loading'>loading...</span>
135
+      <span id='script-warning'><code>php/get-events.php</code> must be running.</span>
136
+    </div>
137
+
138
+    <div class='clear'></div>
139
+
140
+  </div>
141
+
142
+  <div id='calendar'></div>
143
+
144
+</body>
145
+</html>

+ 113
- 0
processes/fullcalendar/examples/timegrid-views.html View File

@@ -0,0 +1,113 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='../packages/core/main.css' rel='stylesheet' />
6
+<link href='../packages/daygrid/main.css' rel='stylesheet' />
7
+<link href='../packages/timegrid/main.css' rel='stylesheet' />
8
+<link href='../packages/list/main.css' rel='stylesheet' />
9
+<script src='../packages/core/main.js'></script>
10
+<script src='../packages/interaction/main.js'></script>
11
+<script src='../packages/daygrid/main.js'></script>
12
+<script src='../packages/timegrid/main.js'></script>
13
+<script src='../packages/list/main.js'></script>
14
+<script>
15
+
16
+  document.addEventListener('DOMContentLoaded', function() {
17
+    var calendarEl = document.getElementById('calendar');
18
+
19
+    var calendar = new FullCalendar.Calendar(calendarEl, {
20
+      plugins: [ 'dayGrid', 'timeGrid', 'list', 'interaction' ],
21
+      header: {
22
+        left: 'prev,next today',
23
+        center: 'title',
24
+        right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
25
+      },
26
+      defaultDate: '2019-08-12',
27
+      navLinks: true, // can click day/week names to navigate views
28
+      editable: true,
29
+      eventLimit: true, // allow "more" link when too many events
30
+      events: [
31
+        {
32
+          title: 'All Day Event',
33
+          start: '2019-08-01',
34
+        },
35
+        {
36
+          title: 'Long Event',
37
+          start: '2019-08-07',
38
+          end: '2019-08-10'
39
+        },
40
+        {
41
+          groupId: 999,
42
+          title: 'Repeating Event',
43
+          start: '2019-08-09T16:00:00'
44
+        },
45
+        {
46
+          groupId: 999,
47
+          title: 'Repeating Event',
48
+          start: '2019-08-16T16:00:00'
49
+        },
50
+        {
51
+          title: 'Conference',
52
+          start: '2019-08-11',
53
+          end: '2019-08-13'
54
+        },
55
+        {
56
+          title: 'Meeting',
57
+          start: '2019-08-12T10:30:00',
58
+          end: '2019-08-12T12:30:00'
59
+        },
60
+        {
61
+          title: 'Lunch',
62
+          start: '2019-08-12T12:00:00'
63
+        },
64
+        {
65
+          title: 'Meeting',
66
+          start: '2019-08-12T14:30:00'
67
+        },
68
+        {
69
+          title: 'Happy Hour',
70
+          start: '2019-08-12T17:30:00'
71
+        },
72
+        {
73
+          title: 'Dinner',
74
+          start: '2019-08-12T20:00:00'
75
+        },
76
+        {
77
+          title: 'Birthday Party',
78
+          start: '2019-08-13T07:00:00'
79
+        },
80
+        {
81
+          title: 'Click for Google',
82
+          url: 'http://google.com/',
83
+          start: '2019-08-28'
84
+        }
85
+      ]
86
+    });
87
+
88
+    calendar.render();
89
+  });
90
+
91
+</script>
92
+<style>
93
+
94
+  body {
95
+    margin: 40px 10px;
96
+    padding: 0;
97
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
98
+    font-size: 14px;
99
+  }
100
+
101
+  #calendar {
102
+    max-width: 900px;
103
+    margin: 0 auto;
104
+  }
105
+
106
+</style>
107
+</head>
108
+<body>
109
+
110
+  <div id='calendar'></div>
111
+
112
+</body>
113
+</html>

+ 118
- 0
processes/fullcalendar/examples/week-numbers.html View File

@@ -0,0 +1,118 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+<meta charset='utf-8' />
5
+<link href='../packages/core/main.css' rel='stylesheet' />
6
+<link href='../packages/daygrid/main.css' rel='stylesheet' />
7
+<link href='../packages/timegrid/main.css' rel='stylesheet' />
8
+<link href='../packages/list/main.css' rel='stylesheet' />
9
+<script src='../packages/core/main.js'></script>
10
+<script src='../packages/interaction/main.js'></script>
11
+<script src='../packages/daygrid/main.js'></script>
12
+<script src='../packages/timegrid/main.js'></script>
13
+<script src='../packages/list/main.js'></script>
14
+<script>
15
+
16
+  document.addEventListener('DOMContentLoaded', function() {
17
+    var calendarEl = document.getElementById('calendar');
18
+
19
+    var calendar = new FullCalendar.Calendar(calendarEl, {
20
+      plugins: [ 'interaction', 'dayGrid', 'timeGrid', 'list' ],
21
+      header: {
22
+        left: 'prev,next today',
23
+        center: 'title',
24
+        right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
25
+      },
26
+      defaultDate: '2019-08-12',
27
+      navLinks: true, // can click day/week names to navigate views
28
+
29
+      weekNumbers: true,
30
+      weekNumbersWithinDays: true,
31
+      weekNumberCalculation: 'ISO',
32
+
33
+      editable: true,
34
+      eventLimit: true, // allow "more" link when too many events
35
+      events: [
36
+        {
37
+          title: 'All Day Event',
38
+          start: '2019-08-01'
39
+        },
40
+        {
41
+          title: 'Long Event',
42
+          start: '2019-08-07',
43
+          end: '2019-08-10'
44
+        },
45
+        {
46
+          groupId: 999,
47
+          title: 'Repeating Event',
48
+          start: '2019-08-09T16:00:00'
49
+        },
50
+        {
51
+          groupId: 999,
52
+          title: 'Repeating Event',
53
+          start: '2019-08-16T16:00:00'
54
+        },
55
+        {
56
+          title: 'Conference',
57
+          start: '2019-08-11',
58
+          end: '2019-08-13'
59
+        },
60
+        {
61
+          title: 'Meeting',
62
+          start: '2019-08-12T10:30:00',
63
+          end: '2019-08-12T12:30:00'
64
+        },
65
+        {
66
+          title: 'Lunch',
67
+          start: '2019-08-12T12:00:00'
68
+        },
69
+        {
70
+          title: 'Meeting',
71
+          start: '2019-08-12T14:30:00'
72
+        },
73
+        {
74
+          title: 'Happy Hour',
75
+          start: '2019-08-12T17:30:00'
76
+        },
77
+        {
78
+          title: 'Dinner',
79
+          start: '2019-08-12T20:00:00'
80
+        },
81
+        {
82
+          title: 'Birthday Party',
83
+          start: '2019-08-13T07:00:00'
84
+        },
85
+        {
86
+          title: 'Click for Google',
87
+          url: 'http://google.com/',
88
+          start: '2019-08-28'
89
+        }
90
+      ]
91
+    });
92
+
93
+    calendar.render();
94
+  });
95
+
96
+</script>
97
+<style>
98
+
99
+  body {
100
+    margin: 40px 10px;
101
+    padding: 0;
102
+    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
103
+    font-size: 14px;
104
+  }
105
+
106
+  #calendar {
107
+    max-width: 900px;
108
+    margin: 0 auto;
109
+  }
110
+
111
+</style>
112
+</head>
113
+<body>
114
+
115
+  <div id='calendar'></div>
116
+
117
+</body>
118
+</html>

BIN
processes/fullcalendar/fullcalendar-4.3.1.zip View File


+ 20
- 0
processes/fullcalendar/packages/bootstrap/LICENSE.txt View File

@@ -0,0 +1,20 @@
1
+Copyright (c) 2019 Adam Shaw
2
+
3
+Permission is hereby granted, free of charge, to any person obtaining
4
+a copy of this software and associated documentation files (the
5
+"Software"), to deal in the Software without restriction, including
6
+without limitation the rights to use, copy, modify, merge, publish,
7
+distribute, sublicense, and/or sell copies of the Software, and to
8
+permit persons to whom the Software is furnished to do so, subject to
9
+the following conditions:
10
+
11
+The above copyright notice and this permission notice shall be
12
+included in all copies or substantial portions of the Software.
13
+
14
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 8
- 0
processes/fullcalendar/packages/bootstrap/README.md View File

@@ -0,0 +1,8 @@
1
+
2
+# FullCalendar Bootstrap Plugin
3
+
4
+Bootstrap 4 theming for your calendar
5
+
6
+[View the docs &raquo;](https://fullcalendar.io/docs/bootstrap-theme)
7
+
8
+This package was created from the [FullCalendar monorepo &raquo;](https://github.com/fullcalendar/fullcalendar)

+ 36
- 0
processes/fullcalendar/packages/bootstrap/main.css View File

@@ -0,0 +1,36 @@
1
+.fc.fc-bootstrap a {
2
+  text-decoration: none;
3
+}
4
+
5
+.fc.fc-bootstrap a[data-goto]:hover {
6
+  text-decoration: underline;
7
+}
8
+
9
+.fc-bootstrap hr.fc-divider {
10
+  border-color: inherit;
11
+}
12
+
13
+.fc-bootstrap .fc-today.alert {
14
+  border-radius: 0;
15
+}
16
+
17
+.fc-bootstrap a.fc-event:not([href]):not([tabindex]) {
18
+  color: #fff;
19
+}
20
+
21
+.fc-bootstrap .fc-popover.card {
22
+  position: absolute;
23
+}
24
+
25
+/* Popover
26
+--------------------------------------------------------------------------------------------------*/
27
+.fc-bootstrap .fc-popover .card-body {
28
+  padding: 0;
29
+}
30
+
31
+/* TimeGrid Slats (lines that run horizontally)
32
+--------------------------------------------------------------------------------------------------*/
33
+.fc-bootstrap .fc-time-grid .fc-slats table {
34
+  /* some themes have background color. see through to slats */
35
+  background: none;
36
+}

+ 12
- 0
processes/fullcalendar/packages/bootstrap/main.d.ts View File

@@ -0,0 +1,12 @@
1
+// Generated by dts-bundle v0.7.3-fork.1
2
+// Dependencies for this module:
3
+//   ../../../../../@fullcalendar/core
4
+
5
+declare module '@fullcalendar/bootstrap' {
6
+    import { Theme } from '@fullcalendar/core';
7
+    export class BootstrapTheme extends Theme {
8
+    }
9
+    const _default: import("@fullcalendar/core").PluginDef;
10
+    export default _default;
11
+}
12
+

+ 83
- 0
processes/fullcalendar/packages/bootstrap/main.esm.js View File

@@ -0,0 +1,83 @@
1
+/*!
2
+FullCalendar Bootstrap Plugin v4.3.0
3
+Docs & License: https://fullcalendar.io/
4
+(c) 2019 Adam Shaw
5
+*/
6
+
7
+import { createPlugin, Theme } from '@fullcalendar/core';
8
+
9
+/*! *****************************************************************************
10
+Copyright (c) Microsoft Corporation. All rights reserved.
11
+Licensed under the Apache License, Version 2.0 (the "License"); you may not use
12
+this file except in compliance with the License. You may obtain a copy of the
13
+License at http://www.apache.org/licenses/LICENSE-2.0
14
+
15
+THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
17
+WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
18
+MERCHANTABLITY OR NON-INFRINGEMENT.
19
+
20
+See the Apache Version 2.0 License for specific language governing permissions
21
+and limitations under the License.
22
+***************************************************************************** */
23
+/* global Reflect, Promise */
24
+
25
+var extendStatics = function(d, b) {
26
+    extendStatics = Object.setPrototypeOf ||
27
+        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
28
+        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
29
+    return extendStatics(d, b);
30
+};
31
+
32
+function __extends(d, b) {
33
+    extendStatics(d, b);
34
+    function __() { this.constructor = d; }
35
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
36
+}
37
+
38
+var BootstrapTheme = /** @class */ (function (_super) {
39
+    __extends(BootstrapTheme, _super);
40
+    function BootstrapTheme() {
41
+        return _super !== null && _super.apply(this, arguments) || this;
42
+    }
43
+    return BootstrapTheme;
44
+}(Theme));
45
+BootstrapTheme.prototype.classes = {
46
+    widget: 'fc-bootstrap',
47
+    tableGrid: 'table-bordered',
48
+    tableList: 'table',
49
+    tableListHeading: 'table-active',
50
+    buttonGroup: 'btn-group',
51
+    button: 'btn btn-primary',
52
+    buttonActive: 'active',
53
+    today: 'alert alert-info',
54
+    popover: 'card card-primary',
55
+    popoverHeader: 'card-header',
56
+    popoverContent: 'card-body',
57
+    // day grid
58
+    // for left/right border color when border is inset from edges (all-day in timeGrid view)
59
+    // avoid `table` class b/c don't want margins/padding/structure. only border color.
60
+    headerRow: 'table-bordered',
61
+    dayRow: 'table-bordered',
62
+    // list view
63
+    listView: 'card card-primary'
64
+};
65
+BootstrapTheme.prototype.baseIconClass = 'fa';
66
+BootstrapTheme.prototype.iconClasses = {
67
+    close: 'fa-times',
68
+    prev: 'fa-chevron-left',
69
+    next: 'fa-chevron-right',
70
+    prevYear: 'fa-angle-double-left',
71
+    nextYear: 'fa-angle-double-right'
72
+};
73
+BootstrapTheme.prototype.iconOverrideOption = 'bootstrapFontAwesome';
74
+BootstrapTheme.prototype.iconOverrideCustomButtonOption = 'bootstrapFontAwesome';
75
+BootstrapTheme.prototype.iconOverridePrefix = 'fa-';
76
+var main = createPlugin({
77
+    themeClasses: {
78
+        bootstrap: BootstrapTheme
79
+    }
80
+});
81
+
82
+export default main;
83
+export { BootstrapTheme };

+ 91
- 0
processes/fullcalendar/packages/bootstrap/main.js View File

@@ -0,0 +1,91 @@
1
+/*!
2
+FullCalendar Bootstrap Plugin v4.3.0
3
+Docs & License: https://fullcalendar.io/
4
+(c) 2019 Adam Shaw
5
+*/
6
+
7
+(function (global, factory) {
8
+    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) :
9
+    typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) :
10
+    (global = global || self, factory(global.FullCalendarBootstrap = {}, global.FullCalendar));
11
+}(this, function (exports, core) { 'use strict';
12
+
13
+    /*! *****************************************************************************
14
+    Copyright (c) Microsoft Corporation. All rights reserved.
15
+    Licensed under the Apache License, Version 2.0 (the "License"); you may not use
16
+    this file except in compliance with the License. You may obtain a copy of the
17
+    License at http://www.apache.org/licenses/LICENSE-2.0
18
+
19
+    THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20
+    KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
21
+    WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
22
+    MERCHANTABLITY OR NON-INFRINGEMENT.
23
+
24
+    See the Apache Version 2.0 License for specific language governing permissions
25
+    and limitations under the License.
26
+    ***************************************************************************** */
27
+    /* global Reflect, Promise */
28
+
29
+    var extendStatics = function(d, b) {
30
+        extendStatics = Object.setPrototypeOf ||
31
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
32
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
33
+        return extendStatics(d, b);
34
+    };
35
+
36
+    function __extends(d, b) {
37
+        extendStatics(d, b);
38
+        function __() { this.constructor = d; }
39
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
40
+    }
41
+
42
+    var BootstrapTheme = /** @class */ (function (_super) {
43
+        __extends(BootstrapTheme, _super);
44
+        function BootstrapTheme() {
45
+            return _super !== null && _super.apply(this, arguments) || this;
46
+        }
47
+        return BootstrapTheme;
48
+    }(core.Theme));
49
+    BootstrapTheme.prototype.classes = {
50
+        widget: 'fc-bootstrap',
51
+        tableGrid: 'table-bordered',
52
+        tableList: 'table',
53
+        tableListHeading: 'table-active',
54
+        buttonGroup: 'btn-group',
55
+        button: 'btn btn-primary',
56
+        buttonActive: 'active',
57
+        today: 'alert alert-info',
58
+        popover: 'card card-primary',
59
+        popoverHeader: 'card-header',
60
+        popoverContent: 'card-body',
61
+        // day grid
62
+        // for left/right border color when border is inset from edges (all-day in timeGrid view)
63
+        // avoid `table` class b/c don't want margins/padding/structure. only border color.
64
+        headerRow: 'table-bordered',
65
+        dayRow: 'table-bordered',
66
+        // list view
67
+        listView: 'card card-primary'
68
+    };
69
+    BootstrapTheme.prototype.baseIconClass = 'fa';
70
+    BootstrapTheme.prototype.iconClasses = {
71
+        close: 'fa-times',
72
+        prev: 'fa-chevron-left',
73
+        next: 'fa-chevron-right',
74
+        prevYear: 'fa-angle-double-left',
75
+        nextYear: 'fa-angle-double-right'
76
+    };
77
+    BootstrapTheme.prototype.iconOverrideOption = 'bootstrapFontAwesome';
78
+    BootstrapTheme.prototype.iconOverrideCustomButtonOption = 'bootstrapFontAwesome';
79
+    BootstrapTheme.prototype.iconOverridePrefix = 'fa-';
80
+    var main = core.createPlugin({
81
+        themeClasses: {
82
+            bootstrap: BootstrapTheme
83
+        }
84
+    });
85
+
86
+    exports.BootstrapTheme = BootstrapTheme;
87
+    exports.default = main;
88
+
89
+    Object.defineProperty(exports, '__esModule', { value: true });
90
+
91
+}));

+ 1
- 0
processes/fullcalendar/packages/bootstrap/main.min.css View File

@@ -0,0 +1 @@
1
+.fc.fc-bootstrap a{text-decoration:none}.fc.fc-bootstrap a[data-goto]:hover{text-decoration:underline}.fc-bootstrap hr.fc-divider{border-color:inherit}.fc-bootstrap .fc-today.alert{border-radius:0}.fc-bootstrap a.fc-event:not([href]):not([tabindex]){color:#fff}.fc-bootstrap .fc-popover.card{position:absolute}.fc-bootstrap .fc-popover .card-body{padding:0}.fc-bootstrap .fc-time-grid .fc-slats table{background:0 0}

+ 6
- 0
processes/fullcalendar/packages/bootstrap/main.min.js View File

@@ -0,0 +1,6 @@
1
+/*!
2
+FullCalendar Bootstrap Plugin v4.3.0
3
+Docs & License: https://fullcalendar.io/
4
+(c) 2019 Adam Shaw
5
+*/
6
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@fullcalendar/core")):"function"==typeof define&&define.amd?define(["exports","@fullcalendar/core"],t):t((e=e||self).FullCalendarBootstrap={},e.FullCalendar)}(this,function(e,t){"use strict";var o=function(e,t){return(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var o in t)t.hasOwnProperty(o)&&(e[o]=t[o])})(e,t)};var r=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return function(e,t){function r(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}(t,e),t}(t.Theme);r.prototype.classes={widget:"fc-bootstrap",tableGrid:"table-bordered",tableList:"table",tableListHeading:"table-active",buttonGroup:"btn-group",button:"btn btn-primary",buttonActive:"active",today:"alert alert-info",popover:"card card-primary",popoverHeader:"card-header",popoverContent:"card-body",headerRow:"table-bordered",dayRow:"table-bordered",listView:"card card-primary"},r.prototype.baseIconClass="fa",r.prototype.iconClasses={close:"fa-times",prev:"fa-chevron-left",next:"fa-chevron-right",prevYear:"fa-angle-double-left",nextYear:"fa-angle-double-right"},r.prototype.iconOverrideOption="bootstrapFontAwesome",r.prototype.iconOverrideCustomButtonOption="bootstrapFontAwesome",r.prototype.iconOverridePrefix="fa-";var a=t.createPlugin({themeClasses:{bootstrap:r}});e.BootstrapTheme=r,e.default=a,Object.defineProperty(e,"__esModule",{value:!0})});

+ 33
- 0
processes/fullcalendar/packages/bootstrap/package.json View File

@@ -0,0 +1,33 @@
1
+{
2
+  "name": "@fullcalendar/bootstrap",
3
+  "version": "4.3.0",
4
+  "title": "FullCalendar Bootstrap Plugin",
5
+  "description": "Bootstrap 4 theming for your calendar",
6
+  "keywords": [
7
+    "calendar",
8
+    "event",
9
+    "full-sized"
10
+  ],
11
+  "homepage": "https://fullcalendar.io/",
12
+  "docs": "https://fullcalendar.io/docs/bootstrap-theme",
13
+  "bugs": "https://fullcalendar.io/reporting-bugs",
14
+  "repository": {
15
+    "type": "git",
16
+    "url": "https://github.com/fullcalendar/fullcalendar.git",
17
+    "homepage": "https://github.com/fullcalendar/fullcalendar"
18
+  },
19
+  "license": "MIT",
20
+  "author": {
21
+    "name": "Adam Shaw",
22
+    "email": "arshaw@arshaw.com",
23
+    "url": "http://arshaw.com/"
24
+  },
25
+  "copyright": "2019 Adam Shaw",
26
+  "peerDependencies": {
27
+    "@fullcalendar/core": "~4.3.0"
28
+  },
29
+  "main": "main.js",
30
+  "module": "main.esm.js",
31
+  "unpkg": "main.min.js",
32
+  "types": "main.d.ts"
33
+}

+ 20
- 0
processes/fullcalendar/packages/core/LICENSE.txt View File

@@ -0,0 +1,20 @@
1
+Copyright (c) 2019 Adam Shaw
2
+
3
+Permission is hereby granted, free of charge, to any person obtaining
4
+a copy of this software and associated documentation files (the
5
+"Software"), to deal in the Software without restriction, including
6
+without limitation the rights to use, copy, modify, merge, publish,
7
+distribute, sublicense, and/or sell copies of the Software, and to
8
+permit persons to whom the Software is furnished to do so, subject to
9
+the following conditions:
10
+
11
+The above copyright notice and this permission notice shall be
12
+included in all copies or substantial portions of the Software.
13
+
14
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 0
- 0
processes/fullcalendar/packages/core/README.md View File


Some files were not shown because too many files changed in this diff